图解
对象头MarkWord
markword用于存储对象的运行时数据。记录分代年龄、锁标志位等。
以下图片基于64位JVM
类型指针
指向方法区的类元数据,JVM通过这个指针确定对象是哪个类的实例。
数组长度
只有数组对象才有。
实例数据用于存储对象中的各字段信息。
对齐填充java对象都是都是按照8字节对齐的。对象占用的空间大小必须是8的倍数。这样的设计是为了加快对象的访问速度,让指针以每8个字节进行跳针。
指针压缩-XX:+UseCompressedOops是启用指针压缩,-XX:-UseCompressedOops是停用指针压缩。在64位JVM中指针压缩是默认开启的功能。
如果不开启指针压缩,那么MarkWord与类型指针都将占用8个字节(64位),指针压缩会缩短类型指针的地址占用。
这样会带来的影响
1.GC变得更加频繁:每个对象的占用空间变大,同一空间的可创建对象数量变小,更容易因为空间占用到达阈值而触发GC。
2.降低CPU缓存命中率:CPU缓存的对象会变少,从而降低了使用的对象在CPU缓存中的概率。
示例
import org.openjdk.jol.info.ClassLayout; import org.openjdk.jol.vm.VM; public class LayoutTest1 { public static void main(String[] args) { System.out.println(VM.current().details()); System.out.println(ClassLayout.parseClass(A.class).toPrintable()); System.out.println(ClassLayout.parseClass(B.class).toPrintable()); System.out.println(ClassLayout.parseInstance(new int[] {}).toPrintable()); } } class A { long a; } class B { int a; }
不开启指针压缩得出的结果
开启指针压缩得出的结果
通过对比两张图,我们可以发现仅从3个对象的内存占用情况来说,开启压缩指针减少了16字节的内存占用。
为什么JVM达到32G内存,压缩指针就失效了?当开启指针压缩后类型指针会被压缩到4个字节。那么类型指针的寻址极限就是4byte * 8bit = 32bit。类型指针可以存放2^32(4G)个内存单元地址。
计算机中信息的最小单位是bit,存储单元的最小单位是byte。一个内存地址可以指向1byte的地址,所以最大内存就达到了32GB。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)