• 对象何时进入老年代、何时发生full gc


     

    一、对象何时进入老年代

    (1)当对象首次创建时, 会放在新生代的eden区, 若没有GC的介入,会一直在eden区, GC后,是可能进入survivor区或者年老代

    (2)当对象年龄达到一定的大小 ,就会离开年轻代, 进入老年代。 而对象的年龄是由GC的次数决定的

    -XX:MaxTenuringThreshold=n  新生代的对象最多经历n次GC, 就能晋升到老年代, 但不是必要条件   

    -XX:TargetSurvivorRatio=n  用于设置Survivor区的目标使用率,即当survivor区GC后使用率超过这个值, 就可能会使用较小的年龄作为晋升年龄

    (3)除年龄外, 对象体积也会影响对象的晋升的, 若对象体积太大, 新生代无法容纳这个对象

    -XX:PretenureSizeThreshold  即对象的大小大于此值, 就会绕过新生代, 直接在老年代分配, 此参数只对串行回收器以及ParNew回收有效, 而对ParallelGC回收器无效

    二、何时发生full gc

    public class ConcurrentMarkSweep {
    
        private static final int SIZE= 1024 * 1024;
    
        public static void main(String[] args) throws Exception{
            byte[] a1, a2, a3, a4;
            a1 = new byte[2 * SIZE];
            a2 = new byte[2 * SIZE];
            a3 = new byte[2 * SIZE];
            a4 = new byte[2 * SIZE];
            System.in.read();
        }
    }

    1. System.gc()方法的调用 
    system.gc(), 此方法的调用是建议JVM进行Full GC, 可通过通过-XX:+ DisableExplicitGC来禁止RMI调用System.gc。 


    2. old/Tenured 空间不足 

    老年代空间在新生代对象转入及创建为大对象、大数组时

    当执行Full GC后空间仍然不足,报错:java.lang.OutOfMemoryError: Java heap space 

    java -Xmx10m -Xms10m -Xmn10m -XX:+UseParNewGC  -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly  -XX:CMSInitiatingOccupancyFraction=75 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC gc.ConcurrentMarkSweep

    3. perm/metaspace 空间不足

    JVM规范中运行时数据区域中的方法区,在HotSpot虚拟机中又被习惯称为永生代或者永生区,

    Permanet Generation中存放的为一些class的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,

    当Full GC后空间仍然不足,报错:java.lang.OutOfMemoryError: PermGen space

    java -cp .:/Users/gl/IntelliJProjects/JBase/jdk/build/tmp/lib/javassist-3.20.0-GA.jar  -XX:MaxMetaspaceSize=32M gc.Metaspace

    在我的MAC上,大约生成21165个class: Exception in thread "main" javassist.CannotCompileException: by java.lang.OutOfMemoryError: Metaspace
    public class Metaspace {
    
       static  ClassPool cp = ClassPool.getDefault();
    
        public static void main(String[] args) throws Exception{
            for (int i = 0; ; i++) {
                System.out.println(i);
                CtClass ctClass = cp.makeClass("com.mp.Person" + i );
                //添加属性
                ctClass.addField(CtField.make("private int age;", ctClass));
                //添加setAge方法
                ctClass.addMethod(CtMethod.make("public void setAge(int age){this.age = age;}", ctClass));
                ctClass.addMethod(CtMethod.make("public int getAge(){return this.age;}", ctClass));
                //If the program is running on some application server, the context class loader might be inappropriate to load the class.
                //如果没有调用,则没影响
                ctClass.toClass();
            }
        }
    }
    
    

    4. CMS GC时出现promotion failed和concurrent mode failure 

    promotion failed是在进行Minor GC时,survivor space放不下, 对象只能放入老年代,而此时老年代也放不下造成的;

    concurrent mode failure是在执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的

    java -Xmx10m -Xms10m -Xmn10m -XX:+UseParNewGC  -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly  -XX:CMSInitiatingOccupancyFraction=75 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC gc.ConcurrentMarkSweep

    5. 判断当前新生代的对象是否能够全部顺利的晋升到老年代,如果不能,就提早触发一次老年代的收集

    java -Xmx14m -Xms14m -Xmn10m -XX:+UseParNewGC  -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly  -XX:CMSInitiatingOccupancyFraction=75 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC ConcurrentMarkSweep

    # JVM 通过 CMSInitiatingOccupancyFraction 的值确定是否gc
    -XX:+UseCMSInitiatingOccupancyOnly
    -XX:CMSInitiatingOccupancyFraction=75

    如下,Meta space 使用为达到75%, 却一直在发生FGC

    如果永久代设置的很小,则会发生系统刚启动就执行CMS

    参考:

    占小狼:一个有意思的CMS问题

  • 相关阅读:
    ptyhon异步开发aiohttp
    python异步编程asyncio
    python ThreadPoolExecutor线程池和ProcessPoolExecutor进程池
    liunx 使用flask + nginx + gunicorn 部署项目
    liunx安装python3.6.8
    Grafana设置mysql为数据源
    使用pyhdfs连接HDFS进行操作
    七、Hadoop搭建Hbase
    六、Zookeeper运行环境
    五、Hadoop搭建Hive
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/8986902.html
Copyright © 2020-2023  润新知