JVM内存模型
JVM内存模型与Java内存模型不是一个东西,很多人经常会搞混掉,JMM是java并发处理时针对CPU内存抽象出来的一个内存模型。JVM内存模型可以理解为JVM启动是开辟了一块内存,然后用于存放各种数据。
图中的运行是数据区就是JVM线程模型,包含一下几个部分组成 方法区、本地方法栈、虚拟机栈、程序计数器、堆。其中方法区和堆是JVM中所有线程共享的,其它几个区域是每一个线程私有的。
方法区
方法区、永久代、元空间三者的区别是什么?
方法区简单理解就是JVM的规范,相当于Java语法中的接口的概念,而永久代和元空间方法区的具体实现。永久代是JDK7之前方法区的实现方式,这块区域是放在JVM内存中的。而元空间是JDK8之后的方法区的实现,是为了取代永久代,元空间是存放在用户内存中,也就是os内存中,不受gc的管理。
方法区中存放的是一些类的元数据, 比如类加载器加载.class文件之后会生成InstanceKlass对象,这个对象类的元数据信息,会放入方法区。
方法区参数调优
查看元空间最大最小值 -XX:MaxMetaspaceSize -XX:MetaspaceSize
调优方法就是最大最小调成一样大,防止元空间内存抖动,大小调成物理内存的1/32左右即可。
虚拟机栈
JVM是软件模拟虚拟机执行,是基于栈运行的,每个栈存放的内容是栈帧。一个方法的调用会在虚拟机栈中创建一个栈帧。方法执行完成之后会移除相应方法的栈帧。
栈帧包含一下四个内容:
局部变量表:保存局部变量
操作数栈:指向指令操作的栈
动态链接:指向元空间的对应的方法的MethodObject的内存地址
返回地址 保存线程:记录上一层栈帧执行的下一个字节码地址
附加信息:保存一些附件信息,用于调试,但实际用处不多。
程序计数器
字节码指令前面的index
本地方法栈
Java通过JNI调用C、C++动态链接库需要的栈,随着socket的发展,JNI技术已经用得非常非常少。
堆区
堆区是JVM内存模型中最主要的一块区域,存放对象,是垃圾回收器回收的区域。
堆内存区域划分
堆内存调优
-Xms -Xmx
最小大小 物理内存的 1 / 64
最大大小 物理内存的 1 / 4-Xms-Xmx
调优策略同方法区相似,最大最小调成一致,防止内存抖动
什么对象会进入老年区?
1、gc次数大于15依然存活的对象会进入老年代
gc次数只能调整小于15的值,因为对象的年龄是记录下对象头的MarkWord字段里,其中用4个位表示对象的年龄
2、大对象
对象大小超过Eden区的一半
3、动态年龄判断
当survivor中相同年龄的对象空间和大于survivor的一半,则suvivior中大于等于改年龄的对象都进入老年代
4、空间担保
young gc之后存活的对象大于survivor的空间,则存活的对象会被空间担保分配到老年代。
JVM内存几块区域的指向关系
方法区指向堆:方法区中存放的InstanceKlass会有指向其镜像类InstanceMirrorKlass的指针
堆指向方法区:堆里存放的对象,对象头中有个KlassPointer指针指向的就是方法区中的InstanceKlass对象
虚拟机栈指向堆:局表变量表中的引用对象指向的就是堆中的对象
虚拟机栈指向元空间:虚拟机栈中的动态链接保存的就是元空间的对应MethodObject的指针。
网友评论