精华内容
下载资源
问答
  • JVM触发老年代GC的情景收集 当年代可用内存小于新生代对象总大小时,根据是否开启了允许空间担保失败,决定是否进行Full GC 相关参数:HandlePromotionFailure 如果设置HandlePromotionFailure = true了,那么...

    JVM触发老年代GC的情景收集

    • 新生代Minor GC后存活对象大于Survivor空间时,对象会直接进入老年代,此时老年代可用空间不足时会触发Full GC
    • 老年代可用内存大小 小于 历次新生代GC后进入老年代的平均对象大小,此时会提前进行Full GC
    • 如果设置了“-XX:CMSInitiatingOccupancyFaction”参数,比如设置成“92%”,那么老年代空间使用超过92%时,就会触发Full GC
    展开全文
  • 似乎线上出现过更为恶略内存环境下的FullGC,不过忘记了是什么环境下和条件下了,就是除了Parnew和CMS外,是否有在内存更为紧张的情况的GC模式;JDK6的环境下
  • -XX:+HandlePromotionFailure 老年代分配担保(true or false) 并行收集器设置  -XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数。并行收集线程数。  -XX:MaxGCPauseMillis=n :设置并行收集...

    1. Java堆中各代分布:

    图1:Java堆中各代分布

    Young:主要是用来存放新生的对象。

    Old:主要存放应用程序中生命周期长的内存对象。

    Permanent:是指内存的永久保存区域,主要存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域. 它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。

     

    2. JVM 使用的GC算法是什么?

    分代收集。

    即将内存分为几个区域,将不同生命周期的对象放在不同区域里;

    在GC收集的时候,频繁收集生命周期短的区域(Young area);

    比较少的收集生命周期比较长的区域(Old area);

    基本不收集的永久区(Perm area)。

     

    3. GC 和 Full GC 有什么区别?

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

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

    他们的收集算法不同,所以使用的时间也不同。 GC 效率也会比较高,我们要尽量减少 Full GC 的次数。 当显示调用System.gc() 时,gc does a full collection(both young generation and tenured generation).

     

    4. Minor GC后,Eden是空的吗?

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

     

    5. Garbage collection options(JDK1.4):

    图2:GC参数

    堆设置  
    -Xms :初始堆大小  
    -Xmx :最大堆大小  
    -XX:NewSize=n :设置年轻代大小  
    -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数。并行收集线程数。

     

    6. 例子:Heap size 设置

    场景:在JAVA_HOME下demo/jfc/SwingSet2/目录下执行下面的命令:

        java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar

    系统输出:

     

    Exception in thread "Image Fetcher 0" java.lang.OutOfMemoryError: Java heap space

    Exception in thread "Image Fetcher 3" java.lang.OutOfMemoryError: Java heap space

    Exception in thread "Image Fetcher 1" java.lang.OutOfMemoryError: Java heap space

    Exception in thread “Image Fetcher 2” java.lang.OutOfMemoryError: Java heap space

    调优:将-Xms和-Xmx选项设置为32m,而-Xmn为1/4的-Xmx值。

    结果:执行java -jar –Xmn8m –Xms32m -Xmx32m SwingSet2.jar,系统正常运行。

     

    7. JVM  Runtime Data Area(运行时数据区):

    图3:JVM运行时数据区(一)

    Heap: JVM只有一个为所有线程所共享的堆,所有的类实例和数组都是在堆中创建的。

    Method area: JVM只有一个为所有的线程所共享的方法区。它存储类结构,例如运行时常量池,成员和方法数据以及方法、构造方法的代码。

    Java Stacks:每个JVM线程拥有一个私有的栈。

    Pc registers: JVM可以同时支持运行多个线程,因此每个线程需要各自的PC(program counter)寄存器。

    Native method stacks: 保存native方法进入区域的地址 。

     

    图4:JVM运行时数据区(二)

    Heap和Method area被所有线程共享,其生存期和JVM的生存期相同;Java Stacks、Pc registers、Native method stacks被每个线程独自拥有,其生存期和线程的生存期相同。

     

     

     

    8. 常见的内存泄露错误

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

                                

    9. 参考资料:

     

    1.  A brief history of garbage collection –

    http://www-128.ibm.com/developerworks/java/library/j-jtp10283/

    2.  Garbage collection in the HotSpot JVM –

    http://www-128.ibm.com/developerworks/java/library/j-jtp11253/

    3.  Tuning Garbage Collection with the 5.0 JavaTM Virtual Machine

    http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html

    4.  Diagnosing a GC problem –

    http://java.sun.com/docs/hotspot/gc1.4.2/example.html

    5、http://www.precisejava.com

     

    GC (minor )日志 
    Full GC 日志
    -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:-HandlePromotionFailure -XX:+PrintHeapAtGC -XX:+PrintGCTimeStamps 
    -XX:+PrintGCDetails -XX:+PrintTenuringDistribution
    展开全文
  • 调整JVM参数如下: -XX:NewSize=104857600—新生代大小为100m -XX:MaxNewSize=104857600—...-XX:+UseConcMarkSweepGC---老年代使用CMS -XX:+PrintGCDetails---打印GC详细日志 -XX:+PrintGCTimeStamps—打印GC时间 .

    调整JVM参数如下:

    -XX:NewSize=104857600—新生代大小为100m
    -XX:MaxNewSize=104857600—新生代最大大小为100m
    -Xms200M—初始堆大小为200m
    -Xmx200M—最大堆大小为200m
    -XX:+UseParNewGC:新生代使用ParNewGC垃圾回收器
    -XX:+UseConcMarkSweepGC---老年代使用CMS
    -XX:+PrintGCDetails---打印GC详细日志
    -XX:+PrintGCTimeStamps—打印GC时间
    -XX:SurvivorRatio=8—设置eden区和survivor区的比例为8:1:1
    -XX:PretenureSizeThreshold=209715200—设置最大对象的阈值为20m
    

    测试demo

    package com.example.springboot.jvm;
    
    import java.util.concurrent.TimeUnit;
    
    public class 年轻代gc耗时真的比老年代短 {
        public static void loadData() throws InterruptedException {
            byte[] data = null;
            for (int i = 0; i < 4; i++) {
                //每个请求10m
                data = new byte[10 * 1024 * 1024];
            }
            data = null;
            byte[] data1 = new byte[10 * 1024 * 1024];
            byte[] data2 = new byte[10 * 1024 * 1024];
            byte[] data3 = new byte[10 * 1024 * 1024];
            data3 = new byte[10 * 1024 * 1024];
            //睡眠1秒
            TimeUnit.SECONDS.sleep(1);
        }
    
        public static void main(String[] args) throws InterruptedException {
            //这里睡眠20秒是为了能够有足够的时间打命令,看到的效果可以更直观
            TimeUnit.SECONDS.sleep(20);
            while (true) {
                loadData();
            }
        }
    }
    

    启动服务,进入命令行界面。

    先输入命令jps,查看各个进程,结果如下:

    在这里插入图片描述
    从结果中可以得到启动程序对应的进程号为3222。

    输入命令jstat -gc 3222 1000 1000,表示统计进程3222的JVM运行状态,然后每隔一秒钟打印统计信息,持续打印1000次,结果如下:

    在这里插入图片描述
    可以发现EU列(Eden区)每次大概增加10M左右的对象,OU列(老年代)每次大概新增20~30M左右的对象,同时每秒触发一次新生代GC,老年代大致每3秒一次GC,不过此时的YGCT(年轻代GC总耗时)远远大于FGCT(老年代GC总耗时),即使双方各除以他们的总次数YGC(年轻代GC总次数)或者FGC(老年代GC总次数),年轻代GC的平均耗时也远远大于老年代GC的耗时。

    这里先解释下为什么Eden区每次大概增加10M左右的对象,老年代每次大概新增20~30M左右的对象?

    首先堆的大小设置为200,新生代的大小被设置为100M,同时Eden区和两个Survivor区的比例是8:1:1,那么Eden区的大小就是80M,两个Survivor区各为10M,老年代的大小为100M。

    回顾代码,每秒会新建40M左右的对象,然后立马置空,让这40M对象失去引用变成垃圾对象,接着继续新建了data1,data2,data3三个对象,每个对象大小各为10M,这时候Eden区就被占用了大致70M左右的空间,最后又将data3变量引用指向另一个10M对象,此时Eden区空间已经不够分配这10M对象了,所以会触发新生代GC,此时40M垃圾对象会被回收,但是data1,data2,data3这三个变量的引用还是有效的,所以GC后一共有30M左右的对象存活,而Survivor区只有10M大小,是放不下30M对象的,因此这30M对象会直接被分配到老年代,然后再分配data3变量最后引用的10M对象,所以每秒Eden区会被占用10M空间。

    为什么此时的年轻代gc耗时比老年代长?

    一般来说,在固有的印象里,年轻代gc耗时比老年代要短得多,真正影响系统性能的应该是老年代GC产生的STW时间,但是在该示例中,年轻代的gc耗时比老年代要长,这是因为,老年代每次会新增20~30M左右的对象,新生代GC后的存活对象有30M左右,老年代空间放不下时,就会触发Full GC,腾出空间后,等到存活对象进入老年代了,新生代GC才算结束。因此可以理解成,本次的新生代GC时间其实是叠加了老年代GC时间的,所以新生代gc耗时才会比老年代长。

    总结

    如果每次年轻代GC时,都会触发老年代GC,那么年轻代GC耗时就会比老年代长了。

    展开全文
  • JVM老年代垃圾回收Full GC

    千次阅读 2020-08-07 13:53:56
    老年代GC:FullGC 是年代的GC,在新生代如果说存在的对象或者说新创建 出来的对象由于某些原因需要移动到年代中,但是年代中压根就没有这么大的内存空间去容纳这个对象, 那么就会引发一次FullGC,如果在执行...

    老年代GC:FullGC 是老年代的GC,在新生代如果说存在的对象或者说新创建 出来的对象由于某些原因需要移动到老年代中,但是老年代中压根就没有这么大的内存空间去容纳这个对象, 那么就会引发一次FullGC,如果在执行完FullGC之后,还是没有办法给这些对象分配内存,那么凉了,该抛出异常了,异常类型就是OutOfMemoryError。

    FullGC危害:在发生FULL GC的时候,意味着JVM会安全的暂停所有正在执行的线程(Stop The World),来回收内存空间,在这个时间段内,所有除了回收垃圾的线程外,其他有关JAVA的程序,代码都会静止,反映到系统上,就会出现系统响应大幅度变慢,卡机等状态。

    而FullGC使用的是和MinorGC不一样的算法,它使用的是标记清除算法,听名字,挺好理解的,来波图示解析一波。 深入了解JVM一书中的图示是这个样子的,

    看名字的话是先标记,然后在删除。这也是也给最最基本的算法。 这个算法就是分两个步骤

    •标记(Mark)过程:找到所有的可以访问的对象,做个指定的标记。

    •清除(Swep)过程:遍历堆内存,把未标记的对象进行一个回收。

    在了解了这个之后,我们还得说一个概念,那就是GC Root,Root我们可以理解成一个根节点就像这个样子

     

    上图中的a,b,c,d,就是活着的对象,如果说存在这引用,比如说b引用的a,那么a他就是属于活着的对象。 当我们老年代内存区中的有效的内存空间不够的时候,那么这时候整个世界都要安静下来了(stop the world),这时候就要开始准备进行垃圾回收了。

    •标记:遍历所有的GC Roots,然后将所有GC Roots可达的对象标记为存活的对象。就是我们图中所标记的a,b,c,d.•清除:清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。 也就是说,如果内存不够,GC线程就会被触发然后将程序暂停,随后将依旧存活的对象标记一遍,最后再将堆中所有没被标记的对象全部清除掉,接下来便让程序继续恢复运行。 

    流程图就想这个样子的 初始下的老年代中的对象状态

     

    这时候都是没有被标记的状态,接下来内存不够,GC线程停止,开始进行标记了

     

    按照根节点开始遍历 标记的abcdeh都是存活的对象,接下来开始标记。

    接下来就是清除数据了,这个就更加的简单了

    清楚完成之后还有就是把标记去除掉,可以下次进行标记清除的时候继续清除

    这样标记清除就执行完毕了,剩下还有两个要说的地方,

     一是在进行标记清楚算法的时候为什么要让程序停止,(stop the world)。

     二是标记清除算法的优点和缺点又是什么?(Stop the World)

    程序停止其实可以理解,因为如果说不停止程序的话,我们在标记完成这个b对象之后,我们new出一个新的对象J,可以从B指向J,也就是说,这时候J应该是被标记的状态,但是实际情况肯定不是,这个对象在B标记完之后,马上都要结束了,我们又new出来一个对象,可想而知,他肯定是没有被标记的,所以在第二阶段进行清除的时候,这个苦命的J将会被清除掉, 那这样肯定是不符合我们的实际情况的。

    你想呀这刚刚new出来的对象结果被清除了,忽然变成了空值,那就不符合我们的要求了。所以他会让程序先停止,然后不会再出现这种情况,然后进行开始标记阶段。

     

    优缺点

    首先我们可以先看缺点,他的缺点非常明显,

    •因为他会递归遍历Root,这样的话 Stop the World的时间就比较长了,这样一直让人等待的滋味可不是那么好受。•第二个就是这种清除方式清除出来的内存空间是不连续的,你看这个图

     

    死亡的上下分成了2部分,是不连续的,这样给JVM又造成了一种额外的负担,他需要去维持一个内存的空闲列表,如果说我们在这时候去new一个数组,你想想他去找这个连续的内存空间的话,是不是就要困难很多呢?

    他的优点也有,

    •比如说不会出现循环引用, 我们可以想想 两个类 互相引用,A中newB,B中newA,那这样岂不是a.b=b ,b.a = a ,是吧 ,而标记清除算法在走完了之后,是可以回收a,和b的,因为他是从根元素开始遍历标记,也就是从ab开始,那么单一的a和单一的b就是没有被标记的,所以,这样就避免了循环引用的问题•还有一点感觉没啥区别,都是内存不够的时候才进行的引用。这没啥说的。

    标记--整理算法

    而因为标记--清除算法会导致内存分配都出现了各种不均匀的空间,这时候就有了另外的一种算法,直接把那些存活的对象标记出来,然后给他怼到内存空间边界,然后剩下的直接全给他清除了。这方法图解看的一清二楚,剩下的都是和标记清除算法一样的,好像没啥解释的,直接上图

    展开全文
  • JVM 新生代老年代GC

    千次阅读 2019-08-06 21:57:51
    Java堆可以分为新生代和老年代两个区,其中新生代又可以分为一个Eden区和两个Survivor区,两个Survivor区分别被命名为From和To以示区分,新生代和老年代的比例为1:2,它们共同组成堆的内存区,所以新生代占堆的1/3...
  • Full GC(老年代GC):指发生在年代的GC,速度一般比 Minor GC 慢十倍以上。如果有Full,说明这次GC发生了Stop-The-World。 2. 什么时候对象进入年代? 大对象直接进入年代。 虚拟机提供了一个阈值参数,令...
  • 老年代GC(major gc) —— 指发生在年代的垃圾回收动作,用的是“标记--整理”算法。  年代几乎都是经过survivor熬过来的,它们不会那么容易“死掉”,因此major gc不会像minor gc那样频繁。   六、...
  • 年轻代、老年代GC原理详细拆解

    千次阅读 2018-06-29 14:25:42
    其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描。而我们的很多对象都是朝生夕死的,如果...
  • 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象...
  • 关于JVM,也许你听过这些术语:年轻代(新生代)、老年代、永久代、minor gc(young gc)、major gc、full gc 不要急,先上图,这是jvm 堆内存结构图 仔细的你发现了 图中有些分数8/10和1/10,这是默认配置下各个...
  • JVM的新生代、老年代、MinorGC、MajorGC 参考资料: http://blog.csdn.net/flamezyg/article/details/44673951 http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html ...
  • JVM新生代老年代GC分析

    千次阅读 2018-08-20 09:25:18
    老年代 标记压缩法 老年代特点 GC不频繁,相对稳定 每次清理内存,清理的比较少 已经经历了很多次的GC 每次回收耗时非常长 比如,有100个对象 可能90个都需要压缩拷贝到内存的另一端,...
  • 1.躲过15次GC之后进入老年代 系统刚启动时,创建的各种各样的对象,都是分配在年轻代里。 随着慢慢系统跑着跑着,年轻代满了,就会出发MinorGC ,可能1%的少量存活对像转移到空着的Survivor区中 然后系统继续运行...
  • 前言 JVM的自动垃圾回收处理的是不再使用的对象/数组, 这些对象/数组都是存储在堆内存中 新生代/老年代 MinorGC和FullGC 7个垃圾收集器
  • java虚拟机老年代回收GC---CMS

    千次阅读 2018-05-22 13:54:56
    转自:http://www.iteye.com/topic/11194911.总体介绍:CMS(Concurrent Mark-Sweep)是以...在启动JVM参数加上-XX:+UseConcMarkSweepGC ,这个参数表示对于老年代的回收采用CMS。CMS采用的基础算法是:标记—清除。2...
  •  发生在老年代GC称为Full GC,又称为Major GC,其经常会伴随至少一次的Minor GC(并非绝对,在Parallel Scavenge收集器中就有直接进行Full GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。
  • JAVA虚拟机:新生代和老年代GC

    千次阅读 2016-07-14 20:53:20
    Java堆可以分为新生代和老年代两个区,其中新生代又可以分为一个Eden区和两个Survivor区,两个Survivor区分别被命名为From和To以示区分,新生代和老年代的比例为1:2,它们共同组成堆的内存区,所以新生代占堆的1/3...
  • Java中的新生代、老年代、永久代和各种GC 转载自: 《JVM的新生代、老年代、MinorGC、MajorGC》 JVM中的堆,一般分为三大部分:新生代、老年代、永久代: 1 新生代 主要是用来存放新生...
  • jvm中的年轻代 老年代 持久代 gc详解

    千次阅读 2017-03-17 10:40:33
    1.Java回收机制基本知识总结:请点此链接 2.jvm中的年轻代 老年代 持久代 gc详解:请点此链接
  • 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象...
  • ![图片说明](https://img-ask.csdn.net/upload/201706/22/1498113926_13383.png) 如上图 上面的GC 和fullgc代表什么含义 我看有种说法是gc代表新生代,fullgc代表所有代的gc 不知道对不对
  • 四种主要的垃圾回收器: * Serial(串行...最后实现的就是: 六、串行GC(Serial Old)(Serial MSC) 其实就是年轻代的串行搬到了老年代而已 结果: 6中垃圾回收器(G1还没讲)总结: 一些新代垃圾回收器的经典组合:
  • 是由回收算法不一样决定的。 minor gc是新生代的“复制”(Copying)算法:将现有的内存空间分为两... full gc老年代,采取的“标记-整理”(Mark-Compact)算法,先需要从根节点开始对所有可达对象做一次标记,...
  • Java GC、新生代、老年代

    千次阅读 2015-03-27 11:49:00
    堆内存  Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。...在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为
  • 尽量腾出一点空间 (但是在jdk1.6 update 24之后-XX:-HandlePromotionFailure 不起作用了,只要老年代的连续空间大于新生代对象的总大小或者历次晋升到老年代的对象的平均大小就进行MinorGC,否则FullGC) fullGC完毕...
  • GC 关于JVM堆区的划分,请转至JVM垃圾回收机制 查看,感谢。 1.垃圾回收机制过程 2.什么时候发生minor GC和Full GC? 3.为什么要进行minor GC? 4.初始化的对象会被放在什么地方呢? 对象的内存分配策略 两个存储...
  • 什么情况下会触发年轻代或者老年代GC,对应使用ParNew和CMS的Hotspot而言?
  • JVM运行时内存 堆 Java堆从GC角度细分为:新生代和老年代 新生代 Eden From Servivor To Servivor 老年代
  •  正常情况下,一个对象从创建到销毁,应该是从Eden,然后到Survivor Spaces(幸存区),再到Old Generation(年老代),最后在某次GC下消失。  当然,一个对象也可能直接在Eden里死掉,也可能一直在Old ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 62,834
精华内容 25,133
关键字:

老年代gc