我正在尝试确定每个方法在运行时使用了多少堆栈内存。为了完成这个任务,我设计了这个简单的程序,它会强制引发一个StackOverflowError
。
public class Main {
private static int i = 0;
public static void main(String[] args) {
try {
m();
} catch (StackOverflowError e) {
System.err.println(i);
}
}
private static void m() {
++i;
m();
}
}
打印一个整数,告诉我 m()
函数被调用了多少次。我手动设置了 JVM 的堆栈大小(-Xss
VM 参数)为不同的值(128k、256k、384k),得到了下面的结果:
stack i delta
128 1102
256 2723 1621
384 4367 1644
delta是由我计算的,它表示当前行与上一行i值之间的差。正如预期的那样,它是固定的。问题就在这里。我知道栈大小内存增量是128k,这意味着每次调用大约使用80个字节的内存(这似乎夸张了)。
在BytecodeViewer中查找m()
,我们可以得到一个最大深度为2的堆栈。我们知道这是一个静态方法,没有this
参数传递,并且m()
没有参数。我们还必须考虑返回地址指针。因此,每个方法调用应该使用大约3 * 8 = 24个字节(我假设每个变量占用8个字节,当然可能完全错误。是吗?)。即使比这多一点,比如说48字节,我们仍然远远低于80字节的值。
我以为可能与内存对齐有关,但事实上,在那种情况下,我们会得到大约64或128个字节的值,我想。
我正在64位Windows7操作系统下运行64位JVM。
我做出了几个假设,其中一些可能完全错误。如果是这种情况,我很乐意听取建议。
在任何人开始问我为什么要这样做之前,我必须坦白一点..