1.GC算法
1.标记清除算法
1.遍历GC Roots,然后将存活的对象标记
2.回收未被标记的对象
缺点 效率不高 空间会产生大量碎片
2.复制算法
将原有的内存空间一分为二,每次只用其中的一块,在垃圾回收时,将正在使用的对象复制到另外一个内存空间中,然后将该内存空间清空,交换两个内存的角色,完成垃圾回收
如果内存中的垃圾对象较多,需要复制的对象就较少,这种情况下适合使用该方式并且效率比较高,反之,则不适合
优点:在垃圾对象多的情况下,效率较高。清理后,内存无碎片
缺点:在垃圾对象少的情况下,不适用
3.标记-整理算法
1.遍历GC Roots,然后将存活的对象标记
2.整理 移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。
4.分代回收
新生代
每次垃圾回收都有大量对象死去,只有少量存活,选用复制算法比较合理
老年代
老年代中对象存活率较高、没有额外的空间分配。所以必须使用 标记清除 或者 标记整理
2.JVM内存
-
新生代的伊甸园(Eden)和幸存者乐园(Survivor)
-
老年代(Tenured)终身颐养园
-
永久代(PermGen/Permanet Generation)
- 主要存放Class和Meta(元数据)的信息
- Jdk7及以前版本 永久代和堆是相互隔离的,但它们使用的物理内存是连续的
- Jdk8元空间不再与堆连续,而且是存在于本地内存
- 为什么做出元空间的改变
- 空间大 可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制
- 本地空间不够不会触发FULLGC
-
图片
-
为什么会有年轻代
分代的唯一理由就是优化GC性能 -
Minor GC
在GC开始的时候,(大对象直接进入老年代)对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置默认是15)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。
- Major GC
老年代的GC - Full GC
- 整个heap的GC
- 触发条件
- System.gc 尽量让jvm自动GC
- 老年代空间不足
- 永久代空间不足
3.垃圾回收器
G1回收过程link
4.jvm调优工具(jdk bin目录)
-
jdk自带
- jps(Java Virtual Machine Process Status Tool)
输出JVM中运行的所有进程状态信息 - jinfo
输出指定pid进程JVM中运行的所有进程状态信息 - jmap
- 主要是打印某一时刻,某个进行的jvm堆信息(内存配置信息和内存占用情况)
- jstat
- 统计某一个进程在指定时间内的gc信息(比如3s一次统计)
- 每个需要gc的区使用情况 各个区的gc次/gc时间/内存使用百分比
- 统计某一个进程在指定时间内的gc信息(比如3s一次统计)
- jstack
- 命令 jstack pid > ./stack.log
- Thread dump(线程信息)
- 最后会有死锁日志
- 主要看 blocked(等待线程)/deadlock
- jconsole(可视化窗口 可远程可本地)
- Summary选项卡:显示JVM和被监视值的汇总信息
- Memory选项卡:显示内存使用信息。
- Threads选项卡:显示线程使用信息。
- Classes选项卡:显示类(class)加载信息
- MBeans选项卡:显示MBeans信息
- VM选项卡:显示JVM信息
- jstack
- 打印Thread dump(deadlock信息)
- jvisualvm(可视化窗口 可远程可本地)
- 和jconsole类似
- JProfile
- 很好用 但是收费
- gc log
- jvm启动参数配置开启gc log配置gclog的输出位置
- 所有的gc日志输出 可以判断gc类型和gc时候的内存占用情况
- jps(Java Virtual Machine Process Status Tool)
-
第三方
- Mat Memory Analyzer Too
- 找出内存泄漏的原因
- 找出重复引用的类和jar
- 分析集合的使用
- 分析类加载器
- arthas link
- 阿里开发的一个服务
- dashboard命令动态查看内存情况
- 分析过程中可以把某一时刻的 内存快照dump出来 然后配合mat工具分析更一步详细的情况
- Mat Memory Analyzer Too
5.jvm调优实战(jdk bin目录)
- 几个步骤/参数/经验抉择
- 几个场景
- 参数
- 调优
- 减少FULL GC次数 Xms/Xmx调成一致 System.gc
- 内存泄露
- 堆内 大对象 服务器会自动重启 原来是在某个条件下,会查询表中所有未处理的指定数据,但是由于查询的时候where条件中少加了模块这个条件,导致查询出的数量达4万多条 4W多个对象
- 堆外 metaspace空间不足
- jvm 参数
- -是标准参数
- X是非标准参数只能被部分VM识别
- 非稳定参数随时可能被修改或者移除
- 内存设置
- Xmx和Xms为老年代存活对象的3-4倍(FullGc后的老年代大小)
- 年轻代为老年代存活对象1-1.5倍
- 老年代为老年代存活对象2-3倍
- 永久代为老年存活对象的1.2-1.5倍