3.2019年周阳老师JVM·第三部分
  GDnPUcdKzG4x 2023年11月02日 40 0


文章目录

  • ​​Heap堆结构简介​​
  • ​​heap堆new对象流程​​
  • ​​Transfervalue​​
  • ​​对象生命周期和GC​​
  • ​​永久代​​
  • ​​堆参数调优​​
  • ​​GC收集日志信息​​

Heap堆结构简介

堆包括三部分:新生代,老年代,元空间/永久代。

新生代包括:伊甸园区,幸存者0区,幸存者1区。

3.2019年周阳老师JVM·第三部分_局部变量


3.2019年周阳老师JVM·第三部分_局部变量_02


7是永久代,8是元空间。

物理上有2部分:新生+养老。

heap堆new对象流程

知识点:new一个对象,是new在了伊甸园区。

3.2019年周阳老师JVM·第三部分_局部变量_03


伊甸园区发生的GC是YGC。y是young的意思。也是轻量级的GC。YGC之后幸存的对象,放到幸存者0区,别名from区。

如果15次GC都没被清空,就会送到养老区。养老区满了,开启Full GC(FGC),Full gc 多次执行完毕之后,还不能清理出空间,就OOM了。

Transfervalue

基本类型传复印件,引用类型传引用,string特殊,方法内部会新建一个指向,并不改变原来的指向。

3.2019年周阳老师JVM·第三部分_堆内存_04


这个题需要注意:栈里面压入一个一个的方法(栈帧),每一个栈帧里面有不同的局部变量,age就是局部变量。虽然传给了另一个方法,是另一个栈帧的入参,是另外一个部分的局部变量,在那个栈帧中改变age,不影响main这个栈帧中age的值。

new person,引用在栈,数据在堆中,传给方法的是内存地址,指向关系如下图:

3.2019年周阳老师JVM·第三部分_局部变量_05


元空间里有常量池,string的使用原则是池子里有我就复用,没有我就在常量池里面新建。string传过去的确实是引用,但是他新建的逻辑是没有就新建,而不是在原来位置修改,就导致了,main中的string指向的内容没有改变。

3.2019年周阳老师JVM·第三部分_老年代_06

对象生命周期和GC

幸存者0区,简称s0,别名叫from区,幸存者1区,简称s1,别名叫to区。

3.2019年周阳老师JVM·第三部分_老年代_07


3.2019年周阳老师JVM·第三部分_局部变量_08


重点:注意关注堆中各部分的比例。新生代:老年代 = 1:2 ,Eden:From:to = 8:1:1.

轻GC(ygc,minorGC)的过程:复制,清空,互换。

永久代

3.2019年周阳老师JVM·第三部分_局部变量_09


永久代是7的叫法,元空间是8的叫法。

3.2019年周阳老师JVM·第三部分_老年代_10

3.2019年周阳老师JVM·第三部分_局部变量_11


3.2019年周阳老师JVM·第三部分_老年代_12


永久代几乎没有垃圾回收。

堆参数调优

3.2019年周阳老师JVM·第三部分_堆内存_13


3.2019年周阳老师JVM·第三部分_堆内存_14


这张图代表的是各个区发生的GC类型,以及调整时的参数设置。

逻辑上JVM分为三块,物理上分为2块。

理解每个参数的意思:

  • Xms:s是start的意思,初始化大小
  • Xmx:x是max的意思,最大化大小
  • Xmn:n是new的意思,代表新生代三块组合起来的大小
    新生区跟养老区是默认1:2的关系。
  • XX:PermSize,永久代的初始值
  • XX:MaxPermSize,永久代的最大值
    跟永久代有关的是jdk7的用法,以后用不到了,jdk8以后就改名了。

    jdk8只是更新了一个元空间,替代了持久区,其他是一样的。
    因为这些参数设置的问题,你的内存条可能不会被全部使用,也就是说,单纯差个内存条,不会让程序性能有想象中的提升,需要调整jvm参数去适配。默认java出厂只用物理内存的四分之一,加个4G内存条,只用1G。


    查看CPU核数:

    Runtime这个类就是对JVM体系结构中运行时数据区的抽象。


    代码测试:Xms(64分之一内存条),Xmx(四分之一内存条)的设置的值。

    运行结果:

    最佳实践:生产环境,Xms和Xmx的大小必须一样!!!!是为了避免jvm和应用程序争抢内存,避免内存忽高忽低,产生停顿
    idea如何配置jvm?

    上图是演示变更JVM的堆内存的初始值和最大值,然后打印gc的日志。
    配置之后再次运行上面的4行代码,结果如下:

    分析上图,实现了初始和最大堆空间一致的效果。根据GC日志,可以证明,堆由young区,old区,metaspace区组成。这是逻辑组成的证明。也可以证明物理组成,因为young区的total|+old区的total就等于我们配置的Xmx和Xms。如此就证明了物理上由young+old组成。如下图:

如何干爆堆,测试方式i如下,思路为调整堆大小,然后死循环创建对象。

3.2019年周阳老师JVM·第三部分_堆内存_15


3.2019年周阳老师JVM·第三部分_老年代_16


运行实际结果截图:堆空间溢出

3.2019年周阳老师JVM·第三部分_局部变量_17


5个常见的异常,这个需要回答。

一句话撑爆:

3.2019年周阳老师JVM·第三部分_局部变量_18


回到循环创建的代码,分析打印的日志:

3.2019年周阳老师JVM·第三部分_局部变量_19


可以分析出先young-gc,很多次ygc之后是一次full-gc,然后又是多次young gc。直到一瞬间,full gc之后也没用空间了,jvm就撂挑子了,如下图:

3.2019年周阳老师JVM·第三部分_局部变量_20


最初的gc过程有这个过程的理论描述(下图),上图是实际的执行过程。发生堆内存的oom异常,最近一次gc是full gc。

3.2019年周阳老师JVM·第三部分_堆内存_21

GC收集日志信息

GC的执行过程一定是先轻后重,先轻gc(young gc,minor gc)再重GC(major gc)。

3.2019年周阳老师JVM·第三部分_局部变量_22

分析一下gc的日志:
第一行,因为分配空间失败了,产生young gc。也就是内存不够用才gc。
第二行:gc发生在young区域,2048是gc之前的用的空间,488是gc之后用的空间,2560是young区(新生代)的总内存(总共大小)。young gc前jvm堆内存占用2048k,之后是773k,9728k是配置的jvm堆总大小。 整个ygc耗时0.0015243 秒。
第三行:时间,用户耗时,系统耗时,时间耗时。

3.2019年周阳老师JVM·第三部分_老年代_23

分析一下爆炸之前的最后一个full-gc:

3.2019年周阳老师JVM·第三部分_老年代_24


full gc的结果只有2个,要么成功,要么就oom。

young区总计2048k,gc前后都是0,old区gc前后只改变了很少的一点,元空间也是,几乎没有清理出太多空间。

清理不出来空间,时间就是0,这种情况,就崩了,会导致oom。

3.2019年周阳老师JVM·第三部分_局部变量_25


3.2019年周阳老师JVM·第三部分_老年代_26


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

GDnPUcdKzG4x