jvm内存模型
Math类
package com.duohoob.jvm.test;
@SuppressWarnings("unused")
public class Math {
private final int i = 123;
private static String str = "abc";
public int compute() {
int a = 1;
int b = 2;
int c = (a + b)* 10;
return c;
}
public static void main(String[] args) {
Math math = new Math();
int compute = math.compute();
System.out.println(compute);
}
}
Java虚拟机组成部分
内存模型
栈
当一个线程开始执行,jvm会为它从栈中分配一块专属的内存空间,
叫线程栈。
栈帧
当线程开始执行方法,会在线程栈内分配方法专属的内存区域,
叫做栈帧。
局部变量表
栈帧中的局部变量表,用于存放方法内部的局部变量,例如a、b、c,
main中的局部变量math对象,
在局部变量表中存储的是math对象在堆上的地址。
操作数栈
代码中的1、2、10…这些被称作操作数,操作数栈是中转操作数的临时内存空间。
动态链接
math.compute()
我们称compute()为符号,
我们通过这个符号找到真正的compute()执行代码,
动态链接存放的就是方法在方法区中代码的内存地址。
方法出口
记录了方法执行完毕后需要返回到的代码行,还有返回值。
堆
new出来的对象一般分配在堆上,
堆上分为年轻代和老年代,年轻代又分为伊甸园区、幸存者区。
new出来的对象如果在堆上分配内存,一般是在伊甸园区,
当伊甸园区空间到一定程度,会进行GC,
叫minor GC或young GC,
minor GC回收的区域包括伊甸园区和当前的幸存者区,
被可达性分析标记的对象会被放到另外一个幸存者区,没有被标记的对象则会被清除,释放空间,
每次经历minor GC存活下来的对象,年龄会+1,分代年龄会记录在对象头中的markword信息中,
当分带年龄达到一定值,比方15,则被放到老年代。
web应用中的单例、静态变量、数据库连接池、对象缓存池、spring容器的bean会很快被放到老年代。
可达性分析
方法区
类加载器会将字节码文件class加载到方法区也叫metaspace,然后由字节码执行引擎进行执行。
元空间用的是物理空间,
一般存放常量池、静态变量、class类信息。
程序计数器
当一个线程开始执行,
jvm会为它从程序计数器中分配出一块专属的内存空间,
作为线程的程序计数器,记录当前线程执行位置,
由字节码执行引擎来维护计数器。
本地方法栈
用native修饰的发方法是本地方法,它是由c或c++实现的,内存空间是在本地方法栈上分配出来的。