云社区 博客 博客详情

JVM笔记六-堆区知识之对象生命周期和GC的关系

凯哥Java 发表于 2020-10-24 10:10:36 2020-10-24
0
0

【摘要】 通过上一篇文章的学习,我们对JVM堆区有了初步的认识,接下来,我们继续展开讲解堆区。24/64草稿箱代码语言 7 秒后保存数据已于 10:09 保存。1632/20000上传附件缩略图:作为封面显示在文章列表,可自定义设置标签设置 : 请添加标签文章摘要 :0/200内容为空时默认显示文章前200字,您可以手动更改评论权限:文章不需要评论文章创作类型:原创文章 翻译文章 转载文章是否允许转...

通过上一篇文章的学习,我们对JVM堆区有了初步的认识,接下来,我们继续展开讲解堆区。

24/ 64

草稿箱

代码语言
  7 秒后保存
数据已于 10:09 保存。 20000
    缩略图:
    作为封面显示在文章列表,可自定义设置
    文章摘要 :
    0/ 200

    内容为空时默认显示文章前200字,您可以手动更改

    评论权限:
    文章创作类型:
      
    是否允许转载:
     
    免责声明:
    用户承诺,发表的文章不存在任何知识产权问题并自行承担全部责任,华为云社区可配合权利人进行必要的维权配合工作。

    对象生命周期和GC的关系。控制台

    我们已经知道了,堆区的新生区分成了三个部分:伊甸园区、幸存者0区、幸存者1区。

    其中0区也叫from,1区也叫to区。但是这个from和to是固定不变的吗?NO,NO,NO不是的。当新生区执行一次GC(YGC)后,from和to区会进行交换。交换后,也就是在GC之后,谁空谁是to区。所以,from区和to区的位置和名分不是一成不变的。会发生变化的。

    Java堆从GC的角度可以分为:新生区和老年代。这个是从物理分的。

    image.png

    新生代和老年代,占用堆区的比例是:1比2

    在新生代中的伊甸园区和幸存者0区、幸存者1区的占比是:8比1比1

    从逻辑来分的话,又有永久代(元空间)。如下图:

    image.png

    新生区GC (MinorGC) 的过程:复制->清空->互换

    1:复制

    eden、Survivor From区 复制到Survivor To区,年龄+1

    首先,当Eden区满的时候会触发第一次GC,把还存活的对象拷贝到survivorFrom区,当Eden区再次触发GC的时候,会扫描Eden区和From区域,对这两个区域进行垃圾回收,经过这次垃圾回收后还存活的对象,则直接复制到To区(如果有对象的年龄已经达到了去往老年代的标准,则这些达到标准的对象将会被复制到老年代区),同时把这些对象的年龄+1

    2:清空

    清空Eden、survivorFrom区

    然后,清空Eden和SuriviorFrom中的对象,也即是复制之后有交换。谁空谁做to区。

    3:SurvivorTo和SurvivorFrom互换

    最后,Survivor To和Survivor From互换,原来Survivor To成为下一次GC的Survivor From区,部分对象会在From和To区中复制来复制去的,如此交换15次(由JVM参赛MaxTenuringThreshold决定的,这个参赛默认值就是15),最终如果还是存活的对象,就把这些存活的对象存入到老年代区域。

    这个过程可以有个生活中的case.士兵到将军的过程。士兵上战场,幸存下来,成班长,下次战争来临的时候,班长带着新的士兵继续冲杀,幸存下来,班长升级成排长,以此类推。经历大大小小战役十五次之后,升级成了将军,进入到年老代。

    Java7的永久代:

    JVM内存管理的模型图如下:

    image.png

    Why?

    真相:经过研究,不同对象的生命周期是不同的(废话嘛,不同对象,操作链路长短不一样,当然生命周期不一样了),98%的对象是临时对象(临时对象,就是用完就被回收了)。

    实际而言,方法区(Method Area)和堆区一样,是各个线程共享的内存区域,它用于存储虚拟机加载的:类信息+普通常量+静态常量+编译器编译后的代码等等。虽然JVM规范将方法区描述为堆的一个逻辑部分,但是它却还有一个别名:N0n-Heap(非堆),目的就是要和堆区分开的(这句话怎么理解?我们从小教育都知道,台湾是中国的一部分,但是台湾还有个别名:中华台北。其目的就是台湾想在国际上和中国区分开而已)。

    对于HotSpot虚拟机,很多开发者习惯将方法区称之为”永久代(Parmanent Gen)”,但严格本质上说两者不同。或者说使用永久代来实现方法区而已,永久代是方法区(相当于是一个接口Interface)的一个实现。JDK1.7的版本中,已经将原本存放永久代的字符串常量池移走了。

    三者之间在堆内存中的关系,我们在来看一遍,如下图:

    image.png

    永久代:java7之前

    永久存储区是一个常驻内存区域,用于存放JDK自身所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占用的内存。

    至此,我们已经把JVM堆区讲完了。那么接下来凯哥(凯哥Java:kaigejava)将接着讲解JVM调优命令了。欢迎大家一起继续学习。


    登录后可下载附件,请登录或者注册

    【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:huaweicloud.bbs@huawei.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
    评论文章 //点赞 收藏 0
    点赞
    分享文章到微博
    分享文章到朋友圈

    上一篇:JVM笔记五-堆区heap

    下一篇:JVM笔记八-堆参数调优

    评论 (0)


    登录后可评论,请 登录注册

    评论

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。