JVM介绍

JVM

JVM内存模型

在这里插入图片描述

  1. 方法区:用于存放JVM架子的类信息、常量、静态变量、即时编译器编译后的代码等;
  2. 堆:分成老年代和新生代(新生代包括一个Eden区和两个Surivor区)
  3. 程序计数器:当前线程执行字节码的行号指示器
  4. 虚拟机栈(JVM执行Java方法):Java方法执行的内存模型,每个方法执行都会创建一个栈帧(局部变量表、操作数栈、动态链接、方法出口),每个方法从开始到结束都对应一个栈帧在虚拟机栈中入栈到出栈的过程
  5. 本地方法栈(JVM执行本地方法):HotSpot把本地方法栈和虚拟机栈合二为一
    方法区和堆是线程共有的,程序计数器、虚拟机栈、本地方法栈都是线程私有的

垃圾回收

1判断对象是否存活

​ 1.1. 引用计数法
实现简单,判定效率高;但是无法解决对象相互循环引用的问题

​ 1.2. 可达性分析算法
当一个对象到GC roots没用引用链时,证明此对象不可用
GC roots种类
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中的静态属性引用的对象
方法区中的常量引用的对象
本地方法栈中JNI(Native方法)引用你的对象
​ 1.3. 引用
强 StringBuffer str = new StringBuffer(“Hello world”);
弱 WeakReference userReference = new WeakReference(u);
软 SoftReference userSoftRef = new SoftReference(u);//创建引用给定对象的新的软引用
虚 PhantomReference phantomRef = new PhantomReference(obj, phantomQueue);
​ 1.4. finalize
对象是否覆盖finalize方法,是的话,jvm执行finalize()方法,否的话,JVM回收对象

2垃圾收集算法

1.1标记清除算法
缺点:1标记和清除效率都不高;2标记、清除之后会产生大量不连续的内存碎片

1.2标记整理算法
限制性标记-清除,让所有存活对象都向一端移动,最后清理掉边界以外的内存

1.3复制算法
Eden:Surivor:Surivor=8:1:1
分配担保:如果Surivor没有足够的空间来存放上次新生代GC存活下来的对象,他们通过分配担保机制进入老年代
缺点是对象存活率高时,复制的效率比较低
回收方式:单线程、并行、并发

3垃圾收集器

新生代

Serial
特点:单线程收集;标记-复制算法
场景:Client模式下默认的新生代收集器;单核机器
PaNew
特点:多线程并行手机;标记-复制算法;其他特点和Serial相似
缺点:在单CPU场景效果不突出
场景:用户交互,配合CMS垃圾收集器
Parallel Scavenge
特点:目标在于达到可控吞吐量(吞吐量=用户代码运行时间/(用户代码运行时间+垃圾收集时间));标记整理算法
场景:高效利用CPU,后台运算且不需要太多交互

老年代

CMS
步骤:
初始标记:标记GC Roots直接相关联的对象,速度快
并发标记:GC Roots Tracing过程,耗时长,与用户进行并发工作
重新标记:修正并发标记期间用户进程继续运行而产生变化的标记,耗时比初始标记长,但远小于并发标记
并发清除:清除标记的对象
缺点:
对CPU资源敏感
无法回收浮动垃圾
标记-清除算法,会产生内存碎片,可通过参数开启碎片的合并整理
Serial Old
特点:Serial的老年代版本,单线程;标记整理算法
场景:jdk1.5之前与Parallel Scavenge配合使用;作为CMS的后背预案
Parallel Old:
特点:多线程,标记-整理算法
场景:为了替代Serial Old与Parallel Scavenge配合使用

G1

步骤
初始标记:标记GC Roots直接关联的对象
并发标记:对堆中对象进行可达性分析,找出存活对象,耗时长,与用户进程并发工作
最终标记:修正并发标记期间用户进程继续运行而产生便获得标记
筛选回收:对各个Region的回收价值排序,然后根据期望的GC停顿时间制定回收计划
特点
将整个Java堆划分成多个大小相等的独立区域Region,跟踪各个Region里面的垃圾堆积的价值大小,在后台维护成一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region

4垃圾回收过程

大多数情况下对象在Eden分配,当Eden没有足够的空间时将发起一次Minor GC;
当Eden执行Minor GC后还不足为以为对象分配空间,大对象直接进入老年代,可以用参数设置大对象直接进入老年代,避免频繁Minor GC;
如果对象在Eden出生,发生Minor GC后仍然存活,且能被Survivor容纳,年龄加1,达到一定年龄进入老年代,默认15;
占Survivor空间一半以上且年龄相等的对象,大于等于该年龄以上的对象直接进入老年代;
发生Minor GC之前会先检查来年代最大可用连续空间是否大于新生代所有对象的总空间,如果大于说明MinorGC安全,否则会判断是否允许担保失败,如果担保失败,判断老年代最大连续空间是否大于历次晋升老年代对象的平均大小,如果大于则尝试MinorGC,否则执行FullGC

性能优化

常见问题

CPU Load过高导致系统不可用或tps急剧降低
YounGC次数频繁
FullGC次数频繁
Full GC时间长
Perm SpaceGC次数频繁
内存泄漏、内存溢出

调优参考依据

系统运行日志
异常堆栈
GC日志
线程快照
堆转储快照

调优工具

jdk命令工具

jps查看系统内所有Hot Sport进程
jinfo显示虚拟机配置信息
jstat收集虚拟机运行数据
jmap生成指定进程堆转储快照(heapdump)
jhat分析heapdump文件
jstack显示虚拟机线程快照

可视化工具

jconsole和jvisualvm查看内存回收情况
BTrace跟踪调试方法
jprofiler监控每个类的内存占用
MAT工具分析内存占用

优化方案

JVM配置

-Xms和-Xmx的值设置成对等
新生代尽量设置大一些

堆区:最大堆、最小堆、新生代:-Xms512M -Xmx512M -Xmn128M
:每个线程可使用内存 -Xss256k
方法区: JVM设置最大最小 -XX:MaxPermSize=128M -XX:permSize=64M
原空间:(jdk1.8)-XX:MetaspaceSize:128M -XX:MaxMetaspaceSize=128M(元空间并不在虚拟机中,而是使用本地内存,因此,云空间的大小仅受本地内存限制)

实现层面

避免创建过大的对象和数组
避免同时加载大量数据
集合中的对象用完后及时清空
在合适的场景中使用软引用、弱引用
尽量避免长时间等待外部数据(数据库、网络、设备资源等)
设置合理的线程数

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值