JVM中的对象

在java虚拟机中new指令时,对象的分配过程如下:
检查加载-》分配内存-》内存空间初始化-》设置-》对象初始化。

检查加载

先执行相应的类加载过程,如果没有,则进行类加载。

分配内存

根据方法区的信息确定为该类分配内存空间大小。

内存分配方式可分为“指针碰撞”和“空闲列表”两种方式。
指针碰撞:java 堆内存空间规整的情况下使用。
空闲列表:java堆空间不规整的情况下使用。
如下图:
在这里插入图片描述
具体使用哪种方式分配内存与使用的GC机制有关。

在多线程环境下创建对象,虚拟机如何保证线程安全?

本地线程分配缓冲TLAB:目的是在为新对象分配内存空间时,让每个 Java 应用线程能在使用自己专属的分配指针来分配空间(Eden 区,默认 Eden 的 1%),这样加载速度更快一些。设置了虚拟机参数 -XX:+UseTLAB,在线程初始化时,同时也会申请一块指定大小的内存,只给当前线程使用减少同步开销。
CAS:在多线程环境下,虚拟机使用CAS比较和交换的方式,保证操作原子性原子。

JVM分配内存的内存布局

分为三开
对象的内存布局必须是8的倍数。

对象的访问方式

1.句柄 ———维护句柄池,稳定的句柄地址,在对象被移动时只会改变句柄中的实例。
2.直接指针——维护reference变量表,节省时间开销。
在这里插入图片描述
对Sun HotSpot而言,它使用的是直接指针的方式进行对象的访问。

堆内存分配策略

堆进一步划分为:

新生代(PSYoungGen)

Eden空间
From Survivor空间
To Survivor空间

老年代(ParOldGen)

其内存配置图如下
在这里插入图片描述

堆中参数配置:

新生代大小: -Xmn20m 表示新生代大小20m(初始和最大)

-XX:SurvivorRatio=8 表示Eden和Survivor的比值,
缺省为8 表示 Eden:From:To= 8:1:1
2 Eden:From:To= 2:1:1

堆内存分配策略策略

1.对象优先在Eden去分配
2.大对象直接进入老年代
3.长期存活的对象将进入老年代
4.动态对象年龄判断
5.空间担保。
虚拟机默认是开启空间分配担保的,其参数值为HandlePromotionFailure,如果开启不去检查老年代空间是否够用,每次进击都往里边放,如果担保失败触发一次Full GC,如果不开启空间担保,每次都会触Full GC,这样做效率很低。

对象分配案例
对象优先在Eden区分配
/**
 * 对象优先在Eden分配
 * -Xms20m -Xmx20m  -Xmn10m -XX:+PrintGCDetails
 */
public class EdenAllocation {
    private static final int _1MB =1024*1024; //1M的大小
    // * 对象优先在Eden分配
    public static void main(String[] args) {
        byte[] b1,b2,b3,b4;
        b1 = new byte[1*_1MB];
        b2 = new byte[1*_1MB];
        b3 = new byte[1*_1MB];
        b4 = new byte[1*_1MB];

    }

}

执行结果

Heap
 PSYoungGen      total 9216K, used 6398K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 78% used [0x00000000ff600000,0x00000000ffc3f8d0,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000)
 Metaspace       used 3232K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 350K,acity 388K, committed 512K, reserved 1048576K

Eden区占用78%,老年代内存占用率0%

长期存活的对象将进入老年代

将堆大小设定限值为20M,新生代设定限值为10M

/**
 * 大对象直接进入老年代
 * -Xms20m -Xmx20m  -Xmn10m -XX:+PrintGCDetails
 * -XX:PretenureSizeThreshold=2m
 * -XX:+UseSerialGC
 */
public class BigAllocation {
    private static final int _1MB =1024*1024; //1M的大小
    // * 大对象直接进入老年代(Eden  2m  +1 )
    public static void main(String[] args) {
        byte[] b1,b2,b3;
        b1 = new byte[1*_1MB]; //这个对象在eden区
        b2 = new byte[1*_1MB]; //这个对象在eden区
        b3 = new byte[5*_1MB];//这个对象直接进入老年代
        b3 = new byte[5*_1MB];//这个对象直接进入老年代
        b3 = new byte[5*_1MB];//这个对象直接进入老年代
        b3 = new byte[5*_1MB];//这个对象直接进入老年代
        b3 = new byte[5*_1MB];//这个对象直接进入老年代
        b3 = new byte[5*_1MB];//这个对象直接进入老年代
        b3 = new byte[5*_1MB];//这个对象直接进入老年代
        b3 = new byte[5*_1MB];//这个对象直接进入老年代
        b3 = new byte[5*_1MB];//这个对象直接进入老年代


    }

}

执行结果

[GC (Allocation Failure) [PSYoungGen: 4185K->776K(9216K)] 9305K->7952K(19456K), 0.0031274 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) --[PSYoungGen: 5896K->5896K(9216K)] 13072K->13072K(19456K), 0.0015998 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 5896K->0K(9216K)] [ParOldGen: 7176K->7815K(10240K)] 13072K->7815K(19456K), [Metaspace: 3228K->3228K(1056768K)], 0.0067237 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 5283K->0K(9216K)] [ParOldGen: 7815K->7814K(10240K)] 13098K->7814K(19456K), [Metaspace: 3228K->3228K(1056768K)], 0.0076641 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 5120K->0K(9216K)] [ParOldGen: 7814K->7814K(10240K)] 12934K->7814K(19456K), [Metaspace: 3228K->3228K(1056768K)], 0.0042113 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 5120K->0K(9216K)] [ParOldGen: 7814K->7814K(10240K)] 12934K->7814K(19456K), [Metaspace: 3228K->3228K(1056768K)], 0.0040019 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 5120K->0K(9216K)] [ParOldGen: 7814K->7814K(10240K)] 12934K->7814K(19456K), [Metaspace: 3228K->3228K(1056768K)], 0.0036034 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 5120K->0K(9216K)] [ParOldGen: 7814K->7814K(10240K)] 12934K->7814K(19456K), [Metaspace: 3228K->3228K(1056768K)], 0.0031672 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 5120K->0K(9216K)] [ParOldGen: 7814K->7814K(10240K)] 12934K->7814K(19456K), [Metaspace: 3228K->3228K(1056768K)], 0.0031305 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 9216K, used 5202K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 63% used [0x00000000ff600000,0x00000000ffb14930,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 10240K, used 7814K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 76% used [0x00000000fec00000,0x00000000ff3a1860,0x00000000ff600000)
 Metaspace       used 3234K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 350K, capacity 388K, committed 512K, reserved 1048576K

老年代的使用率76%,新生代Eden使用率63%。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值