为什么要分代

为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描。因为每次回收都需要遍历所有存活对象,但实际上,对于生命周期长的对象而言,这种遍历是没有效果的,因为可能进行了很多次遍历,但是他们依旧存在。不同的对象的生命周期是不一样的,因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。因此,分代垃圾回收采用分治的思想,进行代的划分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。

对象代的划分

虚拟机中共划分为三个代:年轻代(Young Generation)、老年代(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java类的类信息,与GC要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。

年轻代

主要是用来存放新生的对象。所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。

HotSpot JVM中年轻代分三个区:一个Eden区,两个Survivor区(一般而言)。

默认比例为8:1,为啥默认会是这个比例,接下来我们会聊到。一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到年老代中。

因为年轻代中的对象基本都是朝生夕死的(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。

在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为“To”的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

老年代

在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

持久代:

用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=<N>进行设置。

什么情况下触发垃圾回收

由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Minor GC和Full GC。

Minor GC

一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Minor GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

Full GC

对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:

· 年老代(Tenured)被写满

· 持久代(Perm)被写满

· System.gc()被显示调用

·上一次GC之后Heap的各域分配策略动态变化

几个常见的问题FAQ:

Minor GC 和 Full GC 有什么区别?

Minor GC:收集生命周期短的区域(Young area)。

Full GC(或Major GC):收集生命周期短的区域(Young area)和生命周期比较长的区域(Old area),对整个堆进行垃圾收集。

他们的收集算法不同,所以使用的时间也不同。 Minor GC 效率也会比较高,我们要尽量减少 Full GC 的次数。

Minor GC后,Eden是空的吗?

是的,Minor GC会把Eden中的所有活的对象都移到Survivor区域中,如果Survivor区中放不下,那么剩下的活的对象就被移到Old generation 中。

常见的内存泄露错误

很多开发人员都碰到过java.lang.OutOfMemoryError的错误。这种错误又分两种:java.lang.OutOfMemoryError: Java heap space和java.lang.OutOfMemoryError: PermGen space。引起这种错误的原因可能是程序问题,也可能是是JVM参数配置问题引起的。若是参数问题,前者可以同过配置-Xms和-Xmx参数来设置,而后者可以通过配置 -XX:PermSize和-XX:MaxPermSize来设置。

GC参数设置

堆设置  
-Xms125m  【初始堆大小】  
-Xmx256m 【最大堆大小】  
-XX:NewSize=64M 【设置年轻代大小  】
 -XX:NewRatio=n 【设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4  】
 -XX:SurvivorRatio=n 【年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 】
-XX:MaxPermSize=n 【设置持久代大小】  
收集器设置  
-XX:+UseSerialGC 【设置串行收集器 】 
-XX:+UseParallelGC【 设置并行收集器  】
-XX:+UseParalledlOldGC 【设置并行年老代收集器  】
-XX:+UseConcMarkSweepGC 【设置并发收集器  】
垃圾回收统计信息  
-XX:+PrintHeapAtGC 【GC的heap详情 】
-XX:+PrintGCDetails  【GC详情 】
-XX:+PrintGCTimeStamps  【打印GC时间信息 】
 -XX:+PrintTenuringDistribution    【打印年龄信息等】
-XX:+HandlePromotionFailure   【老年代分配担保(true  or false)】
并行收集器设置  
-XX:ParallelGCThreads=n 【设置并行收集器收集时使用的CPU数。并行收集线程数。  】
-XX:MaxGCPauseMillis=n 【设置并行收集最大暂停时间  】
-XX:GCTimeRatio=n 【设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)  】
并发收集器设置  
-XX:+CMSIncrementalMode 【设置为增量模式。适用于单CPU情况。  】
 -XX:ParallelGCThreads=n 【设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。】

同类随笔

Java虚拟机笔记(一):类加载机制

Java虚拟机笔记(二):GC垃圾回收

Java虚拟机笔记(三):垃圾收集算法

Java虚拟机笔记(四):垃圾收集器

Java虚拟机笔记(五):JVM中对象的分代

参考:
https://my.oschina.net/sunnywu/blog/332870

http://pengjiaheng.iteye.com/blog/524024

转载于:https://www.cnblogs.com/study-everyday/p/7073672.html

Java虚拟机笔记(五):JVM中对象的分代相关推荐

  1. JVM中对象的分代年龄

    堆内存 Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象. 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old ).新生代 ...

  2. 深入学习Java虚拟机笔记

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.走进Java 1.4.2 HotSpot VM 1.4.4 BEA JRockit/IBM J9 VM 1.6.1 ...

  3. Java虚拟机详解----JVM常见问题总结

    [正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...

  4. Java系列笔记(4) - JVM监控与调优【转】

    Java系列笔记(4) - JVM监控与调优[转] 目录 参数设置 收集器搭配 启动内存分配 监控工具和方法 调优方法 调优实例       光说不练假把式,学习Java GC机制的目的是为了实用,也 ...

  5. Java学习笔记(五):一张图总结完JVM8基础概念

    Java学习笔记(五):一张图总结完JVM8基础概念 引文 最近在学习JVM的相关内容,好不容易把基础概念全部都学了一遍,却发现知识网络是零零散散的.迫不得已,只好再来一次总的归纳总结.为了更好的理解 ...

  6. 详解JVM内存管理与垃圾回收机制3 - JVM中对象的内存布局

    在Java语言层面,可以通过Class类来描述普通的Java类,当JVM创建对象的同时,会生成对应的Class对象,用来描述此对象的大致模型,这也是反射的基础.那么在JVM的内部是如何描述一个普通的对 ...

  7. 【Java虚拟机规范】JVM类加载机制

    [Java虚拟机规范]JVM类加载机制 理论知识 一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载(Loading).验证(Verification).准备(Prep ...

  8. [转载] JVM中对象的回收过程

    参考链接: JVM是否创建Main类(具有main()的类)的对象 当我们的程序开启运行之后就,就会在我们的java堆中不断的产生新的对象,而这是需要占用我们的存储空间的,因为创建一个新的对象需要分配 ...

  9. Java 虚拟机笔记

    概述 JDK 包含了Java语言.Java虚拟机和Java API 类库这三部分,是Java 程序开发的最小环境.JRE 包含了Java API 中的Java SE API子集和Java虚拟机这两部分 ...

最新文章

  1. 分享5个有趣的 JavaScript 代码片段
  2. golang安装beego报错:go: cannot use path@version syntax in GOPATH mode
  3. 04-CoreData Stack技术栈堆手动实现
  4. Win7 Matlab 7.0 Runtime Error
  5. Linux环境下安装Tigase XMPP Server
  6. linux安装trac+svn+apache+wike,windos中Trac+apache+svn的安装与配置
  7. Python--简单的端口扫描脚本
  8. bzoj 1096 斜率优化DP
  9. SQL语法用like %或in时Parameters要怎么用才能避免SQL Injection的问题
  10. android viewpager 缩放,android – 使用ViewPager实现捏缩放
  11. 流式布局和viewport
  12. sqlalchemy入门记录
  13. Refactoring: Encapsulate Collection
  14. 2016.12.30非线性优化计算方法1
  15. win10 nginx设置开机启动 --亲测有效
  16. 传播小知识:timeout限制时间命令
  17. 技校考计算机专业大专考什么科目,高职专科考试科目有哪些 考什么内容
  18. Webrtc 回音消除 一
  19. php tp5 cms,thinkphpcms
  20. Bessie Goes Moo(暴力)

热门文章

  1. 自顶向下 计算机网络知识,计算机网络(自顶向下)第七版考试复习要点(第四章)...
  2. 点击高德地图标注没法弹窗_如何在地图上标注我的店铺
  3. 592zn rom/apk 自动签名工具_关于邮件签名证书的常见问题
  4. 爱普生690k打印针测试软件_办公室打印机什么牌子好 办公室打印机怎么选购【详解】...
  5. 清空文件夹_回收站不小心被清空?简单3步即刻找回丢失文件,值得收藏!
  6. html百分比单位,视窗单位 vs 百分比单位
  7. linux中文件大小设置函数,truncate函数和ftruncate修改文件大小-linux
  8. 在linux服务器搭建函数,linux ftp服务器搭建
  9. 计算机 专升硕,2020新西兰专升硕计算机专业可选院校有哪些?新西兰专升硕途径详解!...
  10. quadprog函数的介绍和应用,二次规划函数