JVM
模块
三大模块
- 类装载子系统
- 运行时数据区(内存模型)
- 字节码执行引擎
类装载子系统:把字节码加载到运行时数据区
执行引擎:执行内存中的数据
内存模型 3+2
-
栈(绑定在每个线程上)
线程栈|虚拟机栈
存放线程执行时需要使用的局部变量每一个线程一份
每一个方法一个栈帧
栈帧包含:局部变量表|操作数栈|动态链接|方法出口
局部变量表:存放局部变量和变量的值,如果是对象类型的话则存放的是对应对象在堆内的地址
操作数栈:在程序运行的时候需要计算的一些数据存入这个栈内等待计算
动态链接:存放非公共符号(变量.方法())对应的内存地址
方法出口:调用此方法时 调用方暂停的行号 -
程序计数器(绑定在每个线程上)
每个线程独有的 存贮正在运行代码的行号
每执行完一行代码 执行引擎会修改程序计数器 -
堆(所有线程共享)
存放对象 -
方法区(所有线程共享)
元空间
字节码包含很多常量(符号对应的常量)存在在方法区,运行时常量池
常量
静态变量:如果静态变量是对象类型则存放的是其再堆内的地址
类信息(c语言的类结构) -
本地方法栈(绑定在每个线程上)
存放其他语言程序内存
堆
包含2类模块
- 年轻代(eden:survivor)
E:s0:s1 为 8 :1:1 - 老年代
对象存储流程
先进入eden区
满了之后 minor gc(young gc)
- 找到e和s区中 gc root 标记非垃圾对象(其他模块还有有引用)
- 把上边的对象挪动到s的空区域中(s0,s1依次使用)且对象分代年龄 +1
- eden和本次复制的survivor区域中剩余的对象直接清理
- 分代年龄15的时候和 s空区域放不下 则存入老年代
- 老年代放满了则出发full gc
STW
gc的时候会产生STW
确保在gc过程中不使对象的状态发生改变(非垃圾|垃圾)
分析工具
jdk自带的jvisualvm
内存区域大小设置 主要是3块
- 堆
Xms
Xmx
Xmn:新生代 - 方法区
直接使用的物理内存
不设置的话扩容大小不限制
默认21M 存满就Full GC 然后扩容
启动的时候会持续加载类
XX.MetaspaceSize
XX.MaxMetaspaceSize - 栈
直接使用的物理内存
每个线程使用的大小
Xss:栈帧大小
实践
一般jvm会启动参数
-Xms4096m, -Xmx4096m, -Xmn512m,
-XX:MetaspaceSize=256m, -XX:MaxMetaspaceSize=256m,
后两个是元空间(方法区)的大小
前三个是堆的大小具体分析下来就是