Java 您是否通过在方法中将变量声明为属性来保存垃圾收集器的工作?
比较 到Java 您是否通过在方法中将变量声明为属性来保存垃圾收集器的工作?,java,performance,memory,Java,Performance,Memory,比较 到 假设大量调用了addToA方法,那么您是否使用第二个方法来节省垃圾收集器的工作(并加快程序的速度)?在堆栈上分配局部变量 在这种情况下 public class Core { int b; public int addToA(int a) { b = a + 2; return b; } } public int addToA(int a) { int b = a + 2; return b; } 当该方法
假设大量调用了
addToA
方法,那么您是否使用第二个方法来节省垃圾收集器的工作(并加快程序的速度)?在堆栈上分配局部变量
在这种情况下
public class Core {
int b;
public int addToA(int a) {
b = a + 2;
return b;
}
}
public int addToA(int a) {
int b = a + 2;
return b;
}
当该方法返回并弹出包含b
的堆栈帧时,它所占用的内存将自动恢复。不涉及垃圾收集器
在这种情况下
public class Core {
int b;
public int addToA(int a) {
b = a + 2;
return b;
}
}
public int addToA(int a) {
int b = a + 2;
return b;
}
b
将在为核心
对象保留的堆空间中分配。只有在收集了Core
后,才会对其进行垃圾收集
假设多次调用addToA方法,您是否保存
垃圾收集器通过使用第二个
一个
据我所知,你不会得到任何东西
请阅读文章,了解何时执行和何时不执行建议的示例。局部变量始终在堆栈上声明(因此不要与类成员混淆,它们在堆上)。垃圾收集器是负责堆内存的工具。所以两者完全不同。堆栈上的变量将随着作用域的离开而弹出(例如:返回的方法)。在您的示例中,
b
将在堆栈上,而不是在堆中,因此当堆栈帧弹出时,它将被回收。总承包商没有任何节约。这适用于方法中的所有局部变量
如果您分配了一个对象,而不仅仅是一个变量,那么就会涉及堆。因为您分配的b
值是一个原语,所以在这里不起作用
但例如,假设是:
public class Core {
int b;
public int addToA(int a) {
b = a + 2;
return b;
}
}
现在,堆栈上有一个变量,它保存对堆中对象的引用。从理论上讲,您可以通过重用其中一个来节省GC工作(以更高的内存使用为代价)。但是您必须重用StringBuilder
,而不是变量。实际上,将对象重置为空白状态所需的努力、复杂性和(再次)更高的持续内存使用可能会抵消任何节省
(请注意,有些JVM可能会做一些您可能会干扰的聪明事情,比如将对象放在堆栈上,并将它们移动到堆中,如果方法调用终止后仍然存在对对象的引用。我知道V8在JavaScript世界中就是这样做的,V8从Sun的JVM中获得了很多灵感,所以……)
javap-vcore
救命
现场版本分解为:
StringBuilder sb = new StringBuilder();
0: aload_0
1: iload_1
2: iconst_2
3: iadd
4: putfield #2 // Field b:I
7: aload_0
8: getfield #2 // Field b:I
11: ireturn
局部变量版本分解为:
StringBuilder sb = new StringBuilder();
0: aload_0
1: iload_1
2: iconst_2
3: iadd
4: putfield #2 // Field b:I
7: aload_0
8: getfield #2 // Field b:I
11: ireturn
纯英语的局部变量版本:
ints
在
addToA
调用期间没有执行堆内存分配。一切都是在堆栈上完成的。垃圾收集器停止。否,b
将在堆栈上分配,当方法返回时,堆栈帧弹出时,内存将被清除。@SotiriosDelimanolis:这是一个答案,不是注释。:-)@T.J.Crowder我对这些细节不在行,我不想弄错什么。@SotiriosDelimanolis:看来你会得到足够的支持票,让它变得值得。你的不存在的答案得到了我精神上的支持票。可能有人怀有恶意,例如,如果他们不喜欢你在其他地方的评论。不幸的是,它发生了。