UseCompressedOops UseCompressedClassPointers в jdk-13 и jdk-15 - PullRequest
4 голосов
/ 13 июля 2020

Случайно я наткнулся на изменение в jdk-15, о котором я не знал. Предположим, у меня очень простой вопрос: каков размер массива из трех промежуточных чисел? Для этого я использую 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?

1 Ответ

5 голосов
/ 13 июля 2020

И в jdk-13, и в jdk-15 обе эти опции включены по умолчанию:

java -XX:+PrintFlagsFinal -version | grep Compressed

 bool UseCompressedClassPointers  = true                                 
 bool UseCompressedOops           = true

Когда -XX:-UseCompressedOops отключен, это означает, что UseCompressedClassPointers также отключен. Вот почему при отключении UseCompressedOops размер заголовка увеличивается на 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.

Хотя я сам ответил на это, было бы неплохо, если бы кто-то нашел для этого соответствующую ошибку / изменение? Я пока не добился успеха в этом.

...