关于JVM,也许你听过这些术语:年轻代(新生代)、老年代、永久代、minor gc(young gc)、major gc、full gc

不要急,先上图,这是jvm 堆内存结构图

仔细的你发现了 图中有些分数8/10和1/10,这是默认配置下各个代内存分配比例。

举个栗子:

假如总heap max分配1200M,那么年轻代占用1/3就是400M,老年代占2/3就是800M。

Eden占年轻代的8/10就是320M。Survivor占年轻代的2/10就是80M,from和to各占40M。

年轻代

也叫新生代,顾名思义,主要是用来存放新生的对象。新生代又细分为 Eden区、SurvivorFrom区、SurvivorTo区。

新创建的对象都会被分配到Eden区(如果该对象占用内存非常大,则直接分配到老年代区), 当Eden区内存不够的时候就会触发MinorGC(Survivor满不会引发MinorGC,而是将对象移动到老年代中),

在Minor GC开始的时候,对象只会存在于Eden区和Survivor from区,Survivor to区是空的。

Minor GC操作后,Eden区如果仍然存活(判断的标准是被引用了,通过GC root进行可达性判断)的对象,将会被移到Survivor To区。而From区中,对象在Survivor区中每熬过一次Minor GC,年龄就会+1岁,当年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置,默认是15)的对象会被移动到年老代中,否则对象会被复制到“To”区。经过这次GC后,Eden区和From区已经被清空。

“From”区和“To”区互换角色,原Survivor To成为下一次GC时的Survivor From区, 总之,GC后,都会保证Survivor To区是空的。

奇怪为什么有 From和To,2块区域?

这就要说到新生代Minor GC的算法了:复制算法

把内存区域分为两块,每次使用一块,GC的时候把一块中的内容移动到另一块中,原始内存中的对象就可以被回收了,

优点是避免内存碎片。

老年代

随着Minor GC的持续进行,老年代中对象也会持续增长,导致老年代的空间也会不够用,最终会执行Major GC(MajorGC 的速度比 Minor GC 慢很多很多,据说10倍左右)。Major GC使用的算法是:标记清除(回收)算法或者标记压缩算法。

标记清除(回收):1. 首先会从GC root进行遍历,把可达对象(存过的对象)打标记

2. 再从GC root二次遍历,将没有被打上标记的对象清除掉。

优点:老年代对象一般是比较稳定的,相比复制算法,不需要复制大量对象。之所以将所有对象扫描2次,看似比较消耗时间,其实不然,是节省了时间。举个栗子,数组 1,2,3,4,5,6。删除2,3,4,如果每次删除一个数字,那么5,6要移动3次,如果删除1次,那么5,6只需移动1次。

缺点:这种方式需要中断其他线程(STW),相比复制算法,可能产生内存碎片。

标记压缩:和标记清除算法基本相同,不同的就是,在清除完成之后,会把存活的对象向内存的一边进行压缩,这样就可以解决内存碎片问题。

当老年代也满了装不下的时候,就会抛出OOM(Out of Memory)异常。

永久代(元空间)

在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间,Metaspace)的区域所取代。

值得注意的是:元空间并不在虚拟机中,而是使用本地内存(之前,永久代是在jvm中)。这样,解决了以前永久代的OOM问题,元数据和class对象存在永久代中,容易出现性能问题和内存溢出,毕竟是和老年代共享堆空间。java8后,永久代升级为元空间独立后,也降低了老年代GC的复杂度。

Visual GC插件

自己不妨写点代码,测试下上面说过的GC过程,通过Visual GC插件

Java VisualVM安装Visual GC插件

https://blog.csdn.net/yujianping_123/article/details/99549194

面说到了minor gc 和major gc,那么看下full gc

Full GC

是清理整个堆空间—包括年轻代和老年代。

什么时候触发:

1. 调用System.gc

2. 方法区空间不足

2.老年代空间不足,包括:

新创建的对象都会被分配到Eden区,如果该对象占用内存非常大,则直接分配到老年代区,此时老年代空间不足

做minor gc操作前,发现要移动的空间(Eden区、From区向To区复制时,To区的内存空间不足)比老年代剩余空间要大,则触发full gc,而不是minor gc

等等

GC优化的本质,也是为什么分代的原因:减少GC次数和GC时间,避免全区扫描。

如何减少GC出现的次数(GC优化)

1.对象不用时最好显式置为 Null

一般而言,为 Null 的对象都会被作为垃圾处理,所以将不用的对象显式地设为 Null,有利于 GC 收集器判定垃圾,从而提高了 GC 的效率。

2.尽量少用 System.gc()

此函数建议JVM 进行主GC,虽然只是建议而非一定,但很多情况下它会触发主 GC,从而增加主 GC 的频率,也即增加了间歇性停顿的次数。

3.尽量少用静态变量

静态变量属于全局变量,不会被 GC 回收,它们会一直占用内存。

4.尽量使用 StringBuffer, 而不用String 来累加字符串。

由于 String 是固定长的字符串对象,累加 String 对象时,并非在一个 String对象中扩增,而是重新创建新的 String 对象,如 Str5=Str1+Str2+Str3+Str4,这条语句执行过程中会产生多个垃圾对象,因为对次作“+”操作时都必须创建新的 String 对象,但这些过渡对象对系统来说是没有实际意义的,只会增加更多的垃圾。避免这种情况可以改用 StringBuffer 来累加字符串,因 StringBuffer是可变长的,它在原有基础上进行扩增,不会产生中间对象。

