我想再次学习Java,因为我几年前就离开了它。阅读一本书时,我很难理解Java是如何在堆和堆栈中分配内存的。
这就是我所理解的--我将试着用例子来谈论它。
class TestA {
int a;
void methodA(int b) {
a = b;
}
int getA() {
return a;
}
}
这是一个显示不同情况的示例类。这是我的主要:
int b = 3;
TestA obj = new TestA();
obj.methodA(b);
obj.getA();
那会发生什么呢?
## BEGIN
堆栈-占用一些内存作为主要功能。
堆空
## int b= 3
堆栈-为主函数->取一些内存,这里有b。
堆空
## TestA obj =新TestA()
堆栈-为主函数->取一些内存,这里有b和对TestA的引用。
堆-为int a取一些内存。
## obj.methodA(b);
堆栈-为主函数->取一些内存,这里有b和对TestA的引用。
堆-为int a取一些内存,为methodA取另一个内存。
## execute methodA(int b)
堆栈-为主函数->取一些内存,这里有b和对TestA的引用,并在这里取methodA() ->的内存,我们在这个函数中使用了b
堆-为int a取一些内存,为methodA取另一个内存。
我们有:
heap
中的作用域值
是对的吗?
发布于 2012-01-10 14:42:26
首先,请记住堆也将具有类的Class
实例(以及其他几个实例)。
回复:
TestA obj =新的TestA()堆栈-为主函数->取一些内存,这里有b和对TestA的引用
堆-为int a取一些内存。
作为为a
实例分配的内存的一部分,a
将在堆中而不是堆栈上。b
和obj
在堆栈上,在进入main
时就被分配了(呃,我认为这就是发生这种情况的时候;可能在遇到程序流中的声明之前,JVM不会为它们保留堆栈空间,但现在我们进入了JVM的内部)。堆还包含TestA
的实例。(请记住,变量obj
与它指向TestA
实例的内容完全不同;这些事情都需要内存。)
还请记住,堆栈将包含函数调用的返回地址。例如,当main
调用methodA
时,methodA
返回时应该返回的地址也在堆栈上。
还将为异常处理分配各种堆栈结构。
以上主要是理论上的,头脑。JVM是欢迎进行优化的,它们也是这样做的(HotSpot是一个彻底优化的JVM)。@Voo指出,例如,JVM很可能会将对象放到堆栈上,如果它们能够检测到的话(例如,当对象实例仅在方法中使用时,JVM的字节码分析表明,当方法退出时,不可能有对对象的突出引用)。
发布于 2012-01-10 14:43:02
尽管Java被指定为堆栈机器,但实际上它并不是以这种方式实现的,因此在实际JVM中,堆栈的大小只在退出或进入方法时发生变化。
堆从不是空的-它包括Object.class
等对象,这些对象在启动main
之前由引导类加载器实例化。
所有操作(如new ClassName(...)
在堆*中分配空间)和所有变量声明(int x
、Object ref
)都指定,当输入封闭函数**时,应该在堆栈上留出空间。
*-参见https://stackoverflow.com/a/8690592/20394中有关优化的警告
** -再次优化可以导致堆栈槽被共享。
发布于 2012-08-20 07:32:51
默认情况下,在堆上分配所有对象。但是,有一些编译器优化允许在堆栈上分配对象(或者一起避免分配)。特别是,在java 6中,转义分析允许这样做。
https://stackoverflow.com/questions/8804937
复制相似问题