Java中System.gc()执行后WeakReference.get()返回值差异原因
WeakReference.get()返回null的场景差异问题
测试代码
以下为验证弱引用get()返回逻辑编写的测试代码:
String string = new String("abc"); WeakReference<String> wi = new WeakReference<>(string); WeakReference<String> sr = new WeakReference<>(new String("another")); System.out.println(wi.get()); System.out.println(sr.get()); System.gc(); System.out.println("After gc() wi = " + wi.get()); System.out.println("After gc() sr =: " + sr.get());
运行结果
代码执行输出如下:
abc another After gc() wi = abc After gc() sr =: null
核心原因
该差异和引用指向的对象类型(String/Integer/自定义类)无关,核心判定逻辑是目标对象是否存在GC Roots可达的强引用:
- JVM对弱引用的回收规则是固定的:当一个对象仅被弱引用持有,不存在任何从GC Roots出发的强引用链能到达该对象时,GC触发时就会回收该对象,对应弱引用的get()方法返回null。
wi关联的new String("abc")对象存在强引用:代码第一行声明的局部变量string是强引用,存储在当前方法栈的局部变量表中,属于GC Roots的一部分。在当前代码块执行结束前,这个强引用一直存在,目标对象始终处于强可达状态,因此GC不会回收该对象,调用wi.get()始终能拿到实例。sr关联的new String("another")对象无留存强引用:该对象创建时没有赋值给任何强引用变量,实例初始化完成后就仅被弱引用sr持有,不存在任何GC Roots可达的强引用链,因此GC触发时会直接回收该对象,sr.get()返回null。
补充验证:如果在调用
System.gc()前手动执行string = null;断开强引用,GC执行后wi.get()同样会返回null。
误区排除:该现象和字符串常量池、Integer缓存等特殊机制无关,替换为自定义类得到一致结果已经可以排除这类因素的干扰。
内容的提问来源于stack exchange,提问作者gongliming7
相关产品推荐
相关产品推荐

