JVM 复盘

image.png

JVM 复盘

一 JVM内存块结构
  • 主要是堆栈;方法区;而我们关注比较多的是堆区域,而方法区存放的信息比较少很少会有内存溢出的情况(JDK8 元空间后更加没有)。堆区域分为新生代的Eden/S0/S1区域、老年代分为:Old区域;对象会先到Eden/S0区域,当Eden/S0区域满了;会触发YGC会标记的对象压到S1区域。

  • 当S1区域满了、或者对象标记15次;就会把存活的对象放到Old老年代;当老年代满了触发Full GC这时候会把新生代、老年代全部GC一遍。这个时候会触发STW问题,分代的设计主要是最大努力避免对象到Old并触发Full GC 造成STW问题。


    image.png
二、垃圾收集器cms/g1之间的区别
CMS
  • 本质上就是说在CMS GC期间,他需要把用户线程都停下来;对内存对象进行标记清理在我们系统使用CMS一般优化就是内存不够用就调大一些、在极端业务场景的情况下;可能会根据业务场景来设置堆大小,比如调小可能GC的频率高;但是RT降低了;调大虽然GC频率低了、但每次触发RT 也提高了。

  • 但一般业务场景是可以接受GC造成的停顿耗时;所以会在宿主机内存可用的情况下还是去调大内存,如果调小的话;对象回收不了也很容易造成内存溢出、风险更大。

G1
  • G1 逻辑上区域还是一样的。新生代(包含三个区域(Eden/S0/S1区域)、老年代(old)但是他的结构发生了巨大的变化;就是说他把内存分为2048个内存块;每个块的大小在[1M,32M]之间。
  • 分成块的目的是可以控制扫描范围、这是G1核心功能;你可以设置y每次GC的最大毫秒数、G1根据你设置的毫秒数来决定每次去回收多少个region块。
  • G1的优点就是更灵活了、GC耗时可配置;最大可能降低了扫描范围,虽然也有STW问题;但是他先圈了一块region再去回收(有限使用比较多的region区域)。更精细、延迟更低了,也没有垃圾碎片的问题;不像CMS那样每次还要STW整个堆区域;还有垃圾碎片的问题。
  • 但是G1 GC的频率更高了。对CPU使用也比较频繁;因为每次GC的区域比较小。CMS GC耗时不可预测、CPU使用率低、在能够容忍GC STW还是不错的选择,还有就是G1的新版对STW的优化可能要收费。


    image.png
三、jdk7/jdk8之间的区别
  • 永久代 JDK7 存储的信息比较少、方法、常量等;基本不会触发Full GC、JDK8使用了元空间后;实际上默认共享了物理内存、也就是说物理内存有多大;就可以使用多大;充分降低了JVM可能会造成的GC影响;但一般都会去设置元空间大小为了避免对宿主机内存造成影响;影响其他进程。
四、排查高耗GC的方式
  • 通过top 看高耗线程、线程ID 转换16进制 、再通过jstack 打印堆栈信息、找到16进制的代码块。
  • 通过jmap gcutil 查看内存分配、内存实时运行状态 来判断。很多时候内存溢出都会触发大量的Full GC通过gcutils 可以找到判断信息。有些情况并没有代码抛异常、就是触发Full GC 导致系统卡顿、这个时候查询JVM内存状态是非常好的手段。

你可能感兴趣的:(JVM 复盘)