沐风Cc 2021-05-10 17:47 采纳率: 100%
浏览 117
已采纳

JVM相关:下面代码中年轻代分配的空间才4M大小,为什么就进行了Minor GC?

1.示例代码:

// JVM 配置: -Xmx20m -Xms20m -Xmn10m -XX:+PrintGCDetails 

public class HellocGC {
    
    static int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        byte[] b1 = new byte[2 * _1MB];
        //年轻代大小为10m,为什么执行完b2之后,会进行minor GC?
        byte[] b2 = new byte[2 * _1MB];

        byte[] b3 = new byte[2 * _1MB];
        byte[] b5 = new byte[4 * _1MB];
    }
    
}

2.GC日志:

[GC (Allocation Failure) [PSYoungGen: 6452K->1012K(9216K)] 6452K->3398K(19456K), 0.0024151 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 9216K, used 5512K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 54% used [0x00000000ff600000,0x00000000ffa64eb8,0x00000000ffe00000)
  from space 1024K, 98% used [0x00000000ffe00000,0x00000000ffefd210,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 10240K, used 6482K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 63% used [0x00000000fec00000,0x00000000ff254800,0x00000000ff600000)
 Metaspace       used 3134K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 328K, capacity 392K, committed 512K, reserved 1048576K
Disconnected from the target VM, address: '127.0.0.1:64658', transport: 'socket'

3.环境配置:

JDK版本:1.8 

收集器: PS +PO 

新生代大小:10M    老年代大小:10M 

4.问题:

  1. 1.为什么运行第二行代码之后进行了Minor GC? 我新生代才分配了4M内存啊?  
  2. 2.通过GC日志分析,为什么GC前新生代占用为 6452k, 我才分配了4M,应该是 4096k啊?
  3. 3.通过GC日志分析,老年代占用空间约为 6428k,新生代为  5512k。 我期望的值是 老年代占用约为:4M,因为第一个Minor GC将 b1  b2两个对象放到了老年代故为 4M。  新生代约为:6M.  显示的结果和我期望的是相反的,这走的是分配担保机制吗?如果是分配担保机制为什么没有触发一次Minor GC,这是什么原因?

 

在线等待大佬回答,帮忙解惑,非常感谢。

 

  • 写回答

1条回答 默认 最新

  • 沐风Cc 2021-05-11 11:32
    关注

    个人思考:

    1.如果该程序只有一个main()方法,那么此时内存占用为约为3M大小。详细看:https://ask.csdn.net/questions/7427712

    2.程序分配b1、b2对象,因为该对象共4M大小,加上初始化的3M,新生代总大小为7M。此时新生代大小剩余1M(或者2M? 包括S0区?),已经超过90%的阀值,会触发Minor GC。因为S0区只有1M大小,无法存储新生代的7M,故走了分配担保机制,直接进入了老年代。

    3.分配担保机制:在触发Minor GC时,虚拟机会校验老年代当前最大可用的连续空间是否大于新生代所有对象的总空间(10M>7M),如果此条件成立,那这次进行Minor GC则是安全的。如不成立,虚拟机会查看-XX:HandlePromotionFailure参数的设置值是否允许担保失败。如果允许,则会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的平均大小,如果大于,将尝试进行一个Minor GC,如果小于则会进行Full GC

    这是个人的理解,如有偏差还请大佬指出,谢谢

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c# 使用NPOI快速将datatable数据导入excel中指定sheet,要求快速高效
  • ¥15 高德地图点聚合中Marker的位置无法实时更新
  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题