以下是《深入理解Java虚拟机》部分内容:
java虚拟机内存主要分为5部分,分别是程序计数器,虚拟机栈,本地方法栈,堆,方法区,下面将逐一详细描述。
1,程序计数器
线程私有,即每个线程都会有一个,线程之间互不影响,独立存储。
代表着当前线程所执行字节码的行号指示器。
2,虚拟机栈
线程私有,其生命周期和线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧子啊虚拟机栈中入栈到出栈的过程。
局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。局部变量表的容量以变量槽slot为最小单位,每个slot都能够存放基础类型数据,reference或returnAddress类型的数据。
java程序使用对象就是使用reference类型的数据来操作堆上的对象。但是reference类型在虚拟机规范中只规定了一个指向对象的引用,并没有定义这个引用应该通过何种方式去定位,访问堆中的对象的具体位置。所以对象访问方式取决于虚拟机的实现,目前主流的实现是使用句柄和直接指针两种方式。
如果使用句柄的话,堆中会划分一块内存来作为句柄池,reference中存储的是对象的句柄地址,句柄中则包含了对象实例数据和类型数据各自的具体地址信息。
使用直接指针的话,reference中存储的就是对象地址,
3,本地方法栈
线程私有,本地方法栈和虚拟机栈发挥的作用是相似的,只不过虚拟机栈为虚拟机执行Java方法服务,而本地方法栈为虚拟机用到的Native方法服务。
4,堆
线程共享,用来存放对象实例,也是垃圾收集的主要区域。
5,方法区(非堆)
线程共享,用来存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
该区域的内存回收目标主要是针对常量池的回收和对类型的卸载。
逻辑上方法区是堆的一部分。永久代是方法区的实现方式,但是不是每个虚拟机都有永久代的。1.8之后方法区被元空间替代了。
6,元空间
JDK1.7中,存储在永久代的部分数据就已经转移到了Java堆或者是 Native堆。但永久代仍存在于JDK1.7中,并没完全移除,譬如符号引用(Symbols)转移到了native堆;字面量(interned strings)转移到了java堆;类的静态变量(class statics)转移到了java堆。
元空间的本质和永久代类似,都是对JVM规范中方法区的实现。元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。