JVM思维导图
2024-03-18 15:21:25 64 举报
AI智能生成
类加载机制 垃圾收集器 JVM内存结构 GC优化
作者其他创作
大纲/内容
类加载机制
双亲委派模型
过程
父类加载器优先加载,父类无法加载再由子类加载器加载,都加载不到抛出ClassNotFoundException异常
好处
防止内存中出现多份相同字节码
保证java程序稳定安全运行
破坏模型
重写loadClass()方法
类加载方式
启动后由JVM初始化加载
Class.forName()加载
ClassLoader.loadClass()加载
什么是类的加载
将 .class加载到内存中供后续使用
类的生命周期
加载
连接
验证
准备
解析
初始化
使用
卸载
类加载器
分类
启动类加载器
加载JDK\jre\lib下,或被-Xbootclasspath参数指定的路径且能被虚拟机识别的类库(如rt.jar)
开发者无法直接使用
拓展类加载器
加载JDK\jre\lib\ext,或java.ext.dirs系统变量指定的类库
开发者可直接使用
应用类加载器
加载ClassPath指定的类,默认的类加载器
开发者可直接使用
自定义类加载器
定制加载类的方式,继承ClassLoader类,重写findClass() 方法
加载器关系
组合关系而而非继承关系
加载机制
全盘负责
当一个类加载器加载某个类时,该类依赖和引用的其他类也由此类加载器加载,除非显示使用其他类加载器加载
父类委托
父类加载器优先加载,父类无法加载再由子类加载器加载
缓存机制
加载过的类都会被缓存下来
垃圾收集器
垃圾收集器
年轻代
Serial
单线程
最古老、稳定,可能会产生较长停顿
ParNew
Serial的多线程版本,其余行为和Serial一样
Parallel
多线程
自适应调节吞吐量
计算公式
吞吐量=用户代码运行时间/(用户代码运行时间 + GC时间)
参数
-XX:MaxGCPauseMillis 最大垃圾收集停顿时间
-XX:GCTimeRatio 吞吐量大小
-XX:+UseAdaptiveSizePolicy
开关参数,打开后不需要设置-Xmn、-XX:SurvivorRatio、-XX:PretenureSizeThreshold等细节参数,需要设置基本内存参数(如-Xmx)和优化目标-XX:MaxGCPauseMillis、-XX:GCTimeRatio
老年代
Serial Old
Serial 的老年代版本
标记整理算法
Parallel Old
Parallel的老年代版本
标记整理算法
CMS
以获取最小回收停顿时间为目标
标记清除算法
过程
初始标记
标记GC Roots能直接关联到的对象
并发标记
GC Roots Tracing
重新标记
修正并发标记期间,因用户程序运行过程中标记发生改变的对象的标记记录
并发清除
优
并发收集
低停顿
缺
内存碎片
并发阶段降低吞吐量
跨代
G1
JDK9默认
标记整理、复制算法
将堆划分成多个大小相同的区域(Region)
与CMS比的优势
不存在内存碎片
可预测停顿时间
原理:根据Region回收所需要空间的大小和时间的经验值优先回收价值最大的Region
过程
初始标记,并触发一次Minor GC
Root Region Scanning
并发标记
再标记
复制/清除
垃圾收集算法
标记清除
过程
先标记,然后统一清除
缺点
标记和清除效率不高
内存碎片
复制算法
过程
内存划分为相等的两块,将存活对象复制到一块,清理另一块的内存
缺点
内存缩小为原来一般
对大量存活的对象复制效率不高
标记整理
过程
先标记,然后将存活对象移动到一段,最后清理掉边界之外的内存
分代收集算法
年轻代:对象存活率低 —> 复制算法
年老代:对象存活率高,无空间分配担保 —> 标记清除、标记整理
主要工作对象
堆区
方法区
对象存活判断
引用计数法
计数器 > 0, 存活;计数器 = 0, 回收
无法解决对象循环引用的问题
可达性分析
不存在到GC Roots即为不可达
GC Roots
虚拟机栈引用的对象
本地方法栈引用的对象
方法区中类的静态属性引用的对象
方法区中常量引用的对象
JVM内存结构(JDK7)
控制参数
-Xms 堆区最小空间大小
-Xmx 堆区最大空间大小
-XX:NewSize 新生代最小空间大小
-XX:MaxNewSize 新生代最大空间大小
-Xss 每个线程的堆栈大小
-XX:PermSize 永久代空间最小大小
-XX:MaxPermSize 永久代空间最大大小
内存划分
堆区
说明
JVM管理的最大内存,GC回收重点,进一步划分为年轻代(Eden区 + 2个Survivor区,Eden:Survivor = 8:1)、年老代
存储对象
几乎所有对象实例
是否线程共享
是
异常
内存无法满足且无法拓展时抛出OOM
方法区
说明
有时称为“永久代”(实际上“方法区”是JVM的规范,而“永久代”是规范的一种实现)。回收目标主要是常量池和类型的卸载,回收条件苛刻,回收结果让人难以满意
存储对象
被JVM加载的类信息、常量、静态变量、即时编译后的代码等
是否线程共享
是
异常
内存无法满足且无法拓展时抛出OOM异常
JVM栈
说明
线程私有,描述的是java方法执行的内存模型,方法执行的过程会创建一个栈帧,方法的执行和退出对应栈帧在JVM栈入栈和出栈的过程
存储对象
栈帧(局部变量表、方法出入口等信息)
是否线程共享
否
异常
超过虚拟机允许的深度抛出StackOverflowError异常
如果可拓展,拓展无法申请到足够内存抛出OOM异常
本地方法栈
与JVM栈类似,不过针对的是native本地方法
程序计数器
说明
记录线程执行的字节码的行号指示器,当线程切换时能恢复到正确位置
存储对象
计数器
是否线程共享
否
异常
唯一没有OOM的区域
对象分配规则
对象优先分配在Eden区域。空间不足触发Minor GC
大对象直接进入老年代(避免对大对象复制)。通过参数 -XX:PretenureSizeThreshold 控制对象大小
长期存活的对象进入老年代。通过 -XX:MaxTenuringThreshold 参数控制年龄,每次Minor GC年龄加1
对象动态年龄判断。Survivor区中相同年龄的对象内存总合大于Survivor区的一半,大于等于该年龄的对象进入到老年代
空间分配担保,让Survivor区无法容纳的对象进入老年代。老年代最大可用连续空间是否大于新生代所有对象总和或历次晋升平均大小?是,Minor GC;否,Full GC
GC优化
过程
监控GC,可使用VisualVM、JProfiler(注:VisualVM可在发生OOM dump出内存使用情况)等软件监控
分析结果,GC发生的时间、频率等(注:在线分析GC日志网站 http://gceasy.io)
调节内存大小、选择垃圾收集器
多个参数结果对比验证
将最佳参数应用到服务器上
目的
减少进入老年代的对象
通过 -Xms、-Xmx等调优参数将对象尽量留在年轻代
通过 -XX:PretenureSizeThreshold 设置进入老年代对象大小
通过 -XX:MaxTenuringThreshold 设置对象进入老年代年龄,默认15
减少Full GC的时间
适当减少老年代内存大小(但注意过小会OOM)
选择适合的垃圾收集器
GC优化之前
根源是创建过多的对象
需要减少对象的创建,如StringBuilder代替String、减少不必要日志的输出
常见调优参数
-Xms 初始化堆内存大小
-Xmx 堆内存最大限制
-XX NewSize 年轻代大小
-XX NewRatio 年老代和年轻代内存比
-XX SurvivorRatio Eden区和Survivor区比
0 条评论
下一页