java8 -XX:+ UseCompressedOops -XX:ObjectAlignmentInBytes = 16 [英] java8 -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=16

查看:157
本文介绍了java8 -XX:+ UseCompressedOops -XX:ObjectAlignmentInBytes = 16的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我正在尝试运行一些简单的代码,jdk-8,通过jol输出

So, I'm trying to run some simple code, jdk-8, output via jol

    System.out.println(VMSupport.vmDetails());
    Integer i = new Integer(23);
    System.out.println(ClassLayout.parseInstance(i)
            .toPrintable());

第一次尝试是在禁用压缩oops的情况下运行它,并在64-上压缩klass位JVM。

-XX:-UseCompressedOops -XX:-UseCompressedClassPointers

输出,非常期望是:

Running 64-bit HotSpot VM.
Objects are 8 bytes aligned.

java.lang.Integer object internals:
OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
  0     4       (object header)                01 00 00 00 (00000001 00000000 00000000 00000000) (1)
  4     4       (object header)                00 00 00 00 (00000000 00000000 00000000 00000000) (0)
  8     4       (object header)                48 33 36 97 (01001000 00110011 00110110 10010111) (-1758055608)
 12     4       (object header)                01 00 00 00 (00000001 00000000 00000000 00000000) (1)
 16     4   int Integer.value                  23
 20     4       (loss due to the next object alignment)

Instance size: 24 bytes (reported by Instrumentation API)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

这是有道理的:8字节klass字+ 8字节标记字+ 4字节用于实际值,4字用于填充(对齐8字节)= 24字节。

That makes sense : 8 bytes klass word + 8 bytes mark word + 4 bytes for the actual value and 4 for padding (to align on 8 bytes) = 24 bytes.

T.他第二次尝试在64位JVM上使用压缩oops启用压缩klass运行它。

同样,输出几乎可以理解:

Again, the output is pretty much understandable :

Running 64-bit HotSpot VM.
Using compressed oop with 3-bit shift.
Using compressed klass with 3-bit shift.
Objects are 8 bytes aligned.

OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
  0     4       (object header)                01 00 00 00 (00000001 00000000 00000000 00000000) (1)
  4     4       (object header)                00 00 00 00 (00000000 00000000 00000000 00000000) (0)
  8     4       (object header)                f9 33 01 f8 (11111001 00110011 00000001 11111000) (-134138887)
 12     4   int Dummy.i                        42
 Instance size: 16 bytes (reported by Instrumentation API).

4字节压缩oop(klass字)+ 8字节标记字+ 4字节值+ No空间损失= 16个字节。

4 bytes compressed oop (klass word) + 8 bytes mark word + 4 bytes for the value + no space loss = 16 bytes.

对我来说没有意义的是这个用例:

 -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:ObjectAlignmentInBytes=16

输出为:

 Running 64-bit HotSpot VM.
 Using compressed oop with 4-bit shift.
 Using compressed klass with 0x0000001000000000 base address and 0-bit shift.

我真的希望两者都是4位移位。为什么他们不是?

I was really expecting to both be "4-bit shift". Why they are not?

编辑
第二个例子运行时:

EDIT The second example is run with :

 XX:+UseCompressedOops -XX:+UseCompressedClassPointers

第三个包含:

 -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:ObjectAlignmentInBytes=16


推荐答案

我将尝试对Alexey提供的答案进行一点延伸因为有些事情可能并不明显。

I will try to extend a little bit on the answer provided by Alexey as some things might not be obvious.

根据Alexey的建议,如果我们在OpenJDK的源代码中搜索分配了压缩klass位移值的位置,我们将在metaspace.cpp中找到以下代码:

Following Alexey suggestion, if we search the source code of OpenJDK for where compressed klass bit shift value is assigned, we will find the following code in metaspace.cpp:

void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address cds_base) {
// some code removed 
if ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax) {
  Universe::set_narrow_klass_shift(0);
} else {
  assert(!UseSharedSpaces, "Cannot shift with UseSharedSpaces");
  Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
}

正如我们所看到的,班级班次可以是0(或基本上不是移位)或3位,因为LogKlassAlignmentInBytes是globalDefinitions.hpp中定义的常量:

As we can see, the class shift can either be 0(or basically no shifting) or 3 bits, because LogKlassAlignmentInBytes is a constant defined in globalDefinitions.hpp:

const int LogKlassAlignmentInBytes = 3;

所以,你的回答是:

我真的希望两者都是4位移位。为什么它们不是?

I was really expecting to both be "4-bit shift". Why they are not?

是ObjectAlignmentInBytes对元空间中始终为8bytes的压缩类指针对齐没有任何影响。

is that ObjectAlignmentInBytes does not have any effect on compressed class pointers alignment in the metaspace which is always 8bytes.

当然这个结论没有回答这个问题:

Of course this conclusion does not answer the question:

为什么在使用-XX时: ObjectAlignmentInBytes = 16 with -XX:+ UseCompressedClassPointers narrow klass shift变为零?另外,如果堆只有4GB或更多,JVM如何通过32位引用引用类空间?

