java - 在 jdk-13 和 jdk-15 中 UseCompressedOops UseCompressedClassPointers

标签 java java-13 jol java-15

偶然地,我偶然发现了我不知道的 jdk-15 变化。假设我有一个非常简单的问题:3 个整数的数组的大小是多少?为此,我使用 JOL 。代码相当简单:

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

public class Array {
    public static void main(String [] args){
       int [] array = new int[3];
       System.out.println(ClassLayout.parseInstance(array).toPrintable());
    }
}
我用 jdk-13 运行它:
  java -Djdk.attach.allowAttachSelf -Djol.tryWithSudo=true -cp jol-cli.jar  Array.java
我得到输出:
    [I 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)                           18 0e 07 00 (00011000 00001110 00000111 00000000) (462360)
     12     4        (object header)                           03 00 00 00 (00000011 00000000 00000000 00000000) (3)
     16    12    int [I.<elements>                             N/A
     28     4        (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
这非常明显:
     12 bytes --> Object headers
     4  bytes --> size of array
     12 bytes --> elements of array themselves
     4  bytes --> padding to align by 8 bytes
     ----
     32 bytes total
使用 jdk-15 运行此示例会产生相同的输出,相同的 32 bytes 。预期的...

对于第二部分,我想禁用 JVM 优化: -XX:-UseCompressedOops 。我用 jdk-13 运行它:
java -Djdk.attach.allowAttachSelf -Djol.tryWithSudo=true -cp jol-cli.jar -XX:-UseCompressedOops  Array.java


    [I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           11 00 00 00 (00010001 00000000 00000000 00000000) (17)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           40 0c f0 33 (01000000 00001100 11110000 00110011) (871369792)
     12     4        (object header)                           02 00 00 00 (00000010 00000000 00000000 00000000) (2)
     16     4        (object header)                           03 00 00 00 (00000011 00000000 00000000 00000000) (3)
     20     4        (alignment/padding gap)
     24    12    int [I.<elements>                             N/A
     36     4        (loss due to the next object alignment)
Instance size: 40 bytes
Space losses: 4 bytes internal + 4 bytes external = 8 bytes total
好吧,也有点期待:
     16 bytes --> object headers (I did -XX:-UseCompressedOops after all)
     4 bytes  --> array size
     4 bytes  --> alignment for array headers (AFAIK this is only done for arrays)
     12 bytes --> array elements themselves
     4 bytes  --> 4 bytes padding
     ----
     40 bytes total
现在让我们使用 jdk-15 运行相同的示例:
[I 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)                           0e 09 00 00 (00001110 00001001 00000000 00000000) (2318)
     12     4        (object header)                           03 00 00 00 (00000011 00000000 00000000 00000000) (3)
     16    12    int [I.<elements>                             N/A
     28     4        (loss due to the next object alignment)
Instance size: 32 bytes
为什么现在是 32 bytes?怎么没有 40 ,就像 jdk-13 一样?

最佳答案

jdk-13jdk-15 中,这两个选项都默认开启:

java -XX:+PrintFlagsFinal -version | grep Compressed

 bool UseCompressedClassPointers  = true                                 
 bool UseCompressedOops           = true
-XX:-UseCompressedOops 被禁用时,意味着 UseCompressedClassPointers 也被禁用。这就是为什么当 UseCompressedOops 关闭时, header 大小会增加 4 bytes ,因为 UseCompressedOops 关闭 UseCompressedClassPointers 。至少在 jdk-13 中是这样的:
  java -XX:+PrintFlagsFinal -XX:-UseCompressedOops -version | grep Compressed

    bool UseCompressedClassPointers = false                                  
    bool UseCompressedOops          = false
jdk-15 中的事情发生了变化:
    bool UseCompressedClassPointers = true                                 
    bool UseCompressedOops          = false
所以禁用 UseCompressedOops 并不意味着 UseCompressedClassPointers 也被禁用,所以它保持在 4 bytes
虽然,我自己回答了这个问题,如果有人找到相关的错误/更改会很好吗?到目前为止,我在这方面还没有成功。

关于java - 在 jdk-13 和 jdk-15 中 UseCompressedOops UseCompressedClassPointers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62879157/

相关文章:

Java 代码中的 JavaScript 函数调用

将 sourceCompatibility 和 targetCompatibility 从 1.8 更改为 13 时,任务 ‘:test’ 的 Gradle 执行失败

java - 通过修改对象头掩码字中的位来固定对象

java - Spring4配置CommonsMultipartResolver失败

java - 如何使用 ActiveJDBC 在 postgres 中检索自动生成的主键

从性能pov看Java静态代码分析

java - 如何使用 Gradle 设置 JPMS 模块的 ModuleMainClass 属性?

maven - 是否有任何与 Java 13 兼容的 SonarQube 版本

java - Java 对象头中有什么?

java - Java 对象在 Android 的内存中是如何布局的?