fernflower
Unofficial mirror of FernFlower Java decompiler (All pulls should be submitted upstream)
Top Related Projects
IntelliJ IDEA Community Edition & IntelliJ Platform
This is the public repository for the CFR Java decompiler
Dex to Java decompiler
A Java 8+ Jar & Android APK Reverse Engineering Suite (Decompiler, Editor, Debugger & More)
An Open Source Java Decompiler Gui for Procyon
A standalone Java Decompiler GUI
Quick Overview
Fernflower is an analytical decompiler for Java, developed by JetBrains and maintained by fesh0r on GitHub. It aims to produce high-quality Java source code from compiled class files, making it useful for reverse engineering and code analysis tasks.
Pros
- Produces readable and well-structured Java source code
- Supports decompilation of modern Java features and language constructs
- Actively maintained and regularly updated
- Can be used as a standalone tool or integrated into other projects
Cons
- May struggle with heavily obfuscated code
- Slower performance compared to some other decompilers
- Limited documentation and examples available
- Occasional issues with complex lambda expressions or nested classes
Code Examples
As Fernflower is a decompiler and not a code library, there are no code examples to provide. Instead, it is used as a tool to decompile Java bytecode into source code.
Getting Started
To use Fernflower, follow these steps:
-
Clone the repository:
git clone https://github.com/fesh0r/fernflower.git
-
Build the project using Gradle:
cd fernflower ./gradlew build
-
Use the built JAR file to decompile a class file:
java -jar build/libs/fernflower.jar <input_file.class> <output_directory>
Replace <input_file.class>
with the path to your compiled Java class file and <output_directory>
with the desired output location for the decompiled source code.
Competitor Comparisons
IntelliJ IDEA Community Edition & IntelliJ Platform
Pros of intellij-community
- Comprehensive IDE functionality with a wide range of features and plugins
- Active development with frequent updates and improvements
- Large community support and extensive documentation
Cons of intellij-community
- Larger codebase and more complex architecture
- Higher resource requirements for development and usage
- Steeper learning curve for contributors
Code Comparison
fernflower (Java decompiler):
public class ByteCodeAnalyzer {
public static String decompile(byte[] bytecode) {
// Decompilation logic here
}
}
intellij-community (IDE functionality):
public class JavaDecompiler {
public String decompile(VirtualFile file, Project project) {
// Decompilation logic integrated with IDE
}
}
Summary
fernflower is a focused Java decompiler project, while intellij-community is a comprehensive IDE platform. fernflower offers a simpler, more specialized codebase for Java decompilation, while intellij-community provides a full-featured development environment with integrated decompilation capabilities. The choice between them depends on whether you need a standalone decompiler or a complete IDE solution.
This is the public repository for the CFR Java decompiler
Pros of CFR
- More actively maintained with frequent updates
- Supports decompilation of newer Java versions (up to Java 17)
- Offers additional features like enum and switch expression decompilation
Cons of CFR
- May produce more verbose output in some cases
- Less widespread adoption compared to Fernflower
- Potentially slower decompilation speed for large projects
Code Comparison
CFR:
public class Example {
public static void main(String[] args) {
System.out.println("Hello, CFR!");
}
}
Fernflower:
public class Example {
public static void main(String[] args) {
System.out.println("Hello, Fernflower!");
}
}
Both decompilers produce similar output for simple Java code. However, CFR may generate more detailed comments and handle complex language features better in some cases.
Summary
CFR and Fernflower are both Java decompilers with their own strengths. CFR excels in supporting newer Java versions and offering additional decompilation features, while Fernflower has been widely adopted and integrated into various tools. The choice between them depends on specific project requirements and personal preferences.
Dex to Java decompiler
Pros of jadx
- More actively maintained with frequent updates
- Includes a GUI for easier navigation and analysis
- Supports decompilation of Android resources (XML, manifest)
Cons of jadx
- May struggle with heavily obfuscated code
- Can be slower for large projects compared to fernflower
Code comparison
fernflower:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
jadx:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
In this simple example, both decompilers produce identical output. However, differences may become apparent with more complex code structures or when dealing with obfuscated binaries.
jadx generally produces more readable code for Android-specific constructs and can handle newer Java language features better. fernflower, being integrated into IntelliJ IDEA, benefits from the IDE's code analysis capabilities but may lag behind in supporting the latest Java syntax.
Both tools have their strengths, with jadx being more suited for Android-focused reverse engineering tasks, while fernflower excels in general Java decompilation within the IntelliJ ecosystem.
A Java 8+ Jar & Android APK Reverse Engineering Suite (Decompiler, Editor, Debugger & More)
Pros of Bytecode Viewer
- Offers a comprehensive GUI with multiple decompiler options
- Includes additional features like searching, editing, and compiling
- Supports various file formats beyond just Java class files
Cons of Bytecode Viewer
- Larger file size and more complex setup compared to FernFlower
- May have slower performance due to its extensive feature set
- Requires more system resources to run effectively
Code Comparison
FernFlower (command-line usage):
java -jar fernflower.jar input.jar output
Bytecode Viewer (Java code to open a file):
BytecodeViewer.openFiles(new File[]{new File("input.jar")});
BytecodeViewer.viewer.setVisible(true);
Summary
FernFlower is a lightweight, command-line Java decompiler focused solely on decompilation. It's efficient and easy to use for simple decompilation tasks. Bytecode Viewer, on the other hand, is a feature-rich GUI application that incorporates multiple decompilers (including FernFlower) and provides additional tools for bytecode analysis and manipulation. While Bytecode Viewer offers more functionality, it comes at the cost of increased complexity and resource usage. The choice between the two depends on the user's specific needs and preferences.
An Open Source Java Decompiler Gui for Procyon
Pros of Luyten
- User-friendly GUI for easier decompilation and navigation
- Supports multiple output formats (e.g., Java, Groovy)
- Actively maintained with regular updates
Cons of Luyten
- May be slower for large-scale decompilation tasks
- Less suitable for integration into automated workflows
- Limited command-line interface options
Code Comparison
Fernflower (Java decompilation):
public class Example {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Luyten (Java decompilation):
public class Example {
public static void main(final String[] args) {
System.out.println("Hello, World!");
}
}
Both tools produce similar output for simple Java code. However, Fernflower may handle more complex scenarios with slightly better accuracy, while Luyten offers a more user-friendly interface for exploring decompiled code.
Summary
Fernflower is better suited for large-scale decompilation tasks and integration into automated workflows, while Luyten provides a more accessible GUI-based approach for individual developers. The choice between the two depends on specific use cases and user preferences.
A standalone Java Decompiler GUI
Pros of JD-GUI
- User-friendly graphical interface for easy navigation and decompilation
- Real-time decompilation and syntax highlighting
- Supports drag-and-drop functionality for quick file loading
Cons of JD-GUI
- Less actively maintained compared to Fernflower
- Limited command-line options and automation capabilities
- May produce less accurate decompiled code in some cases
Code Comparison
Fernflower:
public class Example {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
JD-GUI:
public class Example
{
public static void main(String[] paramArrayOfString)
{
System.out.println("Hello, World!");
}
}
Both decompilers produce similar output for simple code, but Fernflower often generates more readable and accurate results for complex classes and methods. JD-GUI may introduce unnecessary line breaks and use different parameter naming conventions.
Fernflower is generally preferred for its accuracy and integration with other tools, while JD-GUI offers a more user-friendly interface for quick visual inspection of decompiled code. The choice between the two depends on the specific use case and user preferences.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
About Fernflower
Fernflower is the first actually working analytical decompiler for Java and probably for a high-level programming language in general. Naturally it is still under development, please send your bug reports and improvement suggestions to the issue tracker.
Fernflower and ForgeFlower
Fernflower includes some patches from ForgeFlower. Sincere appreciation is extended to the maintainers of ForgeFlower for their valuable contributions and enhancements.
Licence
Fernflower is licenced under the Apache Licence Version 2.0.
Running from command line
java -jar fernflower.jar [-<option>=<value>]* [<source>]+ <destination>
* means 0 or more times
+ means 1 or more times
<source>: file or directory with files to be decompiled. Directories are recursively scanned. Allowed file extensions are class, zip and jar. Sources prefixed with -e= mean "library" files that won't be decompiled, but taken into account when analysing relationships between classes or methods. Especially renaming of identifiers (s. option 'ren') can benefit from information about external classes.
<destination>: destination directory
<option>, <value>: a command-line option with the corresponding value (see "Command-line options" below).
Examples:
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\
Command-line options
With the exception of mpm and urc the value of 1 means the option is activated, 0 - deactivated. Default value, if any, is given between parentheses.
Typically, the following options will be changed by user, if any: hes, hdc, dgs, mpm, ren, urc The rest of options can be left as they are: they are aimed at professional reverse engineers.
- rbr (1): hide bridge methods
- rsy (0): hide synthetic class members
- din (1): decompile inner classes
- dc4 (1): collapse 1.4 class references
- das (1): decompile assertions
- hes (1): hide empty super invocation
- hdc (1): hide empty default constructor
- dgs (0): decompile generic signatures
- ner (1): assume return not throwing exceptions
- den (1): decompile enumerations
- rgn (1): remove getClass() invocation, when it is part of a qualified new statement
- lit (0): output numeric literals "as-is"
- asc (0): encode non-ASCII characters in string and character literals as Unicode escapes
- bto (1): interpret int 1 as boolean true (workaround to a compiler bug)
- nns (0): allow for not set synthetic attribute (workaround to a compiler bug)
- uto (1): consider nameless types as java.lang.Object (workaround to a compiler architecture flaw)
- udv (1): reconstruct variable names from debug information, if present
- ump (1): reconstruct parameter names from corresponding attributes, if present
- rer (1): remove empty exception ranges
- fdi (1): de-inline finally structures
- mpm (0): maximum allowed processing time per decompiled method, in seconds. 0 means no upper limit
- ren (0): rename ambiguous (resp. obfuscated) classes and class elements
- urc (-): full name of a user-supplied class implementing IIdentifierRenamer interface. It is used to determine which class identifiers should be renamed and provides new identifier names (see "Renaming identifiers")
- inn (1): check for IntelliJ IDEA-specific @NotNull annotation and remove inserted code if found
- lac (0): decompile lambda expressions to anonymous classes
- nls (0): define new line character to be used for output. 0 - '\r\n' (Windows), 1 - '\n' (Unix), default is OS-dependent
- ind: indentation string (default is 3 spaces)
- crp (0): use record patterns where it is possible
- cps (0): use switch with patterns where it is possible
- log (INFO): a logging level, possible values are TRACE, INFO, WARN, ERROR
- iec (0): include entire class path into context when decompiling
- isl (1): inline simple lambda expressions
- ucrc (1): hide unnecessary record constructor and getters
- cci (1): check if resource in try-with-resources actually implements
AutoCloseable
interface - jvn (0): overwrite any local variable names with JAD style names
- jpr (0): include parameter names in JAD naming
Renaming identifiers
Some obfuscators give classes and their member elements short, meaningless and above all ambiguous names. Recompiling of such code leads to a great number of conflicts. Therefore it is advisable to let the decompiler rename elements in its turn, ensuring uniqueness of each identifier.
Option 'ren' (i.e. -ren=1) activates renaming functionality. Default renaming strategy goes as follows:
- rename an element if its name is a reserved word or is shorter than 3 characters
- new names are built according to a simple pattern: (class|method|field)_<consecutive unique number>
You can overwrite this rules by providing your own implementation of the 4 key methods invoked by the decompiler while renaming. Simply pass a class that implements org.jetbrains.java.decompiler.main.extern.IIdentifierRenamer in the option 'urc' (e.g. -urc=com.example.MyRenamer) to Fernflower. The class must be available on the application classpath.
The meaning of each method should be clear from naming: toBeRenamed determine whether the element will be renamed, while the other three provide new names for classes, methods and fields respectively.
Top Related Projects
IntelliJ IDEA Community Edition & IntelliJ Platform
This is the public repository for the CFR Java decompiler
Dex to Java decompiler
A Java 8+ Jar & Android APK Reverse Engineering Suite (Decompiler, Editor, Debugger & More)
An Open Source Java Decompiler Gui for Procyon
A standalone Java Decompiler GUI
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot