Live data from Hacker News

Fernflower Java Decompiler

github.com

21–30 of 45 posts

Re: Fernflower Java Decompiler

#21
post #9

> Fernflower is the first actually working analytical decompiler for Java and probably for a high-level programming language in general. That really deserves a link. What is an “analytical” decompiler?

Someone apparently had the exact same question in 2020: https://stackoverflow.com/questions/62298929/what-is-an-anal... Answer is pretty vague though, but sounds like it’s about not trying to “reverse” what the compiler did, but rather try and “analytically” work put what source code would likely have yielded the byte code it’s looking at?

Yes, that's what it is doing.

If you have a block of code a compiler will compile a language expression or statement into a particular set of assembly/bytecode instructions. For example converting `a + b` to `ADD a b`.

A reversing decompiler will look at the `ADD a b` and produce `a + b` as the output. This is the simplest approach as it is effectively just a collection of these types of mapping. While this works, it can be harder to read and noisier than the actual code. This is because:

1. it does not handle annotations like @NotNull correctly -- these are shown as `if (arg == null) throw ...` instead of the annotation because the if/throw is what the compiler generated for that annotation;

2. it doesn't make complex expressions readable;

3. it doesn't detect optimizations like unrolling loops, reordering expressions, etc.

For (1) an analytical decompiler can recognize the `if (arg == null) throw` expression at the start of the function and map that to a @NotNull annotation.

Likewise, it could detect other optimizations like loop unrolling and produce better code for that.

Re: Fernflower Java Decompiler

#22
post #9

> Fernflower is the first actually working analytical decompiler for Java and probably for a high-level programming language in general. That really deserves a link. What is an “analytical” decompiler?

The link about Stiver has some details:

> Stiver decided to write his own decompiler as a side project. To overcome the weaknesses of existing alternatives, he took a different approach. After reading the bytecode, he constructed a control-flow graph in static single-assignment form, which is much better to express the program semantics abstracting the particular shape of bytecode. At the beginning of this project, Stiver knew little about static analysis and compiler design and had to learn a lot, but the effort was worth it. The resulting decompiler produced much better results than anything available at that time. It could even decompile the bytecode produced by some obfuscators without any explicit support.

https://blog.jetbrains.com/idea/2024/11/in-memory-of-stiver/

Re: Fernflower Java Decompiler

#23
post #21

Earlier quoted context omitted.

Someone apparently had the exact same question in 2020: https://stackoverflow.com/questions/62298929/what-is-an-anal... Answer is pretty vague though, but sounds like it’s about not trying to “reverse” what the compiler did, but rather try and “analytically” work put what source code would likely have yielded the byte code it’s looking at?

Yes, that's what it is doing. If you have a block of code a compiler will compile a language expression or statement into a particular set of assembly/bytecode instructions. For example converting `a + b` to `ADD a b`. A reversing decompiler will look at the `ADD a b` and produce `a + b` as the output. This is the simplest approach as it is effectively just a collection of these types of mapping. While this works, it…

I'm not sure that @NotNull example is appropriate. Java compiler does not add any checks for @NotNull annotations. Those annotations exist for IDE and linting tools, compiler doesn't care. May be there are Java-like languages like Lombok or non-standard compilers which do add those checks, but I think that Java decompiler shouldn't do assumptions of these additional tools.

Re: Fernflower Java Decompiler

#24
post #21

Earlier quoted context omitted.

Yes, that's what it is doing. If you have a block of code a compiler will compile a language expression or statement into a particular set of assembly/bytecode instructions. For example converting `a + b` to `ADD a b`. A reversing decompiler will look at the `ADD a b` and produce `a + b` as the output. This is the simplest approach as it is effectively just a collection of these types of mapping. While this works, it…

I'm not sure that @NotNull example is appropriate. Java compiler does not add any checks for @NotNull annotations. Those annotations exist for IDE and linting tools, compiler doesn't care. May be there are Java-like languages like Lombok or non-standard compilers which do add those checks, but I think that Java decompiler shouldn't do assumptions of these additional tools.

https://www.jetbrains.com/help/idea/annotating-source-code.h...

> When you compile your project with IntelliJ IDEA build tool, the IDE adds assertions to all code elements annotated with @NotNull. These assertions will throw an error if the elements happen to be null at runtime.

Re: Fernflower Java Decompiler

#25

https://github.com/Vineflower/vineflower

Why would one choose this over the original?

After a little research it seems like it's main focus in on decompiled code readability.

https://old.reddit.com/r/java/comments/ue8u59/new_open_sourc...

A little more info in this thread as well:

https://old.reddit.com/r/java/comments/ue8u59/new_open_sourc...

(It was earlier named Quiltflower and is actually a combination of multiple Fernflower forks from its' gh README)

Would ideally expect the project site/github to list out how's the fork different though.

Re: Fernflower Java Decompiler

#26
post #24

Earlier quoted context omitted.

I'm not sure that @NotNull example is appropriate. Java compiler does not add any checks for @NotNull annotations. Those annotations exist for IDE and linting tools, compiler doesn't care. May be there are Java-like languages like Lombok or non-standard compilers which do add those checks, but I think that Java decompiler shouldn't do assumptions of these additional tools.

https://www.jetbrains.com/help/idea/annotating-source-code.h... > When you compile your project with IntelliJ IDEA build tool, the IDE adds assertions to all code elements annotated with @NotNull. These assertions will throw an error if the elements happen to be null at runtime.

[dead]

Re: Fernflower Java Decompiler

#29

Can the decompiled result be compiled again?

It's not a perfect decompiler, some obfuscated code gets decompiled into commented-out bytecode.

However, most of the time it'll output perfectly valid Java code that'll compile if you just create the necessary maven/ant/gradle build configuration to get all of the sources loaded correctly.

Re: Fernflower Java Decompiler

#30
post #24

Earlier quoted context omitted.

I'm not sure that @NotNull example is appropriate. Java compiler does not add any checks for @NotNull annotations. Those annotations exist for IDE and linting tools, compiler doesn't care. May be there are Java-like languages like Lombok or non-standard compilers which do add those checks, but I think that Java decompiler shouldn't do assumptions of these additional tools.

https://www.jetbrains.com/help/idea/annotating-source-code.h... > When you compile your project with IntelliJ IDEA build tool, the IDE adds assertions to all code elements annotated with @NotNull. These assertions will throw an error if the elements happen to be null at runtime.

That's not java compiler. That's intellij compiler. I'd say that's very weird anti-feature, because your build in IDE and maven will work differently.
Post reply on HN