Java: странный результат после декомпиляции - PullRequest
2 голосов
/ 14 декабря 2010

У меня странный jar-файл, он содержит некоторый класс, который, когда я использую JD Decompiler, показывает такой сегмент:

public final void a(ak aa) {
    this.jdField_a_of_type_Ak = aa;
}

public final void a(cn ccn) {
  this.jdField_a_of_type_Cn = ccn;
}

public final cN a() {
  return this.jdField_a_of_type_CN;
}

public final void a() {
  super.b();
}

public final boolean a() {
    return this.jdField_a_of_type_Boolean;
}

Мне просто интересно, почему / компилятор / обфускатор может создатьБайт-код класса, как это, я имею в виду сигнатуру метода.Кто-нибудь знал, что обфускатор может это сделать?

Ответы [ 4 ]

6 голосов
/ 14 декабря 2010

Как правильно указывает @ Йоахим Зауэр : спецификация JVM налагает меньше ограничений на перегрузку методов в байт-коде, чем JLS на программы Java.

Из спецификации JVM(Раздел 4.6, Методы) :

Ни один из двух методов в одном файле класса не может иметь одинаковое имя и дескриптор (§4.3.3).

И дескриптор метода включает тип возвращаемого значения: ( 4.3.3 Дескрипторы метода )

MethodDescriptor:( ParameterDescriptor* ) ReturnDescriptor

Методы, которые вы упомянули в вашем вопросе, имеют разные дескрипторы, поэтому они в порядке:

public final void a(ak aa)     ->     (Lsomepkg1/ak;)V
public final void a(cn ccn)    ->     (Lsomepkg2/ccn;)V
public final cN a()            ->     ()Lsomepkg3/cN;
public final void a()          ->     ()V
public final boolean a()       ->     ()Z

Это искусно используется обфускаторами.У действительной программы байт-кода больше нет «непосредственно соответствующей» Java-программы. ProGuard делает это, например.Вот фрагмент из их руководства:

-overloadaggressivelyУказывает на применение агрессивной перегрузки при запутывании.Несколько полей и методов могут затем получить одинаковые имена, , если их аргументы и возвращаемые типы различны (не только их аргументы) .

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


Чтобы ответить на очевидный дополнительный вопрос: Как JVM узнает, какой метод вызывать на сайте вызова?

В инструкциях invoke вы должны указать ссылку на полную сигнатуру метода (включая возвращаемый тип метода), который должен быть вызван.

6 голосов
/ 14 декабря 2010

Байт-код Java поддерживает конструкции, которые недопустимы в исходном коде Java.Обфускаторы используют этот факт, изменяя байт-код для использования этих конструкций (при этом давая тот же результат, что и необфускацированный байт-код).

1 голос
/ 14 декабря 2010

Класс был скомпилирован без отладочной информации (по крайней мере, отсутствует информация о локальной переменной) и затем запутан.

Одна из основных запутывающих стратегий заключается в замене (почти) всех имен пакетов, классов и методов новыми, бессмысленными именами, чтобы никто не мог понять декомпилированный код.

Дополнительные стратегии - запутывание строк и добавление конструкций байт-кода, которые не могут быть декомпилированы в код Java.

Вы все равно сможете создать эквивалент исходного кода Java для запутанного файла классов, но только с большими усилиями.

1 голос
/ 14 декабря 2010

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

...