Java 堆和栈到底要怎么理解
2018-01-07
这要从操作系统里进程的内存结构说起了。。。
下图是linux 中一个进程的虚拟内存分布:
以32位地址操作系统为例,一个进程可拥有的虚拟内存地址范围为0-2^32。分为两部分,一部分留给kernel使用(kernel virtual memory),剩下的是进程本身使用, 即图中的process virtual memory。
普通Java 程序使用的就是process virtual memory.
上图中最顶端的一部分内存叫做user stack. 这就是题目问的 stack. 中间有个 runtime heap。就是题目中的heap. 他们的名字和数据结构里的stack 和 heap 几乎每啥关系。
注意在上图中,stack 是向下生长的; heap是向上生长的。
当程序进行函数调用时,每个函数都在stack上有一个 call frame。
比如对于以下程序,
public void foo(){
//do something...
println("haha"); // <<<=== 在这儿设置breakpoint 1}public void bar(){
foo();}main(){
bar();
println("hahaha"); // <<<=== 在这儿设置 breakpoint 2}
当程序运行到breakponit1时,user stack 里会有三个frame
|
| main 函数的 frame
-------------------
|
| bar 函数的 frame
-------------------<<<=== %ebp
|
| foo 函数的 frame
------------------- <<<===%esp
其中 esp 和 ebp 都是寄存器。 esp 指向stack 的顶(因为stack 向下生长,esp会向下走); ebp 指向当前frame的边界。
当程序继续执行到brekapoing 2的时候stack 大概是这样的: