Java堆栈为每个方法调用创建新帧,但是这个帧是否在堆栈上占用内存?
澄清我的问题:
public void oneWay()
{
System.out.println("start");
get1();
}
private void get1()
{
System.out.println("get1");
get2();
}
private void get2()
{
System.out.println("get2");
}
输出与:
相同public void anotherWay()
{
System.out.println("start");
System.out.println("get1");
System.out.println("get2");
}
但是第二个代码片段在堆栈上占用更多内存还是相等?简而言之,堆栈帧会记忆吗?
编辑:堆叠帧占用多少内存? Sun是否有任何规范,现在是Oracle?
答案 0 :(得分:4)
是的,很自然。这就是为什么如果嵌套太深,你会得到堆栈溢出的原因。如果您发现需要为线程设置更大(或更小)的堆栈,则可以使用-Xss
命令行开关来修改堆栈大小。
specification似乎为实现提供了很大的自由,所以总而言之,你不能真正依赖堆栈帧大小。
答案 1 :(得分:1)
您可以将当前线程堆栈上的堆栈帧数计算为:
Thread.currentThread().getStackTrace().length
在您的情况下,在get2
中获取此值会比直接在oneWay
(大于2)中获得更大的值。确切的值取决于您调用的代码oneWay
中的位置。
虽然其他一些编程语言不一定为每个函数调用创建一个堆栈帧,但Java总是如此。 JVM规范在§2.6中明确指出“每次调用方法时都会创建一个新帧”。以后“框架从Java虚拟机堆栈分配”。因此在Java中,每个方法调用都会设置一个堆栈帧,每个堆栈帧都会占用堆栈上的内存。即使在调用无效的函数时,虚拟机也需要一定量的内存来跟踪堆栈帧本身。
答案 2 :(得分:1)
如Inside the Java Virtual Machine中所述,
堆栈帧有三个部分:局部变量,操作数堆栈和帧数据。局部变量和操作数堆栈的大小(以单词计量)取决于每个单独方法的需要。这些大小在编译时确定,并包含在每个方法的类文件数据中。帧数据的大小取决于实现。
当Java虚拟机调用Java方法时,它会检查类数据以确定方法在局部变量和操作数堆栈中所需的字数。它为方法创建了适当大小的堆栈帧,并将其推送到Java堆栈。