我的app很头疼,
有时候很容易记混淆,搞不懂哪个是内存不足才会回收,哪个随时可能被回收 哪个调用gc之后一定会回收,哪个是安卓推荐使用的..
那么先从安卓的源码开始,打开源码发现有一段注释证明软引用不推荐使用,
SoftReference
SoftReference
的类注释:
* Soft reference objects, which are cleared at the discretion of the garbage
* collector in response to memory demand.
*
* <p> Suppose that the garbage collector determines at a certain point in time
* that an object is <a href="package-summary.html#reachability">softly
* reachable</a>. At that time it may choose to clear atomically all soft
* references to that object and all soft references to any other
* softly-reachable objects from which that object is reachable through a chain
* of strong references. At the same time or at some later time it will
* enqueue those newly-cleared soft references that are registered with
* reference queues.
*
* <p> All soft references to softly-reachable objects are guaranteed to have
* been cleared before the virtual machine throws an
OutOfMemoryError . Otherwise no constraints are placed upon the
* time at which a soft reference will be cleared or the order in which a set
* of such references to different objects will be cleared. Virtual machine
* implementations are, however, encouraged to bias against clearing
* recently-created or recently-used soft references.
*
* <h3>Avoid Soft References for Caching</h3>
* In practice, soft references are inefficient for caching. The runtime doesn't
* have enough information on which references to clear and which to keep. Most
* fatally, it doesn't know what to do when given the choice between clearing a
* soft reference and growing the heap.
*
* <p>The lack of information on the value to your application of each reference
* limits the usefulness of soft references. References that are cleared too
* early cause unnecessary work; those that are cleared too late waste memory.
*
* <p>Most applications should use an {@code android.util.LruCache} instead of
* soft references. LruCache has an effective eviction policy and lets the user
* tune how much memory is allotted.
*
* @author Mark Reinhold
* @since 1.2
*/
从上面有几个关键英文单词
Avoid Soft References for Caching
Most applications should use an {@code android.util.LruCache}
避免使用, 大部分应用应该使用LruCache
这里说的很清楚,不是绝对,一定,不是必须使用LruCache, fragment的存储缓存是无法知道大小的,LruCache 我是不知道怎么整,翻阅了百度也找不到任何答案,测量obj大小的方法 也被谷歌删除了.fragment的存储到底用哪个好呢?
避免使用缓存缓存的软引用
*实际上,软引用对于缓存是无效的。运行时没有足够的信息,说明哪些要明确,哪些要保留。最
*致命的
All soft references to softly-reachable objects are guaranteed to have
* been cleared before the virtual machine throws an
* <code>OutOfMemoryError</code>. O
guaranteed
保证
虚拟机保证在内存不足之前清理所有Soft references,我英语不好,应该是说内存不足的时候才会清除?还是说内存不足的时候一定会清除,但是不足的时候清除不清除呢?
WeakReference
注释:
/**
* Weak reference objects, which do not prevent their referents from being
* made finalizable, finalized, and then reclaimed. Weak references are most
* often used to implement canonicalizing mappings.
*
* <p> Suppose that the garbage collector determines at a certain point in time
* that an object is weakly reachable</a>. At that time it will atomically clear all weak references to
* that object and all weak references to any other weakly-reachable objects
* from which that object is reachable through a chain of strong and soft
* references. At the same time it will declare all of the formerly
* weakly-reachable objects to be finalizable. At the same time or at some
* later time it will enqueue those newly-cleared weak references that are
* registered with reference queues.
*
*/
软引用验证,只有内存不足才会回收 如果回收了还是内存不足就鸡鸡了,这很适合用在fragment的缓存,因为内存还足够没必要回收.
下面是我测试SoftReference的程序,用eclipse测试最好不过了,调整最大内存为2M,初始化内存也为2M
改配置感受 紧
Launch configurations for 'TestReference.java' ->Argments选项卡 Vm argments里面填写参数-Xmx2m -xms2m
测试软引用源代码
。
/**
*Launch configurations for 'TestReference.java' ->Argments选项卡 Vm argments里面填写参数-Xmx2m -xms2m
* @param args
*/
public static void main(String[] args) {
Object referent = new Object();
java.util.List<String[]> list = new ArrayList<>();
SoftReference<Object> softRerference = new SoftReference<Object>(referent);
assertNotNull(softRerference.get());
referent = null;
int count = 0;
while (softRerference.get()!=null) {
System.out.println("obj!=null count:" + count);
count++;
String[] current=new String[1000];
System.out.println("isempty:"+(softRerference.get()==null));
list.add(current);
for (int i = 0; i < current.length; i++) {
current[i]=i+"";
}
if(count%1000==0){
}
}
System.out.println("obj is recycle");
/**
* soft references 只有在 jvm OutOfMemory 之前才会被回收, 如果回收后发现还是内存不足,那么蛋蛋了
* Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.Arrays.copyOfRange(Arrays.java:3664)
at java.lang.String.<init>(String.java:207)
at java.lang.StringBuilder.toString(StringBuilder.java:407)
at TestReference.main(TestReference.java:29)
*
*/
}
弱引用测试
static class MyObj {
public MyObj(int no) {
this.no = no;
}
public String[] getCurrent() {
return current;
}
public void setCurrent(String[] current) {
this.current = current;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
String[] current = new String[1000];
int no;
@Override
protected void finalize() throws Throwable {
System.out.println("from:"+no+" :我被回收了我是hasCode:" + hashCode());
super.finalize();
}
}
/**
*Launch configurations for 'TestReference.java' ->Argments选项卡 Vm argments里面填写参数-Xmx2m -xms2m
* @param args
*/
public static void main(String[] args) {
Object referent = new Object();
java.util.List<WeakReference<MyObj>> list = new ArrayList<>();
int loopindex = 0;
System.err.println("=================================弱引用测试=================================");
while(loopindex<200){
String[] current=new String[500];
for (int i = 0; i < current.length; i++) {
current[i]=i+"";
}
MyObj obj=new MyObj(loopindex);
obj.setCurrent(current);
list.add(new WeakReference<TestReference.MyObj>(obj));
if(loopindex%5==0&&loopindex>0){
System.out.println("start================"+loopindex+"================================");
System.out.println("即将调用调用主动gc,刚刚放进去的对象index:"+loopindex+"还在否:"+list.get(loopindex).get());
System.gc();
System.out.println("主动调用gc");
System.out.println("调用之后刚刚放进去的对象index:"+loopindex+"还在否:"+list.get(loopindex).get());
System.out.println("调用之后第一个还在否:"+list.get(0).get());
System.out.println("end================"+loopindex+"================================");
}
loopindex++;
}
/**
*
*/
}
输出结果:
=================================弱引用测试=================================
start================5================================
即将调用调用主动gc,刚刚放进去的对象index:5还在否:TestReference$MyObj@6d06d69c
主动调用gc
调用之后刚刚放进去的对象index:5还在否:TestReference$MyObj@6d06d69c
调用之后第一个还在否:null
end================5================================
from:2 :我被回收了我是hasCode:1113044619
from:3 :我被回收了我是hasCode:1284526257
from:4 :我被回收了我是hasCode:1219485179
from:1 :我被回收了我是hasCode:229464714
from:0 :我被回收了我是hasCode:1915835994
start================10================================
即将调用调用主动gc,刚刚放进去的对象index:10还在否:TestReference$MyObj@7852e922
主动调用gc
调用之后刚刚放进去的对象index:10还在否:TestReference$MyObj@7852e922
调用之后第一个还在否:null
end================10================================
from:9 :我被回收了我是hasCode:1022006645
from:8 :我被回收了我是hasCode:178046742
from:7 :我被回收了我是hasCode:1837278661
from:6 :我被回收了我是hasCode:368688553
from:5 :我被回收了我是hasCode:1829164700
start================15================================
即将调用调用主动gc,刚刚放进去的对象index:15还在否:TestReference$MyObj@4e25154f
主动调用gc
from:10 :我被回收了我是hasCode:2018699554
调用之后刚刚放进去的对象index:15还在否:TestReference$MyObj@4e25154f
from:14 :我被回收了我是hasCode:2102444894
调用之后第一个还在否:null
from:13 :我被回收了我是hasCode:295178133
from:12 :我被回收了我是hasCode:1774992622
from:11 :我被回收了我是hasCode:822136971
end================15================================
start================20================================
测试调节初始化数组大小为500 或者1000 如果是1千,我们发现即使没有调用System.gc()它已经开始进行回收了,也就是稍微吃紧就会回收了,而改成500之后 第一次loop,没有回收等到调用gc执行完毕start-end逻辑后, 3 ,4,2,1,0都一个一个被回收了,从这里的消息也可以看出,回收虽然不会超大概率回收刚刚放进去的,但是也不会百分百先回收第一个,或者也许是日志打印和本地native消息不同步导致的??
看上去好像差不多,意思是在不定期检测 弱引用对象,那些不可达的进行清除.
但是没有说内存不足``oom```之前弱引用对象就一定已经被清除了。。
WeakHashMap
对于集合来说,用WeakHashMap
也许更方便
软引用 手动调用System.gc
回收的时候软引用不一定会回收, 但是弱引用一定会被回收,所以你是打算用软引用还是用弱引用呢?
为了加深印象避免混淆,我打算给他们取一个名字 ,软足 和 弱鸡g ,也就是软引用是内存不足才会瘦 ,弱引用 gc马上会瘦
参考链接
http://san-yun.iteye.com/blog/1683558
https://baijiahao.baidu.com/s?id=1578867464445861486&wfr=spider&for=pc
http://www.cnblogs.com/skywang12345/p/3154474.html
测试案例参考
http://wiseideal.iteye.com/blog/1469295