我们已经知道类空间是在Java堆之上分配的,并且可以达到3G的大小。考虑到这一点,让我们做一些测试。 -XX:+ UseCompressedOops -XX:默认情况下启用UseCompressedClassPointers,因此我们可以消除这些以简洁。

We already know that the class space is allocated on top of the java heap and can be up to 3G in size. With that in mind let's make a few tests. -XX:+UseCompressedOops -XX:+UseCompressedClassPointers are enabled by default, so we can eliminate these for conciseness.

测试1:默认值 - 8字节对齐

$ java -XX:ObjectAlignmentInBytes=8 -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -version

heap address: 0x00000006c0000000, size: 4096 MB, zero based Compressed Oops

Narrow klass base: 0x0000000000000000, Narrow klass shift: 3
Compressed class space size: 1073741824 Address: 0x00000007c0000000 Req Addr: 0x00000007c0000000

请注意,堆在虚拟空间中的地址0x00000006c0000000处开始并且具有大小4GBytes。让我们从堆开始的位置跳过4Gbytes,然后我们就到了类空间开始的地方。

Notice that the heap starts at address 0x00000006c0000000 in the virtual space and has a size of 4GBytes. Let's jump by 4Gbytes from where the heap starts and we land just where class space begins.

0x00000006c0000000 + 0x0000000100000000 = 0x00000007c0000000

类空间大小为1Gbyte,所以让我们跳过另一个1Gbyte:

The class space size is 1Gbyte, so let's jump by another 1Gbyte:

0x00000007c0000000 + 0x0000000040000000 = 0x0000000800000000

我们降到32G以下。通过3位类空间移位,JVM能够引用整个类空间,尽管它处于极限(有意)。

and we land just below 32Gbytes. With a 3 bits class space shifting the JVM is able to reference the entire class space, although it's at the limit (intentionally).

测试2:16字节已对齐

java -XX:ObjectAlignmentInBytes=16 -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -version

heap address: 0x0000000f00000000, size: 4096 MB, zero based Compressed Oops

Narrow klass base: 0x0000001000000000, Narrow klass shift: 0
Compressed class space size: 1073741824 Address: 0x0000001000000000 Req Addr: 0x0000001000000000

这次我们可以看到堆地址不同,但让我们试试相同的步骤:

This time we can observe that the heap address is different, but let's try the same steps:

0x0000000f00000000 + 0x0000000100000000 = 0x0000001000000000

这一次堆空间在64GBytes虚拟空间边界以下结束,类空间分配在64Gbyte边界以上。由于类空间只能使用3位移位,JVM如何引用位于64Gbyte以上的类空间?关键是:

This time around heap space ends just below 64GBytes virtual space boundary and the class space is allocated above 64Gbyte boundary. Since class space can use only 3 bits shifting, how can the JVM reference the class space located above 64Gbyte? The key is:

Narrow klass base: 0x0000001000000000

JVM仍然使用32位压缩指针作为类空间,但在编码和解码这些时,它总是将0x0000001000000000 base添加到压缩引用而不是使用shift。请注意,只要引用的内存块低于4Gbytes(32位引用的限制),此方法就可以工作。考虑到类空间最大可以达到3G字节,我们可以轻松地在限制范围内。

The JVM still uses 32 bit compressed pointers for the class space, but when encoding and decoding these, it will always add 0x0000001000000000 base to the compressed reference instead of using shifting. Note, that this approach works as long as the referenced chunk of memory is lower than 4Gbytes (the limit for 32 bits references). Considering that the class space can have a maximum of 3Gbytes we are comfortably within the limits.

3:16字节对齐,引脚堆基础为8g

$ java -XX:ObjectAlignmentInBytes=16 -XX:HeapBaseMinAddress=8g -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -version

heap address: 0x0000000200000000, size: 4096 MB, zero based Compressed Oops

Narrow klass base: 0x0000000000000000, Narrow klass shift: 3
Compressed class space size: 1073741824 Address: 0x0000000300000000 Req Addr: 0x0000000300000000

在此测试中,我们仍然保留-XX:ObjectAlignmentInBytes = 16,还要求JVM使用-XX:HeapBaseMinAddress = 8g JVM参数在虚拟地址空间的第8 GByte分配堆。类空间将在虚拟地址空间中以第12 GByte开始,并且3位移位足以引用它。

In this test we are still keeping the -XX:ObjectAlignmentInBytes=16, but also asking the JVM to allocate the heap at the 8th GByte in the virtual address space using -XX:HeapBaseMinAddress=8g JVM argument. The class space will begin at 12th GByte in the virtual address space and 3 bits shifting is more than enough to reference it.

希望这些测试及其结果回答问题:

Hopefully, these tests and their results answer the question:


为什么使用-XX:ObjectAlignmentInBytes = 16和-XX:+ UseCompressedClassPointers时,狭窄的klass移位变为零?而且,没有移位如果堆是4GB或更多,JVM如何使用32位引用引用类空间?

"Why when using -XX:ObjectAlignmentInBytes=16 with -XX:+UseCompressedClassPointers the narrow klass shift becomes zero? Also, without shifting how can the JVM reference the class space with 32-bit references, if the heap is 4GBytes or more?"

这篇关于java8 -XX:+ UseCompressedOops -XX:ObjectAlignmentInBytes = 16的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