Proguard - Не удается найти общий суперкласс/java.lang.VerifyError

Мы разрабатываем настольное приложение. При запуске ProGuard (версия 5.3.3) в коде с использованием следующих флагов конфигурации:

-dontoptimize
-allowaccessmodification
-dontusemixedcaseclassnames
-dontwarn

Proguard дает следующую ошибку:

Unexpected error while performing partial evaluation:
  Class       = [com/code/backend/e/b/b]
  Method      = [b(Ljava/lang/String;)Ljava/nio/file/Path;]
  Exception   = [java.lang.IllegalArgumentException] (Can't find common super class of [com/google/common/collect/ImmutableList] (with 2 known super classes) and [com/google/common/collect/UnmodifiableIterator] (with 1 known super classes))
Unexpected error while preverifying:
  Class       = [com/code/backend/e/b/b]
  Method      = [b(Ljava/lang/String;)Ljava/nio/file/Path;]
  Exception   = [java.lang.IllegalArgumentException] (Can't find common super class of [com/google/common/collect/ImmutableList] (with 2 known super classes) and [com/google/common/collect/UnmodifiableIterator] (with 1 known super classes))


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task 'proguard'.
> Can't find common super class of [com/google/common/collect/ImmutableList] (with 2 known super classes) and [com/google/common/collect/UnmodifiableIterator] (with 1 known super classes)

Если флаг -dontpreverify добавлен в конфигурацию, сборка будет успешной. Однако при запуске jar файла мы получаем следующую ошибку:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 11
Exception Details:
  Location:
    com/code/code2/MainWindow.b(Lcom/code/code2/ClientAPIProtos$SoftwareStatus;)V @1: ifnull
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0x0000000: 2bc6 000a 2ab4 00bc c700 04b1 2bb2 00a4
    0x0000010: a500 0a2b b800 f599 0018 2ab4 00bc b601
    0x0000020: 9299 0020 2ab4 00bc 03b6 0193 a700 152a
    0x0000030: b400 bcb6 0192 9a00 0b2a b400 bc04 b601
    0x0000040: 932b b800 f699 0012 1225 4db8 0138 4e2a
    0x0000050: 04b5 00c8 a700 0f12 1e4d b801 3a4e 2a03
    0x0000060: b500 c82a b400 bcb6 0191 3a04 1904 c600
    0x0000070: 0c2c 1904 b601 799a 000b 2ab4 00bc 2cb6
    0x0000080: 0195 2ab4 00bc b601 903a 0519 05c6 0009
    0x0000090: 2d19 05a5 000b 2ab4 00bc 2db6 0194 b1  

    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
    at java.lang.Class.getMethod0(Class.java:3018)
    at java.lang.Class.getMethod(Class.java:1784)
    at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)

Кого можно избежать, используя флаг JVM -noverify. Чтение потока:

Обфускация вызывает VerifyError: ожидание кадра стека

Мы хотели бы избежать этих флажков без проверки, если это возможно.

Примечание. Ошибка сборки возникает даже при добавлении

-dontobfuscate
-dontshrink

Ответ 1

Вы указываете опцию -dontwarn для подавления предупреждений о нерешенных ссылках. Это может привести к проблемам при обработке кода. ProGuard нужны эти ссылки, например. на этапе предварительной проверки. Ошибка действительно предполагает, что вход не содержит всех необходимых зависимостей: отсутствует обычный общий класс или интерфейс ImmutableList и UnmodifiableIterator. Для настольного приложения вы должны проверить, что вы указываете банку времени выполнения Java со всеми необходимыми классами:

-libraryjars <java.home>/lib/rt.jar

См. руководство ProGuard > Устранение неполадок > Предупреждение: не удается найти суперкласс или интерфейс

Ответ 2

Инициализация, проверка и валидация являются частью проекта здания. Я считаю, что флаг -allowaccessmodification позволяет изменять при построении проекта, т.е. Ваши классы модифицируются из исходной структуры. Когда исходная структура класса изменяется, а их стопки кадров нарушаются. Это приводит к сбою проверки. Если вы хотите игнорировать ошибку проверки, то, как уже упоминалось, вам нужно использовать флаг, который приостанавливает проверку.

Ответ 3

Troubleshooting

ProGuard может распечатывать некоторые заметки и не смертельные предупреждения:

Примечание: не удается найти динамически ссылочный класс ProGuard не может найти класс или интерфейс, к которым ваш код обращается посредством интроспекции. Вы должны проверить, хотите ли вы добавить банку, содержащую этот класс.

Примечание:... calls '(...) Class.forName(variable).newInstance()' ProGuard перечисляет все классные броски динамически созданных экземпляров класса, такие как "(MyClass) Class.forName(variable).newInstance()". В зависимости от вашего приложения вам может потребоваться сохранить упомянутые классы с опцией "класс -keep class MyClass" или их реализация с опцией "класс -keep" реализует MyClass ". Вы можете отключить эти заметки, указав параметр -dontnote.

Примечание:... доступ к полю/методу '...' динамически ProGuard перечисляет ряд конструкций, таких как ".getField(" myField ")". В зависимости от вашего приложения вам может понадобиться выяснить, где указаны указанные члены класса, и сохранить их с помощью опции "-keep class MyClass {MyFieldType myField;}". В противном случае ProGuard может удалить или обфускать членов класса, поскольку он не может точно знать, какие именно они. Он перечисляет возможных кандидатов для вашей информации. Вы можете отключить эти заметки, указав параметр -dontnote.