本文为<<深入理解java虚拟机>>一书的学习笔记
我们知道,在java管理的内存区域中,共分为5个部分。如下图:
虚拟机栈
虚拟机栈是线程私有的,它描述的是java方法执行的内存模型:每一个方法在执行期间都会创建一个栈帧用来存储局部变量表,操作数栈,动态链接,方法出口等信息。
我们重点说说局部变量表。局部变量表里面存放的是各种基本类型(int,char等等)和引用类型。当然引用类型并不是对象本身,而是指向数据存储位置的一个指针。
每一个线程启动的时候,jvm都会为它创建一个对应的虚拟机栈,而每一个方法都会有一个栈帧。我们看下面的例子
public void m1(int args){
int b=10;
Person p=new Person();
Object o=new Object();
m2();
....
}
public void m2(){
.....
}
当程序执行到m2内部的时候
虚拟机栈大致内容如下
当然当m2方法执行完毕后,它所代表的栈帧就会消失,此时的栈顶就是m1所代表的按个栈帧。
同时b和args里面直接存放具体数值,而p与o为引用变量,里面存放的是堆的一个地址。
在虚拟机栈里面,有两种异常状况。
1 如果请求的栈深度大于虚拟机所允许的深度,将会跑出StackOverflowError。
2 现在的虚拟机栈一般都可以动态扩展,如果扩展时申请不到足够的内存就会抛出OutOfMemoryError异常。
本地方法栈
它与虚拟机的区别在于,虚拟机栈为java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用的Native方法服务。
当然本地方法栈也会抛出StackOverflowError与OutOfMemoryError。
java堆
java堆是java虚拟机管理的最大一块内存。且被所有线程共享。这块区域在虚拟机启动时就会创建。它存在的唯一目的就是存放对象。
另一方面java堆也是垃圾收集管理的主要区域。关于垃圾收集与管理,我们后面再说。
方法区
方法区也是各个线程所共享的。它存储已被虚拟机加载的类信息,常亮,静态变量,即时编译器编译后的代码等等。
运行时常量池
运行时常量池是方法区的一部分。Class文件里除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期间上次的各种字面量和符号引用。
程序计数器
可以看做是当前线程所执行的字节码的行号指示器。
参考资料:
深入理解java虚拟机 第二章