JVM内存模型概述以及内存分配机制
一、JVM内存模型结构
1.类装载子系统:负责将class文件加载到JVM虚拟机内存中
2.字节码执行引擎
3.堆:基本创建的对象实例都会在这里分配内存,所有线程可以共享的区域,一般方法区或者栈帧的变量都会存储对应在堆的指针
4.栈:又成栈帧,每开启一个线程,JVM就会分配一个栈帧区域
5.本地方法栈:JVM内存很多是C++实现的,该内存空间是专门分配给C++本地方法的
6.程序计数器:每个线程都有,用于记录当前线程执行字节码的地址
二、栈(线程)内部结构
1.局部变量表
2.操作数栈:例如代码a=2的赋值操作,会先将2压入操作数栈,在成员变量表中开辟a的内存空间,再将操作数栈弹出赋值在成员变量表的内存空间中
3.动态链接:后续博文会详细解释,涉及概念较多
4.方法出口:主线程中可能会调用多个方法,方法出口可以定位当前方法的结束为止,保障主线程在内部方法执行完成之后,继续下面的代码执行
三、爆栈实例代码
public class test {
private void test(){
this.test();
}
public static void main(String[] args) {
test t= new test();
t.test();
}
}
递归不断调用,JVM栈内存会持续分配无法释放,发生爆栈
四、爆堆实例代码
public class OOMbject {
public static void main(String[] args) {
List<OOMbject> list = new ArrayList<>();
while (true) {
list.add(new OOMbject());
}
}
}
持续不断新建对象,撑爆堆空间
五、堆的内部结构
总体分为:年轻代(2/3)和老年代(1/3)
年轻代又分Eden区和s0,s1区,比例是8:1:1
Eden区优先放,放满触发minus gc,不在gc root引用的直接清除,还在gc root引用的对象到s0或者s1区,再放满,Eden,s0或者s1触发munus gc,s0或者s1区还在gc root的,交换位置,但是代数+1,到15的时候 转如老年代,一般spring容器的对象或者缓存对象都会最后再老年代。老年代空间不足的时候,会触发full gc,full gc的时候会有一个STW(stop the world)的机制,会停止线程继续分配空间到堆中,系统短暂停止响应,JVM调优就是减少这种情况,提高系统的响应率。