Что мы имеем в виду с отрицательным значением кода инструкции LDC? - PullRequest
3 голосов
/ 06 мая 2019

Я очень новичок в мире байт-кода Java. У меня есть некоторая задача отладки, которая включает в себя байт-код. Проходя через это, я заметил некоторые значения, которые выглядят подозрительно, но я не уверен. вот часть полного байт-кода

// access flags 0x100A
  private static synthetic $jacocoInit()[Z
    GETSTATIC ClassUnderTest.$jacocoData : [Z
    DUP
    IFNONNULL L0
    POP
    LDC -1475355800743669619
    LDC "ClassUnderTest"
    BIPUSH 64
    INVOKESTATIC org/jacoco/agent/rt/internal_1f1cc91/Offline.getProbes (JLjava/lang/String;I)[Z
    DUP
    PUTSTATIC ClassUnderTest.$jacocoData : [Z
   L0

Здесь LDC -1475355800743669619 - это то, что меня интересует. До сих пор я узнал, что это поле для константных значений в классе.

Я запутался, если значение НРС может быть отрицательным или нет?

Другая проблема, с которой я столкнулся, заключается в том, что в JDK-8 значение LDC для того же класса является положительным, а в JDK-11 - отрицательным. Итак, мой вопрос, это также зависит от JDK?

1 Ответ

5 голосов
/ 06 мая 2019

Стандартизированного формата для сборки Java не существует, поэтому могут существовать различия в зависимости от того, какой инструмент вы использовали для получения текстовой формы.

По-видимому, используемый вами инструмент не печатает пул констант.индекс, используемый инструкцией LDC (которая действительно должна быть положительной), но фактическое постоянное значение из пула.Самый сильный индикатор - это последующая инструкция, показывающая фактическое значение String, а не постоянный индекс пула.

Это соответствует последующему вызову getProbes(JLjava/lang/String;I), который ожидает long, Stringint в стеке.

  • LDC -1475355800743669619 помещает в стек буквальное значение long -1475355800743669619, которое является допустимым, если -1475355800743669619 вписывается в диапазон значений long(который подписан)
  • LDC "ClassUnderTest" толкает ссылку на String, представляющий "ClassUnderTest" в стек
  • BIPUSH 64 толкает буквальное значение int 64 кstack

Итак, у вас есть long, String и int в стеке для вызова getProbes.

Так как *Значение 1038 * является аргументом первого параметра getProbes, метод getProbes определяет его значение, а также являются ли отрицательные или положительные значения вероятными аргументами, а также должно ли значение быть одинаковым для JDK 8 или JDK 11..

https://www.jacoco.org/jacoco/trunk/doc/implementation.html говорит:

Каждый класс загружается в runtИм нужен уникальный идентификатор, чтобы связать данные покрытия.JaCoCo создает такие идентификаторы с помощью хеш-кода CRC64 из определения необработанного класса.

Если это значение long, которое мы здесь видим, просто перекомпилируем класс с другой версией JDK , возможно измените фактическое значение, и отрицательные значения вполне правдоподобны.

Обратите внимание, что если вы использовали javap вместо этого, чтобы получить текстовый вывод, это было бы больше похоже на

 0: getstatic       #42             // ClassUnderTest.$jacocoData : [Z
 3: dup
 4: ifnonnull       22
 7: pop
 9: ldc2_w          #43             // long -1475355800743669619l
11: ldc             #44             // String ClassUnderTest
13: bipush          64
15: invokestatic    #45             // org/jacoco/agent/rt/internal_1f1cc91/Offline."getProbes":(JLjava/lang/String;I)[Z
18: dup
19: putstatic       #42             // ClassUnderTest.$jacocoData : [Z

действительно показываяположительные постоянные индексы пула и фактические значения в форме комментария в конце строки.Конечно, я просто составил цифры, так как у меня нет оригинального файла класса.Это просто для иллюстрации факта, изложенного в начале ответа, нет стандартизированной формы для вывода сборки Java.Вы можете запустить javap для действительного байтового кода.

...