精华内容
下载资源
问答
  • 关于JVM,也许你听过这些术语:年轻代(新生代)、老年代、永久代、minor gc(young gc)、major gc、full gc 不要急,先上图,这是jvm 堆内存结构图 仔细的你发现了 图中有些分数8/101/10,这是默认配置下各个...

    关于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时间,避免全区扫描。

    展开全文
  • JVM内存中的年轻代老年代

    千次阅读 2018-07-25 00:02:45
    对于大多数Java应用来说,Java Heap(Java堆)是JVM管理的内存中较大的一块,而且Java Heap是被所有线程共享的一块内存区域,于虚拟机启动时创建。 而Java堆的唯一目的就是存放对象实例。 由于Java堆是垃圾收集器...

    引言

    对于大多数Java应用来说,Java Heap(Java堆)是JVM管理的内存中较大的一块,而且Java Heap是被所有线程共享的一块内存区域,于虚拟机启动时创建。

    而Java堆的唯一目的就是存放对象实例。

    由于Java堆是垃圾收集器管理的主要区域,因此也被称为"GC堆"。

    再从内存回收的角度来看,由于现代收集器基本都采用分代收集算法,所以Java Heap还可以被细分为:

    新生代和老年代,新生代再分得细致一点就可以分为Eden空间和两个相同大小相同的Survivor空间,下面来谈谈新生代和老年代。

     

    新生代

    先上一张图(图是盗的,来自https://blog.csdn.net/sted_zxz/article/details/72476673)

    通俗理解就是新创建的对象就是先进入新生代,然后创建久而且还未被回收的对象自然而然就进入老年代。

    上面说了,年轻代又分为一个Eden空间和两个Survivor空间,这样分的意义是什么呢,这里不得不说一下一个垃圾收集算法:

    复制算法:

    这里不得不又介绍一下

    传统的标记清除算法:就是首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

    该算法有如下缺点:
       1.效率问题
       2.空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作。

    (图是截书上的,应该看得清吧)

    所以复制算法就是主要为了解决以上的缺点,复制算法就是将可用内存按容量划分为大小相等两块,每次只使用其中的一块,

    当这一块的内存用完了,就将还存活着的对象复制道另外一块上面,然后再把已使用过的内存空间一次清理掉,这样每次都是对整个半区进行内存回收,所以内存分配时也就不用去考虑内存碎片等复杂情况了,但是这种算法也有一个很明显的缺点,会缩小实际可以使用的内存,这里就直接缩小了一半!

    而其实年轻代这样分配Eden和两个两个Survivor其实就是采用了复制算法的思想,不过这就没有每次都只使用一次这么夸张,这里年轻代每次都只使用Eden和一个Survivor,即新创建的对象都放入Eden和一个Survivor,如果内存不够,就会先把这两个空间上还存活的对象放入另一个Survivor空间,然后进行Minor GC。

    而新生代为什么要采用这种算法呢,这是因为新生代的对象大部分都是“朝生夕死”,因此这里虽然采用了复制算法的思想,但是并不需要按1:1来划分空间,而只需要分配一小部分空间给Survivor即可,HotSpot虚拟机默认Eden和Survivor比例是8:1 ,即每次新生代可用内存空间为90%,当然如果在这种情况下由超过10%的对象存活(因为这里一个Survivor空间只有10%),即进行过一次Minor GC之后,一个Survivor空间装不下存活的对象,这就需要老年代进行分配担保了。

    设置新生代空间:

    1.直接对新生代大小进行设置  -Xmn   例如:-Xmn10M   新生代大小为10M(eden+ 2 survivor space)

    2.通过设置老年代与新生代的比例来设定  -XX:NewRatio 例如:-XX:NewRatio=4 

    (表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5,Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置)

    设置Eden与Survivor的比例:-XX:SurvivorRatio 例如:-XX:SurvivorRatio=8

    (则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10)

    老年代

    上面说过经过Minor GC之后,如果Survivor存放不下存活的对象,对象就会通过分配担保机制进入老年代,而如果老年代空间还不够,就会进行Full GC。

    老年代使用的回收算法是标记整理算法:

    该算法也有标记过程,和标记清除算法一样,但是后面不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存:

    进入老年代除了以上那种情况还有以下情况:

    1.大对象直接进入老年代

    大对象是需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串以及数组,
    经常出现大对象容易导致内存还有不少空间时就提前出发垃圾收集以获取足够的连续空间来安置它们。

    虚拟机提供了 -XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配,
    目的是避免在Eden区以及两个Survivor区之间发生大量的内存赋值(新生代采用复制算法收集内存)
     

    2.长期存活的对象即将进入老年代

    虚拟机给每个对象定义了一个对象年龄计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动道Survivor空间,并且对象年龄设为1,并且每经过一次Minor GC,就会多一岁,当达到一定值时,就会被移动道老年代(默认为15),可以通过设置-XX:MaxTenuringThreshold设置。

    3.动态对象年龄绑定

    如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。

    展开全文
  • 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。 新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象...

    概述

    在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。

    新生代 ( Young ) 又被划分为三个区域:EdenFrom SurvivorTo Survivor

    这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。

    堆的内存模型大致为:
    在这里插入图片描述
    从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。

    默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。

    其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。

    默认的,Eden : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。

    JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。

    因此,一般新生代可用空间=Eden+from,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。

    如何设置划分老年代和新生代的大小

    方法1:通过前文知道默认的比例,那么设置内存的总大小即可,自动按比例划分

    方法2:

    -Xms 堆内存的初始大小,默认为物理内存的1/64
    -Xmx 堆内存的最大大小,默认为物理内存的1/4
    -Xmn 堆内新生代的大小。通过这个值也可以得到老生代的大小:-Xmx减去-Xmn

    可以参见:《《深入理解java虚拟机v3》长期存活的对象将进入老年代 > 代码清单3-9》,里面有实战样例






    参考:
    《JVM老年代和新生代的比例》

    展开全文
  • 本篇文章主要讲解内存区域的年轻代,老年代和永久代,略微提及一些垃圾回收算法,下面是正文。 堆整体 堆主要用于存放各种类的实例对象和数组。在java中被分为两个区域:年轻代和老年代。在java中还有一个永久代的...

    前言

    最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家。本篇文章主要讲解内存区域的年轻代,老年代和永久代,略微提及一些垃圾回收算法,下面是正文。

    堆整体

    堆主要用于存放各种类的实例对象和数组。在java中被分为两个区域:年轻代和老年代。在java中还有一个永久代的意思,这里最后会单独说明。


    年轻代和老年代的划分是为了更好的内存分派及回收。提高效率。
    堆是垃圾回收机制的重点区域。我们知道垃圾回收机制有三种,minor gc,major gc 和full gc。针对于堆的就是前两种。年轻代的叫 minor gc,老年代的叫major gc。

    年轻代

    年轻代用来存放新近创建的对象,尺寸随堆大小的增加和减少而相应的变化,默认值是保持为堆的1/15。
    年轻代的大小可以通过-xmn设置固定大小,也可以通过-xx:newratio设置年轻代和年老代的比例。
    年轻代中存在的对象是死亡非常快的。存在朝生夕死的情况。
    所以为了提高年轻代的垃圾回收效率,又将年轻代划分为三个区域,一个eden和两个sunrvivor from。


    eden和survivor默认比例是8:1:1,进行垃圾回收采用的是分代复制算法。每次新生代的使用,会是eden区和一块survivor区。当我们进行垃圾回收的时候,清除正在使用的区域,将其中的存货对象,放入到另一个survivor区域,并进行整理,保证空间的连续。如果对象长时间存活,则将对象移动到老年区。存活下来的对象,他的年龄会增长1。当对象的年龄一次次存活,一次次增长,到达15的时候,这些对象就会移步到老年代。在年轻代执行gc的时候,如果老年代的连续空间小于新生代对象的总大小,就会触发一次full gc。是为了给新生代做担保,保证新生代的老年对象可以顺利的进入到老年代的内存区。

    老年代

    老年代中存放的对象是存活了很久的,年龄大于15的对象。在老年代触发的gc叫major gc也叫full gc。full gc会包含年轻代的gc。但老年代只要执行gc就一定是full gc。
    full gc采用的是标记-清除算法。会产生内存碎片。在执行full gc的情况下,会阻塞程序的正常运行。老年代的gc比年轻代的gc效率上慢10倍以上。对效率有很大的影响。

    永久代

    永久代是hotspot虚拟机,也就是我们使用的java虚拟机的特有的概念,他不属于堆内存,是方法区的一种实现,各大厂商对方法区有各自的实现。永久代存放jvm运行时,需要的类,包含java库的类和方法,在触发full gc的情况下,永久代也会被进行垃圾回收。永久代的内存溢出也就是 pergen space。

    元空间

    元空间是metaspace,在jdk1.8的时候,jvm移除了永久代的概念,元空间也是对java虚拟机的方法区的一种实现。元空间与永久代最大的区别在于,元空间不在虚拟机中,使用本地内存。通过配置如下参数可以更改元空间的大小。
    -XX:MetaspaceSize:初始空间的大小。达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
    -XX:MaxMetaspaceSize,最大空间,默认是没有限制的。
    永久代的回收会随着full gc进行移动,消耗性能。每种类型的垃圾回收都需要特殊处理元数据。将元数据剥离出来,简化了垃圾收集,提高了效率。

    展开全文
  • JVM 的堆空间分成2个区域:年轻代老年代 年轻代又进一步细分成3个区域:Eden、Survivor From、Survivor To 如下图所示: 默认情况下,年轻代老年代比例为1:2。可以通过参数-XX:NewRatio修改,NewRatio默认值是...
  • 堆整体 java堆的特点《深入理解... 从内存回收的角度来看, 由于现在收集器基本都采用分收集算法, 所以Java堆可以细分为:新生代(Young)和老年代(Old)。 新生代又被划分为三个区域Eden、From Survivor, To
  • JVM内存:年轻代老年代,永久代

    万次阅读 多人点赞 2017-05-18 17:06:57
    1.Java 新生代、老年代、持久、元空间 2.Java内存与垃圾回收调优Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象,如下图所示: 在 Java 中,堆被划分成两个不同的区域:新生代 ...
  • 1.年轻代GC实验-YGC进入Survivor区 1.1 JVM参数设置 #jvm参数配置 -Xms25m #堆内存最小25m -Xmx25m #堆内存最大值25m -Xmn10m #年轻代大小 -Xss1m #线程栈大小 -XX:+UseParNewGC #使用ParNew垃圾回收器 -XX:+...
  • 现有的主流JVM分别是HotSpotJRockit,主要研究对象也是这两个。这篇文章里,我们只研究HotSpot,也就是所谓的Sun JVM。目前阶段,Sun的GC方式主要有CMSG1两种。考虑到效果实际应用,这里只介绍CMS。CMS,全称...
  • 如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代的1/4 -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区...
  • JVM堆内存相关的启动参数:年轻代老年代和永久代的内存分配 2015年03月27日 15:38:48 阅读数:2091 如果想观察JVM进程占用的堆内存,可以通过命令工具jmap或者可视化工具jvisualvm.exe。JVM这些启动参数都拥有...
  • jvm的新生代、老年代、永久关系

    万次阅读 多人点赞 2018-07-08 13:43:44
    原文地址:...通常情况下,对象主要分配在新生代的Eden区上,少数情况下也可能会直接分配在老年代中。Java虚拟机每次使用新生代中的Eden其中一块Survivor(From)...
  • 1.Java 新生代、老年代、持久、元空间 2.Java内存与垃圾回收调优 3.方法区的Class信息,又称为永久,是否属于Java堆? Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象,如下图所示...
  • 秉承不重复造轮子的原则,↓↓↓↓ 传送门:JVM年轻代老年代,永久代详解
  • 所以这里不用在意,当它写错了 三、并行回收GC(Parallel)(Parallel Scavenge) 默认的那个 (俗称:吞吐量优先收集器) 年轻代默认使用 Parallel Old相互激活 使用上面任意一个后,老年代默认开启使用Parallel Old...
  • 1.为什么会有年轻代我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到...
  • jvm中的年轻代 老年代 持久代 gc详解

    千次阅读 2017-03-17 10:40:33
    1.Java回收机制基本知识总结:请点此链接 2.jvm中的年轻代 老年代 持久代 gc详解:请点此链接
  • 文章目录Pre躲过15次GC之后进入老年动态对象年龄判断大对象直接进入老年代Minor GC后的对象太多,无法放入Survivor区怎么办?老年代空间分配担保规则老年代垃圾回收算法 Pre 上篇文章已经讲清楚了新生代的垃圾...
  • JVM 年轻代和年老代 大小设置

    万次阅读 2017-11-22 18:29:48
    年轻代在经过n(hotspot默认是15)轮后会进入老年代, 这样老年代顶不住了,就会触发full gc, 回收时需要 stop the world ,这样系统经 常发生长时间停顿 ,影响系统的 吞吐量 ...
  • 年轻代垃圾回收器ParNew 新生代的辣鸡回收器ParNew,主打的就是多线程回收 另外一种Serial垃圾回收器,主打的是单线程回收 回收算法一样 当ParNew垃圾回收器,在合适的时机进行垃圾回收的时候 会暂停当前的工作线程 ...
  • 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象...
  • 3、JVM 堆内存内部结构 一、Heap Dump是什么? Heap Dump 是Java进程在某个时间点上的内存快照。通常在写heap dump文件前会触发一次FullGC,所以heap dump文件中保存的是FullGC后留下的对象信息。 1、一般在...
  • 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old)。新生代 ( Young ) 又被划分为三个区域:Eden、S0、S1。 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及...
  • 长期存活的对象进入老年 ...对象在Survivor区每熬过一次MinorGC年龄就加一岁,当它的年龄增加到一定程度(默认为15岁)时,就会晋升到老年代中,对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTen...
  • 1.是哪些参数控制了 old:young eden : from 和年轻代老年代的年龄限制的 2.哪些情况会导致 年轻代 越过 15年龄的限制 去到老年代 大家应该知道 jvm年轻代 老年代 方法区等等 大概组成部分 如果不清楚...
  • 年轻代的垃圾收集器包含: Serial、ParNew、Parallell 老年代则包括Serial Old老年代版本、CMS、Parallel Old老年代版本JDK11中的G1收集器。 Serial:单线程版本收集器,进行垃圾回收的时候会STW(Stop The World...
  • 现有的主流JVM分别是HotSpotJRockit,主要研究对象也是这两个。这篇文章里,我们只研究HotSpot,也就是所谓的Sun JVM。目前阶段,Sun的GC方式主要有CMSG1两种。考虑到效果实际应用,这里只介绍CMS。CMS,全称...
  • 所以JVM将Java堆内存划分了两个区域,分别是年轻代和老年代年轻代,顾名思义,就是把创建和使用完之后立马就要回收的对象放在里面; 老年代,就是创建之后需要一直长期存在的对象放在里面。 比如下面的代码...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,485
精华内容 9,394
关键字:

jvm年轻代和老年代