[JVM]请问a = null,对于垃圾回收,有效果吗
如A a = new A();
.........
最后用完了 a= null;
[JVM]请问a = null,对于垃圾回收,有效果吗
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
6条回答 默认 最新
rednaxelafx 2009-06-07 16:37关注随便说个,随便听听……
各个JVM的实现方式不同,设null有没有影响也是不一定的。也就是说如果想确定一用完某个对象马上就释放其占用的内存空间,没有在各JVM上都通用的办法。于是就可以看些有趣的例子了。许多JVM的实现都会在合适的时候把字节码即时编译为机器码,在这过程中有可能做方法内联、无用代码消除等诸多优化。看这个假象例子:
[code="java"]public class Foo {
public void bar() {
A a = new A();
a.doTask(this);
}
}public class Quux {
public void baz() {
Foo foo = getFoo();
for (int i = 0; i < 100000; i++) {
foo.bar();
}
doSomeLongTask();
}private void doSomeLongTask() { // ... }}[/code]
Foo.bar()是一个小方法,而且在一个高强度的循环里被调用,则如果Quux.bar()被多调用几次,在某些JVM上就有机会看到实际运行的Quux.baz()代码变成了类似这样:
[code="java"]public void baz() {
Foo foo = getFoo();
if (Foo.class == foo.getClass()) { // guarded inline method cache
for (int i = 0; i < 100000; i++) {
A a = new A();
a.doTask(foo);
}
} else {
for (int i = 0; i < 100000; i++) {
foo.bar(); // fallback
}
}
doSomeLongTask();
}[/code]
甚至有可能进一步把A.doTask()也内联进来。
这样,a这个引用的作用域就跑到Quux.baz()里了。如果原先在Foo.bar()里写上了a = null;会怎样呢?
1、这句有可能原本就被优化掉了(因为这是对变量的赋值,而赋值后没有代码再读取过这个值)。反正方法调用结束后局部变量自然消失,设不设null都一样 << 前提是没内联优化。
2、这句没有一开始就被优化掉,而是被内联来到了Quux.baz()里:
[code="java"]public void baz() {
Foo foo = getFoo();
if (Foo.class == foo.getClass()) { // guarded inline method cache
for (int i = 0; i < 100000; i++) {
A a = new A();
a.doTask(foo);
a = null;
}
} else {
for (int i = 0; i < 100000; i++) {
foo.bar(); // fallback
}
}
doSomeLongTask();
}[/code]
看起来似乎很有用对吧?似乎在Quux.baz()的中间就把a设为了null,减少了一个对new A()得到的对象的引用?
如果JVM有能力把代码内联进来,也就不差在计算变量的存活范围和消除无用代码了。于是a = null;照样被当作无用代码消除掉,同时也可以得知a变量的存货范围只有for循环里的两行,所以Quux.baz()的其它局部变量可以在其它时间占用a所在的寄存器或栈空间。设不设null还是一样。如果在执行doSomeLongTask()时进行GC,即时不设置a为null,GC也会认为没有那个引用,不影响可能的回收。但如果没那么多优化,JVM就老老实实的执行没优化过的字节码呢?
[code="java"]public void baz() {
Foo foo = getFoo();
A a = new A();
a.doTask(foo);
a = null;
doSomeLongTask();
}[/code]
JVM可能会老老实实把全部局部变量都放在栈帧上,可能不消除无用代码,可能在doSomeLongTask()的执行过程中进行了GC。如果a没有被手工设为null,则GC的时候会看到栈上还存在一个指向new A()得到的对象的引用,于是认为该对象还是活的。手工设置null最有用的场景恐怕就是在特定JVM上配合System.gc()来用了吧 =v=
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报