
Декомпилятор из байт-кода Java в Java, используемый в IntelliJ IDEA.
Fernflower — это первый реально работающий аналитический декомпилятор для Java и, вероятно, для языков программирования высокого уровня в целом.
Релизы публикуются в репозитории Intellij Community.
Пожалуйста, отправляйте сообщения об ошибках и запросы на новые функции в [трекер задач] (в подсистеме Java. Decompiler. Engine).
Fernflower поставляется в составе IntelliJ IDEA и в основном используется для отображения Java-кода при отладке или навигации по файлам классов.
Fernflower можно запускать из командной строки в автономном режиме с помощью следующей команды:
java -jar fernflower.jar [-<option>=<value>]* [<source>]+ <destination>
* означает ноль или более раз
+ означает один или более раз
<source>: файл или каталог с файлами, подлежащими декомпиляции.
Каталоги сканируются рекурсивно.
Допустимые расширения файлов: class, zip и jar.
Источники с префиксом -e= означают «библиотечные» файлы, которые не будут декомпилированы, но будут учитываться при анализе
связей между классами или методами.
Особенно переименование идентификаторов (см. опцию ren) может извлечь выгоду из информации о внешних классах.
<destination>: целевой каталог для размещения результирующего Java-исходного кода
<option>=<value>: опция командной строки с соответствующим значением (см. «Опции командной строки» ниже).
java -jar fernflower.jar -hes=0 -hdc=0 c:\Temp\binary\ -e=c:\Java\rt.jar c:\Temp\source\
java -jar fernflower.jar -dgs=1 c:\Temp\binary\library.jar c:\Temp\binary\Boot.class c:\Temp\source\
За исключением mpm и urc значение 1 означает, что опция активирована, 0 — деактивирована.
Значение по умолчанию, если оно есть, указано в скобках.
Обычно пользователь меняет следующие опции, если вообще меняет: hes, hdc, dgs, mpm, ren, urc Остальные опции можно оставить как есть: они предназначены для профессиональных реверс-инженеров.
rbr (1): скрывать мостовые методыrsy (0): скрывать синтетические члены классаdin (1): декомпилировать внутренние классыdc4 (1): сворачивать ссылки на классы 1.4das (1): декомпилировать утвержденияhes (1): скрывать пустой вызов superhdc (1): скрывать пустой конструктор по умолчаниюdgs (0): декомпилировать обобщённые сигнатурыner (1): предполагать, что return не выбрасывает исключенияden (1): декомпилировать перечисленияrgn (1): удалять вызов getClass(), когда он является частью оператора new с квалификациейlit (0): выводить числовые литералы «как есть»Некоторые обфускаторы дают классам и их членам короткие, бессмысленные и, прежде всего, неоднозначные имена. Перекомпиляция такого кода приводит к большому количеству конфликтов. Поэтому целесообразно позволить декомпилятору, в свою очередь, переименовывать элементы, обеспечивая уникальность каждого идентификатора.
Опция ren (т.е. -ren=1) активирует функциональность переименования. Стратегия переименования по умолчанию выглядит следующим образом:
org.jetbrains.java.decompiler.main.extern.IMemberIdentifierRenamer, в опции urc
(например, -urc=com.example.MyRenamer) в Fernflower. Класс должен быть доступен в classpath приложения.Назначение каждого метода должно быть ясно из названия: toBeRenamed определяет, будет ли элемент переименован, а остальные три предоставляют новые имена для классов, методов и полей соответственно.
Сборка исполняемого стартового скрипта:
./gradlew :installDist
Стартовый скрипт генерируется в build/install/engine/bin.
Fernflower является частью проекта IntelliJ Community, вклад приветствуется, предпочтительный способ отправки патчей — создание pull request в репозитории IntelliJ community. При отправке патчей, пожалуйста, следуйте правилам участия.
Fernflower лицензирован в соответствии с Apache License Version 2.0.
Fernflower изначально был разработан Stiver, но поддерживается компанией JetBrains с 2014 года. В этот репозиторий были включены некоторые патчи из ForgeFlower. Зеркало Fernflower также долгое время поддерживалось Andrew McRae.
Правильное название — Fernflower, а не FernFlower.
asc (0): кодировать не-ASCII символы в строковых и символьных литералах как Unicode-экранированияbto (1): интерпретировать int 1 как boolean true (обходной путь для ошибки компилятора)nns (0): разрешить отсутствие синтетического атрибута (обходной путь для ошибки компилятора)uto (1): считать безымянные типы как java.lang.Object (обходной путь для недостатка архитектуры компилятора)udv (1): восстанавливать имена переменных из отладочной информации, если она естьump (1): восстанавливать имена параметров из соответствующих атрибутов, если они естьrer (1): удалять пустые диапазоны исключенийfdi (1): убрать встраивание finally-структурmpm (0): максимальное допустимое время обработки на декомпилируемый метод, в секундах. 0 означает отсутствие ограниченияren (0): переименовывать неоднозначные (или обфусцированные) классы и элементы классовurc (-): полное имя пользовательского класса, реализующего интерфейс IIdentifierRenamer. Используется для определения того, какие идентификаторы классов следует переименовывать, и предоставляет новые имена идентификаторов (см. «Переименование идентификаторов»)inn (1): проверять наличие специфической для IntelliJ IDEA аннотации @NotNull и удалять вставленный код, если она найденаlac (0): декомпилировать лямбда-выражения в анонимные классыnls (0): задавать символ новой строки для вывода. 0 — '\r\n' (Windows), 1 — '\n' (Unix), по умолчанию зависит от ОСind: строка отступа (по умолчанию 3 пробела)crp (0): использовать запись с образцами (record patterns) где это возможноcps (0): использовать switch с образцами где это возможноlog (INFO): уровень логирования, возможные значения: TRACE, INFO, WARN, ERRORiec (0): включать весь classpath в контекст при декомпиляцииisl (1): встраивать простые лямбда-выраженияucrc (1): скрывать ненужный конструктор записи и геттерыcci (1): проверять, реализует ли ресурс в try-with-resources интерфейс AutoCloseablejvn (0): перезаписывать имена локальных переменных именами в стиле JADjpr (0): включать имена параметров в именование JADpbo (0): добавлять уточняющие скобки при смешивании побитовых/сдвиговых операторов с арифметическими