• JVM 09.2 运行时数据区 堆 年轻带/老年代/对象分配过程


    版权声明:源出处:尚硅谷JVM

    博客来源于大佬整理

    年轻代与老年代

    1.存储在JVM中的java对象可以被划分为两类:

    • 一类是生命周期较短的瞬时对象,这类对象的创建和消亡都非常迅速
    • 另外一类对象时生命周期非常长,在某些情况下还能与JVM的生命周期保持一致

    2.Java堆区进一步细分可以分为年轻代(YoungGen)和老年代(OldGen)。其中年轻代可以分为Eden空间、Survivor0空间和Survivor1空间(有时也叫frmo区,to区)

    3.配置新生代与老年代在堆结构的占比

    • 默认-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整个堆的1/3
    • 可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整个堆的1/5

    4.在hotSpot中,Eden空间和另外两个Survivor空间缺省所占的比例是8:1:1(测试的时候是6:1:1),开发人员可以通过选项 -XX:SurvivorRatio 调整空间比例,如-XX:SurvivorRatio=8

    5.几乎所有的Java对象都是在Eden区被new出来的

    6.绝大部分的Java对象都销毁在新生代了(IBM公司的专门研究表明,新生代80%的对象都是“朝生夕死”的)

    7.可以使用选项-Xmn设置新生代最大内存大小(这个参数一般使用默认值就好了)

    测试代码:
    复制代码
    /**
     * -Xms600m -Xmx600m
     *
     * -XX:NewRatio : 设置新生代与老年代的比例。默认值是2.
     * -XX:SurvivorRatio :设置新生代中Eden区与Survivor区的比例。默认值是8
     * -XX:-UseAdaptiveSizePolicy :关闭自适应的内存分配策略 '-'关闭,'+'打开  (暂时用不到)
     * -Xmn:设置新生代的空间的大小。 (一般不设置)
     *
     */
    public class EdenSurvivorTest {
        public static void main(String[] args) {
            System.out.println("我只是来打个酱油~");
            try {
                Thread.sleep(1000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    复制代码

    图解对象分配的一般过程

    为新对象分配内存是件非常严谨和复杂的任务,JVM的设计者们不仅需要考虑内存如何分配、在哪里分配的问题,并且由于内存分配算法与内存回收算法密切相关,所以还需要考虑GC执行完内存回收后是否会在内存空间中产生内存碎片。

    1.new的对象先放伊甸园区。此区有大小限制。

    2.当伊甸园的空间填满时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。再加载新的对象放到伊甸园区

    3.然后将伊甸园中的剩余的幸存对象移动到幸存者0区。

    4.如果再次触发垃圾回收,此时上次幸存下来的放到幸存者0区的,如果没有回收,就会放到幸存者1区。

    5.如果再次经历垃圾回收,此时会重新放回幸存者0区,接着再去幸存者1区。

    6.啥时候能去养老区呢?可以设置次数。默认是15次。·可以设置参数:-XX:MaxTenuringThreshold=进行设置。

    7.在养老区,相对悠闲。当老年区内存不足时,再次触发GC:Major GC,进行养老区的内存清理。

    8.若养老区执行了Major GC之后发现依然无法进行对象的保存,就会产生OOM异常。

    总结:针对幸存者s0,s1区:复制之后有交换,谁空谁是to。
               关于垃圾回收:频繁在新生区收集,很少在养老区收集,几乎不再永久区/元空间收集。

    注意:只有伊甸园满了才会触minorGC/youngGC,而幸存者区满了是绝对不会触发minorGC的。

    对象分配的特殊情况

     代码举例:

    复制代码
    public class HeapInstanceTest {
        byte[] buffer = new byte[new Random().nextInt(1024 * 200)];
    
        public static void main(String[] args) {
            ArrayList<HeapInstanceTest> list = new ArrayList<HeapInstanceTest>();
            while (true) {
                list.add(new HeapInstanceTest());
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    复制代码

    对应堆空间分配过程:

     

  • 相关阅读:
    JVM类加载器
    Java类加载过程
    进程间8种通信方式详解
    SpringCloud教程(Finchley版本)-00:什么是SpringCloud
    pyinstaller打包web项目
    Type javax.xml.bind.JAXBContext not present
    Cannot execute request on any known server
    websocket原理
    falsk模板jinja2与Vue冲突解决方案
    关于springboot Error resolving template之类问题
  • 原文地址:https://www.cnblogs.com/superxuezhazha/p/13329085.html
Copyright © 2020-2023  润新知