5.分散对象创建或删除的时间

集中在短时间内大量创建新对象,特别是大对象,会导致突然需要大量内存,JVM 在面临这种情况时,只能进行主 GC,以回收内存或整合内存碎片,从而增加主 GC 的频率。

集中删除对象,道理也是一样的。它使得突然出现了大量的垃圾对象,空闲空间必然减少,从而大大增加了下一次创建新对象时强制主 GC 的机会。

6.尽量少用 finalize 函数。

因为它会加大 GC 的工作量,因此尽量少用finalize 方式回收资源。

7.如果需要使用经常用到的图片,可以使用软引用类型,它可以尽可能将图片保存在内存中,供程序调用,而不引起 OutOfMemory。

8.能用基本类型如 int,long,就不用 Integer,Long 对象

基本类型变量占用的内存资源比相应包装类对象占用的少得多,如果没有必要,最好使用基本变量。

9.增大-Xmx

java年轻代minor gc_jvm之年轻代(新生代)、老年代、永久代以及GC原理详解、GC优化...相关推荐

  1. jvm之年轻代(新生代)、老年代、永久代以及GC原理详解

    关于JVM,也许你听过这些术语:年轻代(新生代).老年代.永久代.minor gc(young gc).major gc.full gc 不要急,先上图,这是jvm 堆内存结构图 仔细的你发现了 图中 ...

  2. jvm中的年轻代 老年代 持久代 gc ----------转载

    jvm中的年轻代 老年代 持久代 gc 虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation) ...

  3. GC 年轻代 老年代 持久代

    转载自:http://www.cnblogs.com/yaoyuan23/p/5587548.html 虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Gener ...

  4. jvm中的年轻代 老年代 持久代 gc

    虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation).其中持久代主要存放的是Java类的类信 ...

  5. java Parallel gc_JVM Parallel Scavenge GC日志详解

    Parallel Scavenge 日志格式 -XX:+PrintGCDetails [GC (Allocation Failure) [PSYoungGen: 127520K->20064K( ...

  6. GC算法 (标记清除、复制、标记整理、 分代收集) 、 新生代 老年代

    一.标记-清除算法(Mark-Sweep)   1标记阶段:首先通过根节点,标记所有从根节点开始的可达对象.未被标记的对象就是未被引用的垃圾对象 2清除阶段:清除所有未被标记的对象. 不足:1效率问题 ...

  7. 一位读者小姐姐的阿里Java后台面经分享,快被问哭了!(附部分问题详解)

    我是 Guide 哥,一 Java 后端开发,半个全栈,自由的少年. 这篇文章是一位 女读者 (加粗!太难得)的面试阿里的经历分享,虽然第二面面完就失败了,但是这样的经历对自己帮助还是很大的. 下面的 ...

  8. WEB后台--邮件和短信业务实现(包括Java一键实现、封装和异步)以及原理详解

    本来就打算针对一些固定的特别点的业务(QQ与网易邮件.拦截设计.短信.定时器等等)来进行记录以及解析原理,这些会比较零散记录在JavaWeb的分类里面,感兴趣的童鞋可以去看下. 有人问为什么要邮件短信 ...

  9. 【JVM】Java垃圾回收机制(GC)详解

    Java垃圾回收机制(GC)详解 一.为什么需要垃圾回收? 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收.除非内存无限大,我们可以任性的分配不回收,但是事实并非如 ...

最新文章

  1. centos安装easy_instal
  2. 学习进度条--第七周
  3. 2020-10-30(smali复杂类解析)
  4. python for in语句 index_使用for循环查找句子中的单词及其索引位置
  5. 科目三并不难 盘点科目三技巧
  6. Web 前端攻防 2014
  7. 库存盘点应用的工具盘点机
  8. 学习笔记TF065:TensorFlowOnSpark 1
  9. 制作app软件具体要多少钱?(整合篇)
  10. c语言对英文字母循环加密,加密英语
  11. supergo定位软件_super go定位修改下载
  12. Hadoop版本区别Hadoop组成
  13. 2019年7-9月新发布的主流手机品牌型号参数
  14. 题目:在C语言中,表达式23|2^5的值是()
  15. 观景台售票情况数据分析【Python】
  16. 尚硅谷 宋红康老师 Java视频全程课程目录
  17. python词频统计GUI(thinter)
  18. 极路由KMS_Activator插件使用教程
  19. Maven 自定义 archeType
  20. 只需五步!哈佛学霸教你用Python分析相亲网站数据,在两万异性中找到真爱

热门文章

  1. 智慧物业综合解决方案
  2. python写游戏与c语言转化,使用ctypes实现python类型和C语言类型之间的相互转化
  3. 可以把将日文汉字转换成平假名、片假名、罗马音的KaKaSi
  4. 搭建基于github的个人网站
  5. 独立站SEO如何分析竞争对手之策略与教程
  6. ACGAN与CGAN的区别
  7. hisi3559平台PCIE转USB调试
  8. Windows安装配置FitNesse
  9. 1分钟了解流程图、顺序图、状态图
  10. 【虚拟化】virsh指令大全