JVM学习-堆空间(二)

年轻代与老年代
  • 存储在JVM中的Java对象被划分为两类
    • 一类是生命周期较短的瞬时对象,这类对象的创建和消亡都非常迅速
    • 一类对象的生命周期很长,在某些极端情况下还能够与JVM的生命周期保持一致
  • Java堆区进一步细分的话,分为年轻代(YoungGen)和老年代(OldGen)
  • 其中年轻代可以划分为Eden空间、Survior0空间和Survior1空间(或from区和to区)
  • 配置新生代和老年代在堆结构的占比
    • 默认-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整个堆的1/3
    • 可以修改-XX:NewRatio=4,表示新生代1,老年代占4,新生代占整个堆的1/5
  • 新生代当中,默认Eden和Survivor的比例为8:1:1,但使用时比例为6:1:1,运行时需要关闭自适应策略,可能不起作用(-XX:-UseAdaptiveSizePolicy)
    • 显示指定-XX:SurvivorRatio=8可以将比例调整为8:1:1
  • 几乎所有的Java对象是在Eden区被new出来的
  • 绝大多数的Java对象的销毁都在新生代进行
    • IBM公司研究表明,新生代中80%对象都是朝生夕死的
  • 可以通过-Xmn设置新生代最大内存大小
    • 这个参数一般使用默认即可
java 复制代码
C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter05>jinfo -flag SurvivorRatio 8112
-XX:SurvivorRatio=8

设置-XX:NewRatio=2 -Xms512m -Xmx512m,如生命周期比较长的对象多时,建议调大老年代对象比例

java 复制代码
//先通过jps查看当前进程PID,通过jinfo命令查看进程的NewRation的设置比例
C:\Users\Administrator\IdeaProjects\jvm\target\classes\com\chapter05>jinfo -flag NewRatio 10332
-XX:NewRatio=2
对象分配过程

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

  1. new对象先放伊甸园区。此区有大小限制
  2. 当伊甸园空间满时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁,再加载新的对象放到伊甸园区
  3. 然后将伊甸园中的剩余对象移动到幸存者0区(Survivor0)
  4. 如果再次触发垃圾回收,此时上次幸存下来的放到幸存者0区的,如果没有回收,放到幸存者1区
  5. 如果再次经历垃圾回收,此时会重新放回幸存者0区,接着再去幸存者1区
  6. 啥时候去养老区呢,可以设置次数,默认15次
    • 设置参数:-XX:MaxTenuringThreshold=进行设置
  7. 在养老区,相对悠闲,当养老区内存不足时,再次触发GC:Major GC,进行养老区的内存清理
  8. 若养老区执行了Major GC之后发现依然无法进行对象的保存,就会产生OOM异常



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

java 复制代码
public class HeapInstanceTest {
    byte[] buffer = new byte[new Random().nextInt(1024*1024)];
    public static void main(String[] args) {
        List<HeapInstanceTest> list = new ArrayList<>();
        while (true) {
            list.add(new HeapInstanceTest());
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//执行结果
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at com.chapter06.HeapInstanceTest.<init>(HeapInstanceTest.java:12)
	at com.chapter06.HeapInstanceTest.main(HeapInstanceTest.java:16)
相关推荐
神仙别闹34 分钟前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭1 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫1 小时前
泛型(2)
java
超爱吃士力架1 小时前
邀请逻辑
java·linux·后端
南宫生1 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石2 小时前
12/21java基础
java
李小白662 小时前
Spring MVC(上)
java·spring·mvc
sanguine__2 小时前
Web APIs学习 (操作DOM BOM)
学习
GoodStudyAndDayDayUp2 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶2 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb