[转帖]JVM--OOPS

JVM--OOPS

https://www.jianshu.com/p/45dd5e449b98

Compressed Oops

OOP 也叫 ordinary object pointer 是指向普通对象的指针
通常 指针的的大小与机器指针大小一致. 在64位系统 需要使用1.5倍以上的内存 才能达到 相同的程序运行在32位系统上的效果。 原因是 OOP变大了。 所以仅仅增加xmx到4G多一点点是不可取的.
32位系统中 OOP使用4个字节,64位使用8个 所以 OOP的个数增加了2^32-1倍,同时带了
问题:

  1. 增加了GC开销:64位对象引用需要占用更多的堆空间,留给其他数据的空间将会减少,从而加快了GC的发生,更频繁的进行GC。
  2. 降低CPU缓存命中率:64位对象引用增大了,CPU能缓存的oop将会更少,从而降低了CPU缓存的效率。
    解决办法:
    oop保留32位 -->如何用32位oop来引用更大的堆内存-->压缩指针(CompressedOops)。
    启用CompressOops后,
    会压缩的:
        1. 每个Class的属性指针(静态成员变量)
        2. 每个对象的属性指针
        3. 普通对象数组的每个元素指针
    不会压缩的:比如指向 PermGen的Class 对象指针,本地变量,堆栈元素,入参,返回值,NULL指针
    下面是 compress的原理 &为什么是32G!!(这个我找了好久 在oracle官网找到的)
    2^32 =4*2^30 个指针每个指针指向一个byte(byte offsets) 也就是4Gi内存
    而compress 之后 2^32 个指针 指向一个对象(object offsets) 而每个对象在java中最少是8byte,所以8byte*2^32=32Gi

Managed pointers in the Java heap point to objects which are aligned on 8-byte address boundaries. Compressed oops represent managed pointers (in many but not all places in the JVM software) as 32-bit object offsets from the 64-bit Java heap base address.
Because they're object offsets rather than byte offsets, they can be used to address up to four billion objects (not bytes), or a heap size of up to about 32 gigabytes.
To use them, they must be scaled by a factor of 8 and added to the Java heap base address to find the object to which they refer. Object sizes using compressed oops are comparable to those in ILP32 mode.

Zero-Based Compressed Ordinary Object Pointers (oops)

从以上结果中我们知道 32GB 以下是启用了 UseCompressedOop,但是当我们线上真正启动服务的时候直接设置 -Xmx=32GB 的时候很可能导致 CompressedOop 失效,那我们怎么确定当前环境下最大内存设置多大才且最大限度的使用内存才能启动 CompressedOop 呢?

32G是个近似值,这个临界值跟JVM和平台有关。如果不想精确设置的话,31G是个决定安全的数值,31G肯定默认开启compressed oops。我们可以通过增加JVM参数 -XX:+PrintFlagsFinal,验证UseCompressedOops的值,从而得知,到底是不是真的开启了压缩指针,还是压缩指针失效!
  那我们就手动来验证这个临界值:

 
image

32G,即32*1024=32768M,刚好在范围[32760, 32770]中。而 32768m 验证后得到并没有开启压缩指针,所以可以从 32760 ~ 32768 之间验证选择一个最大的且开启压缩指针的内存大小。

简单测试验证

我们来做了一个简单测试,验证一下这个问题:分配设置内存大小分别为:-Xmx32760m 和 -Xmx32770m,-Xmn 都是 100M(S0:S1:Eden默认1:1:8)。总计分配一个包含8个对象类型和8个原子类型以及String,总计17个类型属性的对象 1kw 次。看它们分别触发了多少 YGC,结论如下表所示:
实验次数 开启压缩指针YGC次数 关闭压缩指针YGC次数

 
image

由执行结果可知,Young区完全一样的情况下,开启压缩指针相比关闭压缩指针,能节省20%多的内存。由此可知,32G还真是一个奇妙的魔法数值!另外需要说明的是YGC次数有小数,是表示Eden区占用比例,比如 17.52 次 YGC 表示发生了 17次 YGC 并且 Eden 还占了52%

来源:
hotspot-oracle
hotspot-openjdk
openj9
cnblogs

猜你喜欢

转载自www.cnblogs.com/jinanxiaolaohu/p/12890126.html