### Use Vineflower decompiler API in Java
Source: https://vineflower.org/usage-code
Demonstrates the core API usage for Vineflower decompiler. Shows how to configure inputs, outputs, options, and execute decompilation.
```Java
Decompiler decompiler = new Decompiler.Builder()
.inputs(inputFile) // also accepts IContextSource
.output(new SingleFileSaver(outputJar)) // also accepts DirectoryResultSaver, or a custom IResultSaver implementation
.option(IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, true) // optional, change options for the decompiler
.logger(new IFernflowerLogger() { ... }) // optional, provide a logger impl for the decompiler to use
.libraries(libraryFile) // optional, include libraries to enhance the decompiler's analysis but not decompile
.build();
decompiler.decompile();
// Done!
```
--------------------------------
### Double Brace Initializers in Enums (Java)
Source: https://vineflower.org/output-comparison
Illustrates the decompilation of enums using double brace initializers, a feature that can be challenging for decompilers. Compares how different tools handle the syntax and modifiers.
```Java
public enum TestEnum {
A {{
System.out.println("A");
}},
B {{
System.out.println("B");
}}
}
```
```Java
public static enum TestEnum {
A {
{
System.out.println("A");
}
},
B {
{
System.out.println("B");
}
};
}
```
```Java
public static enum TestEnum {
A {
private {
System.out.println("A");
}
},
B {
private {
System.out.println("B");
}
};
}
```
```Java
public static enum TestEnum {
A{
{
System.out.println("A");
}
}
,
B{
{
System.out.println("B");
}
};
}
```
```Java
public enum TestEnum permits TestEnum$1, TestEnum$2
{
A {
{
System.out.println("A");
}
},
B {
{
System.out.println("B");
}
};
}
```
--------------------------------
### Java: Try-with-resources with finally block (Java 16)
Source: https://vineflower.org/output-comparison
Illustrates the decompilation of a try-with-resources statement combined with a finally block, using bytecode generated from Java 16. Vineflower, CFR, and Procyon decompile this construct correctly, whereas Fernflower and JD-GUI do not recognize the pattern and produce more verbose or incorrect code.
```java
public void test(File file) throws FileNotFoundException {
try (Scanner scanner = new Scanner(file)) {
scanner.next();
} finally {
System.out.println("Hello");
}
}
```
```java
public void test(File file) throws FileNotFoundException {
try {
Scanner scanner = new Scanner(file);
try {
scanner.next();
} catch (Throwable var10) {
try {
scanner.close();
} catch (Throwable var9) {
var10.addSuppressed(var9);
}
throw var10;
}
scanner.close();
} finally {
System.out.println("Hello");
}
}
```
```java
public void test(File file) throws FileNotFoundException {
try (Scanner scanner = new Scanner(file);){
scanner.next();
}
finally {
System.out.println("Hello");
}
}
```
```java
public void test(final File file) throws FileNotFoundException {
try (final Scanner scanner = new Scanner(file)) {
scanner.next();
}
finally {
System.out.println("Hello");
}
}
```
```java
public void test(File file) throws FileNotFoundException {
try {
Scanner scanner = new Scanner(file);
try {
scanner.next();
scanner.close();
} catch (Throwable throwable) {
try {
scanner.close();
} catch (Throwable throwable1) {
throwable.addSuppressed(throwable1);
}
throw throwable;
}
} finally {
System.out.println("Hello");
}
}
```
--------------------------------
### Vineflower decompiled definite assignment test
Source: https://vineflower.org/output-comparison
Vineflower's reconstruction of the definite assignment test method. Demonstrates how Vineflower simplifies complex conditionals and handles variable assignments in control flow structures. Shows differences in block organization compared to original source.
```java
void testAssignments(int n, boolean bool) {
if (bool) {
int a = n;
if (n > 0 || (a = -n) > 100) {
System.out.println(a);
}
}
int b;
if (!bool && (b = n * n) <= 0) {
System.out.println(b);
} else {
System.out.println("b");
}
double cFake = 0.01;
System.out.println(cFake);
if (n < 1.0 - n && (cFake = n + 5) > cFake * cFake - cFake / 2.0 ? !(n > cFake) : !(n < 5.0 - (cFake = n))) {
cFake += 5.0;
} else {
System.out.println(cFake);
cFake += 2.0;
}
System.out.println(cFake);
double d;
if ((d = n) > 0.0) {
System.out.println(d);
}
}
```
--------------------------------
### Decompile While Loop with Break
Source: https://vineflower.org/output-comparison
Illustrates how different decompilers handle `while` loops with `break` statements. The test cases explore varying loop structures and exit conditions, examining the decompilers' ability to reconstruct the original logic.
```Java
public void test(int i) {
while (i > 10) {
i++;
if (i == 15) {
break;
}
System.out.println(0);
}
}
```
```Java
public void test(int i) {
while (i > 10) {
if (++i != 15) {
System.out.println(0);
continue;
}
break;
}
}
```
```Java
public void test(int i) {
while(true) {
if (i > 10) {
++i;
if (i != 15) {
System.out.println((int)0);
continue;
}
}
return;
}
}
```
```Java
public void test(int i) {
while (i > 10 && ++i != 15) {
System.out.println(0);
}
}
```
```Java
public void test(int i) {
while (i > 10 && ++i != 15) {
System.out.println(0);
}
}
```
```Java
public void test(int i) {
i++;
while (i > 10 && i != 15)
System.out.println(0);
}
```
--------------------------------
### Configure Sonatype snapshots repository in Gradle (Kotlin)
Source: https://vineflower.org/usage-code
Configures Gradle (Kotlin DSL) to use Sonatype OSS snapshots repository for accessing Vineflower development builds.
```Kotlin
repositories {
maven(url = "https://central.sonatype.com/repository/maven-snapshots/") {
name = "sonatype-central-snapshots"
}
}
```
--------------------------------
### Configure Sonatype snapshots repository in Maven
Source: https://vineflower.org/usage-code
Configures Maven to use Sonatype OSS snapshots repository for accessing Vineflower development builds.
```XML
sonatype-central-snapshots
https://central.sonatype.com/repository/maven-snapshots/
```
--------------------------------
### Decompile Java method with pattern matching in argument
Source: https://vineflower.org/output-comparison
Demonstrates decompilation of a method that uses pattern matching (instanceof with variable) to compute a boolean argument for another method call. The source uses a concise expression; decompilers vary between preserving the pattern match and introducing temporary variables or labels.
```Java (Vineflower)
public void test(Object o) {
this.accept(o, o instanceof String s && s.length() > 5);
}
```
```Java (Fernflower)
public void test(Object o) {
boolean var10002;
label12: {
if (o instanceof String s) {
if (s.length() > 5) {
var10002 = true;
break label12;
}
}
var10002 = false;
}
this.accept(o, var10002);
}
```
```Java (CFR)
public void test(Object o) {
String s;
Object object = o;
this.accept(o, object instanceof String && (s = (String)object).length() > 5);
}
```
```Java (Procyon)
public void test(final Object o) {
boolean b = false;
Label_0029: {
if (o instanceof final String s) {
if (s.length() > 5) {
b = true;
break Label_0029;
}
}
b = false;
}
this.accept(o, b);
}
```
--------------------------------
### Configure Sonatype snapshots repository in Gradle (Groovy)
Source: https://vineflower.org/usage-code
Configures Gradle (Groovy DSL) to use Sonatype OSS snapshots repository for accessing Vineflower development builds.
```Groovy
repositories {
maven {
name = "sonatype-central-snapshots"
url = "https://central.sonatype.com/repository/maven-snapshots/"
}
}
```
--------------------------------
### Switch Pattern Matching (Java 21)
Source: https://vineflower.org/output-comparison
Shows the decompilation of Java 21's switch pattern matching feature. Evaluates which decompilers can correctly reconstruct switch expressions and handle the underlying invokedynamic calls.
```Java
public String test2(Object o) {
return switch (o) {
case Integer i -> Integer.toString(i);
case String s -> s;
default -> "null";
};
}
```
```Java
public String test2(Object o) {
return switch (o) {
case Integer i -> Integer.toString(i);
case String s -> s;
default -> "null";
};
}
```
```Java
public String test2(Object o) {
String var10000;
switch (o) {
case Integer i -> var10000 = Integer.toString(i);
case String s -> var10000 = s;
default -> var10000 = "null";
}
return var10000;
}
```
```Java
public String test2(Object o) {
Object object = o;
Objects.requireNonNull(object);
Object object2 = object;
int n = 0;
return switch (SwitchBootstraps.typeSwitch("typeSwitch", new Object[]{Integer.class, String.class}, (Object)object2, n)) {
case 0 -> {
Integer i = (Integer)object2;
yield Integer.toString(i);
}
case 1 -> {
String s;
yield s = (String)object2;
}
default -> "null";
};
}
```
```Java
public String test2(final Object o) {
Objects.requireNonNull(o);
String string = null;
switch (/* invokedynamic(!)
*/ProcyonInvokeDynamicHelper_2.invoke(o, false)) {
case 0: {
final Integer i = (Integer)o;
string = Integer.toString(i);
break;
}
case 1: {
final String s = string = (String)o;
break;
}
default: {
string = "null";
break;
}
}
return string;
}
```
--------------------------------
### Boxing and Unboxing in Conditional Statements (Java)
Source: https://vineflower.org/output-comparison
Demonstrates how different Java decompilers handle boxing and unboxing operations within conditional statements. Some decompilers may incorrectly unbox constants, leading to syntax errors.
```Java
public void test(int x) {
if ((x ^ 126) == 7) {
Integer.valueOf(0xFFFF);
} else {
Boolean.valueOf(false);
}
Float.valueOf(0.9f);
}
```
```Java
public void test(int x) {
if ((x ^ 126) == 7) {
Integer.valueOf(65535);
} else {
Boolean.valueOf(false);
}
Float.valueOf(0.9F);
}
```
```Java
public void test(int x) {
if ((x ^ 126) == 7) {
65535;
} else {
false;
}
0.9F;
}
```
```Java
public void test(int x) {
if ((x ^ 0x7E) == 7) {
Integer.valueOf(65535);
} else {
Boolean.valueOf(false);
}
Float.valueOf(0.9f);
}
```
```Java
public void test(final int x) {
if ((x ^ 0x7E) == 0x7) {
65535;
}
else {
false;
}
0.9f;
}
```
```Java
public void test(int x) {
if ((x ^ 0x7E) == 7) {
Integer.valueOf(65535);
} else {
Boolean.valueOf(false);
}
Float.valueOf(0.9F);
}
```
--------------------------------
### Decompile Java switch expression method
Source: https://vineflower.org/output-comparison
Shows how various decompilers translate a Java 14 switch expression that returns a string based on an integer input. No external dependencies are required. The method returns a string for cases 1 and 2, otherwise "Unknown". Some decompilers generate auxiliary variables or malformed code.
```Java (Vineflower)
public String test(int i) {
return switch (i) {
case 1 -> "1";
case 2 -> "2";
default -> "Unknown";
};
}
```
```Java (CFR)
public String test(int i) {
return switch (i) {
case 1 -> "1";
case 2 -> "2";
default -> "Unknown";
};
}
```
```Java (Procyon)
public void test(final int i) {
return switch (i) {
case 1 -> "1";
case 2 -> "2";
default -> "Unknown";
};
}
```
```Java (Fernflower)
public String test(int i) {
String var10000;
switch (i) {
case 1 -> var10000 = "1";
case 2 -> var10000 = "2";
default -> var10000 = "Unknown";
}
return var10000;
}
```
```Java (JD-GUI)
public String test(int i) {
switch (i) {
case 1:
case 2:
}
return
"Unknown";
}
```
--------------------------------
### Procyon decompiled definite assignment test
Source: https://vineflower.org/output-comparison
Procyon's reconstruction of the definite assignment test method. Uses labeled break constructs and final variable modifiers. Shows different approaches to handling conditional expressions compared to other decompilers.
```java
void testAssignments(final int n, final boolean bool) {
if (bool) {
int a = n;
if (n > 0 || (a = -n) > 100) {
System.out.println(a);
}
}
Label_0062: {
if (!bool) {
int b = n;
if ((b *= n) <= 0) {
System.out.println(b);
break Label_0062;
}
}
System.out.println("b");
}
final double cFake = 0.01;
System.out.println(cFake);
double c = 0.0;
Label_0161: {
Label_0153: {
if (n >= 1.0 - n || (c = n + 5) <= c * c - c / 2.0) {
if (n >= 5.0 - (c = n)) {
break Label_0153;
}
}
else if (n <= c) {
break Label_0153;
}
System.out.println(c);
c += 2.0;
break Label_0161;
}
c += 5.0;
}
System.out.println(c);
final double d;
final boolean x;
if (x = ((d = n) > 0.0)) {
System.out.println(d);
}
}
```
--------------------------------
### Original Source: Nameless Local Class Test - Java
Source: https://vineflower.org/output-comparison
This source code demonstrates a nameless local class assigned to a var variable, defining a println method that prints to System.out. The method calls println with a string argument. Purpose: Tests decompiler support for Java 10+ var and anonymous classes. Limitations: Requires Java 10+ for var keyword.
```java
public void testNamelessTypeVirtual() {
var printer = new Object() {
void println(String s) {
System.out.println(s);
}
};
printer.println("goodbye, world!");
}
```
--------------------------------
### Decompiling Java 21 Record Patterns
Source: https://vineflower.org/output-comparison
Record patterns enable destructuring in pattern matching, introduced in Java 21, allowing concise instanceof checks with variable binding. This snippet displays the source method using record patterns and decompiled versions, where Vineflower approximates it with synthetic variables but others use verbose try-catch for shared exception handling. Depends on record definition; inputs are bytecode, outputs vary in readability and correctness, with limitations in preserving pattern syntax and control flow.
```Java
public void test1(R r) {
if (r instanceof R(int x, Object o)) {
System.out.println(x);
System.out.println(o);
}
}
// Not shown in decompiled output for space
record R(int i, Object o) {}
```
```Java
public void test1(R r) {
if (r instanceof R(int var5, Object var8)) {
System.out.println(var5);
System.out.println(var8);
}
}
```
```Java
public void test1(R r) {
if (r instanceof R) {
R var10000 = r;
try {
var9 = var10000.i();
} catch (Throwable var7) {
throw new MatchException(var7.toString(), var7);
}
int o = var9;
int x = o;
var10000 = r;
try {
var11 = var10000.o();
} catch (Throwable var6) {
throw new MatchException(var6.toString(), var6);
}
Object o = var11;
System.out.println(x);
System.out.println(o);
}
}
```
```Java
public void test1(R r) {
if (r instanceof R) {
Object object;
int x;
R r2 = r;
try {
int n;
x = n = r2.i();
}
catch (Throwable throwable) {
throw new MatchException(throwable.toString(), throwable);
}
Object o = object = r2.o();
System.out.println(x);
System.out.println(o);
}
}
```
```Java
public void test1(final R r) {
while (true) {
if (r instanceof R) {
try {
final int x = r.i();
final Object o = r.o();
System.out.println(x);
System.out.println(o);
}
catch (final Throwable cause) {
throw new MatchException(cause.toString(), cause);
}
return;
}
continue;
}
}
```
```Java
public void test1(R r) {
if (r instanceof R) {
R r1 = r;
try {
int i = r1.i(), x = i;
Object object1 = r1.o(), o = object1;
System.out.println(x);
System.out.println(o);
} catch (Throwable throwable) {
throw new MatchException(throwable.toString(), throwable);
}
}
}
```
--------------------------------
### Decompile Java method using null in generic context
Source: https://vineflower.org/output-comparison
Illustrates decompilation of a method that retrieves an Optional from a map and returns its value or null. The code works with standard Java collections and Optional. Some decompilers add unnecessary casts, while JD-GUI inserts extra type casts for the map key.
```Java (Vineflower)
public Object doThing(Map> map) {
return map.get(0).orElse(null);
}
```
```Java (CFR)
public Object doThing(Map> map) {
return map.get(0).orElse(null);
}
```
```Java (Fernflower)
public Object doThing(Map> map) {
return (map.get(0)).orElse((Object)null);
}
```
```Java (Procyon)
public Object doThing(final Map> map) {
return map.get(0).orElse((Object)null);
}
```
```Java (JD-GUI)
public Object doThing(Map> map) {
return ((Optional)map.get(Integer.valueOf(0))).orElse(null);
}
```
--------------------------------
### JD-GUI Decompilation: Nameless Local Class - Java
Source: https://vineflower.org/output-comparison
JD-GUI incorrectly decompiles by creating a named Object without the inner class definition, passing 'this' to the constructor and calling println directly on it. No var usage. Limitations: Completely misses the anonymous class structure, resulting in non-compilable or incorrect code.
```java
public void testNamelessTypeVirtual() {
Object object = new Object(this);
object.println("goodbye, world!");
}
```
--------------------------------
### Test definite assignment with complex conditionals in Java
Source: https://vineflower.org/output-comparison
Original test method demonstrating various definite assignment scenarios in Java. Shows complex conditional expressions with embedded assignments and control flow constructs. Used as input for comparing decompiler outputs.
```java
void testAssignments(int n, boolean bool) {
int a;
if (bool && ((a = n) > 0 || (a = -n) > 100)) {
System.out.println(a);
}
int b;
if (bool || (b = (b = n) * b) > 0) {
System.out.println("b");
} else {
System.out.println(b);
}
{
double cFake = 0.01;
System.out.println(cFake);
}
double c;
if (!((n < 1.0 - n) && (c = (n + 5)) > (c * c - c / 2)) ? n < 5.0 - (c = n) : n > c) {
System.out.println(c);
c += 2;
} else {
c += 5;
}
System.out.println(c);
boolean x;
double d;
if (x = ((d = n) > 0)) {
System.out.println(d);
}
}
```
--------------------------------
### JD-GUI decompiled definite assignment test
Source: https://vineflower.org/output-comparison
JD-GUI's reconstruction of the definite assignment test method. Maintains some structural similarity to the original source. Uses explicit double literal suffixes (D) and simplified conditional expressions.
```java
void testAssignments(int n, boolean bool) {
int a;
if (bool && ((a = n) > 0 || (a = -n) > 100))
System.out.println(a);
int b;
if (bool || (b = (b = n) * b) > 0) {
System.out.println("b");
} else {
System.out.println(b);
}
double cFake = 0.01D;
System.out.println(cFake);
double c;
if (((c = (n + 5)) <= c * c - c / 2.0D) ? (n < 5.0D - (c = n)) : (n > c)) {
System.out.println(c);
c += 2.0D;
} else {
c += 5.0D;
}
System.out.println(c);
boolean x;
double d;
if (x = ((d = n) > 0.0D))
System.out.println(d);
}
```
--------------------------------
### CFR Decompilation: Switch Loop with Labeled Break - Java
Source: https://vineflower.org/output-comparison
CFR fails to fully structure the code, using a for loop but approximating the labeled break with a goto label and continue statement. It assumes j is declared externally and includes diagnostic comments. Inputs: int i. Outputs: Prints with goto-based flow. Limitations: Relies on unstructured goto, incomplete variable scoping.
```java
/*
* Unable to fully structure code
*/
public void test8(int i) {
switch (i) {
case 0: {
for (j = 0; j < 10; ++j) {
if (j != 3) {
continue;
}
** GOTO lbl8
}
System.out.println(0);
lbl8:
// 2 sources
System.out.println("after");
}
case 1: {
System.out.println(1);
}
}
System.out.println("after2");
}
```
--------------------------------
### Decompile Super Wildcard Synthetic Cast
Source: https://vineflower.org/output-comparison
Demonstrates how decompilers handle synthetic casts, specifically related to super wildcards in generic types. The test aims to evaluate the decompression of code requiring type casts that are not explicitly present in the bytecode.
```Java
public Class test(Inner inner) {
Class t = (Class) inner.get();
return (Class) inner.get();
}
// Not shown in decompiled output for space
public class Inner {
public Class super T> get() {
return null;
}
}
```
```Java
public Class test(Inner inner) {
Class t = inner.get();
return inner.get();
}
```
```Java
public Class test(Inner inner) {
Class t = inner.get();
return inner.get();
}
```
```Java
public Class test(final Inner inner) {
final Class t = (Class)inner.get();
return (Class)inner.get();
}
```
```Java
public Class test(Inner inner) {
Class t = inner.get();
return inner.get();
}
```
--------------------------------
### Fernflower decompiled definite assignment test
Source: https://vineflower.org/output-comparison
Fernflower's reconstruction of the definite assignment test method. Shows labeled break constructs and explicit type casting behavior. Illustrates how Fernflower handles nested conditionals with goto-like structures.
```java
void testAssignments(int n, boolean bool) {
int a;
if (bool && (n > 0 || (a = -n) > 100)) {
System.out.println(a);
}
int b;
if (!bool && (b = n * n) <= 0) {
System.out.println(b);
} else {
System.out.println("b");
}
double cFake;
label38: {
label55: {
cFake = 0.01;
System.out.println(cFake);
if ((double)n < (double)1.0F - (double)n && (cFake = (double)(n + 5)) > cFake * cFake - cFake / (double)2.0F) {
if ((double)n > cFake) {
break label55;
}
} else if ((double)n < (double)5.0F - (cFake = (double)n)) {
break label55;
}
cFake += (double)5.0F;
break label38;
}
System.out.println(cFake);
cFake += (double)2.0F;
}
System.out.println(cFake);
double d;
if ((d = (double)n) > (double)0.0F) {
System.out.println(d);
}
}
```
--------------------------------
### Procyon Decompilation: Switch Loop with Labeled Break - Java
Source: https://vineflower.org/output-comparison
Procyon's output incorrectly nests a for loop inside a while(true), leading to infinite loop potential and misplaced print statements for the labeled break. It adds final to parameters. Dependencies: None. Limitations: Distorts control flow, printing 'after' inside the if condition instead of after the loop.
```java
public void test8(final int i) {
switch (i) {
case 0: {
while (true) {
for (int j = 0; j < 10; ++j) {
if (j == 3) {
System.out.println("after");
}
}
System.out.println(0);
continue;
}
}
case 1: {
System.out.println(1);
break;
}
}
System.out.println("after2");
}
```
--------------------------------
### Add Vineflower dependency in Gradle (Kotlin)
Source: https://vineflower.org/usage-code
Adds Vineflower as a dependency in a Gradle project using Kotlin DSL. Configures Maven Central repository and implementation dependency.
```Kotlin
repositories {
mavenCentral()
}
dependencies {
implementation("org.vineflower:vineflower:1.11.2")
}
```
--------------------------------
### CFR Decompilation: Nameless Local Class - Java
Source: https://vineflower.org/output-comparison
CFR correctly uses var for the nameless local class and reconstructs the anonymous Object with the println method, similar to the source. It handles the method call properly. Dependencies: Java 10+ var support. Limitations: Minor formatting differences, but functionally accurate.
```java
public void testNamelessTypeVirtual() {
var printer = new Object(){
void println(String s) {
System.out.println(s);
}
};
printer.println("goodbye, world!");
}
```
--------------------------------
### Add Vineflower dependency in Gradle (Groovy)
Source: https://vineflower.org/usage-code
Adds Vineflower as a dependency in a Gradle project using Groovy DSL. Configures Maven Central repository and implementation dependency.
```Groovy
repositories {
mavenCentral()
}
dependencies {
implementation "org.vineflower:vineflower:1.11.2"
}
```
--------------------------------
### Procyon Decompilation: Nameless Local Class - Java
Source: https://vineflower.org/output-comparison
Procyon infers the type as Object without using var, adding final to the local variable and parameter. It reconstructs the anonymous class but loses the var inference. Outputs: Prints the string. Limitations: Invalid without var, requires explicit Object type.
```java
public void testNamelessTypeVirtual() {
final Object printer = new Object() {
void println(final String s) {
System.out.println(s);
}
};
printer.println("goodbye, world!");
}
```
--------------------------------
### Original Source: Switch Loop with Labeled Break Test - Java
Source: https://vineflower.org/output-comparison
This source code implements a switch statement containing a for loop with a labeled break to test decompiler handling of nested control flow. The method takes an int parameter i and prints values based on the case, exiting the loop early at j==3. Dependencies: Java standard library for System.out. Limitations: Tests specific to Java 8+ labeled statements.
```java
public void test8(int i) {
switch (i) {
case 0:
label: {
for (int j = 0; j < 10; j++) {
if (j == 3) {
break label;
}
}
System.out.println(0);
}
System.out.println("after");
case 1:
System.out.println(1);
}
System.out.println("after2");
}
```
--------------------------------
### Decompiling Java 15 Text Blocks
Source: https://vineflower.org/output-comparison
Text blocks are multi-line string literals introduced in Java 15, compiling to the same bytecode as concatenated strings. This snippet shows the original source text block and decompiled outputs from various tools, which mostly convert it to escaped newline strings except Procyon. No external dependencies; inputs are bytecode from the source, outputs are readable Java code with potential loss of original formatting.
```Java
private final String text = """
Hello!
This is a text block!
It's multiple lines long.
I can use "quotes" in it.
It's rather cool.
""";
```
```Java
private final String text = "Hello!\nThis is a text block!\nIt's multiple lines long.\nI can use \"quotes\" in it.\nIt's rather cool.\n";
```
```Java
private final String text = "Hello!\nThis is a text block!\nIt's multiple lines long.\nI can use \"quotes\" in it.\nIt's rather cool.\n";
```
```Java
private final String text = "Hello!\nThis is a text block!\nIt's multiple lines long.\nI can use \"quotes\" in it.\nIt's rather cool.\n";
```
```Java
private final String text = """
Hello!
This is a text block!
It's multiple lines long.
I can use "quotes" in it.
It's rather cool.
""";
```
```Java
private final String text = "Hello!\nThis is a text block!\nIt's multiple lines long.\nI can use \"quotes\" in it.\nIt's rather cool.\n";
```
--------------------------------
### Decompile Local Enums in Java
Source: https://vineflower.org/output-comparison
Demonstrates how different decompilers handle Java 16 local enums. Local enums are created within a method and have scope limited to that method. This tests the decompilers' ability to recognize and reproduce this feature accurately.
```Java
public void test(int i) {
enum Type {
VALID,
INVALID
}
Type type = i == 0 ? Type.VALID : Type.INVALID;
}
```
```Java
public void test(int i) {
enum Type {
VALID,
INVALID;
}
Type type = i == 0 ? Type.VALID : Type.INVALID;
}
```
```Java
public void test(int i) {
final class Type extends Enum {
VALID,
INVALID;
// $FF: synthetic method
private static Type[] $values() {
return new Type[]{VALID, INVALID};
}
}
Type type = i == 0 ? Type.VALID : Type.INVALID;
}
```
```Java
public void test(int i) {
static enum Type {
VALID,
INVALID;
}
Type type = i == 0 ? Type.VALID : Type.INVALID;
}
```
```Java
public void test(final int i) {
enum Type {
VALID,
INVALID;
}
final Type type = (i == 0) ? Type.VALID : Type.INVALID;
}
```
```Java
public void test(int i) {
Type type = (i == 0) ? Type.VALID : Type.INVALID;
}
```
--------------------------------
### CFR decompiled definite assignment test
Source: https://vineflower.org/output-comparison
CFR's reconstruction of the definite assignment test method. Uses goto statements and block labels to represent complex control flow. Indicates inability to fully structure some code segments with explicit comments.
```java
/*
* Unable to fully structure code
*/
void testAssignments(int n, boolean bool) {
block6: {
if (bool && ((a = n) > 0 || (a = -n) > 100)) {
System.out.println(a);
}
if (bool) ** GOTO lbl-1000
b = n;
if ((b *= b) > 0) lbl-1000:
// 2 sources
{
System.out.println("b");
} else {
System.out.println(b);
}
cFake = 0.01;
System.out.println(cFake);
if ((double)n < 1.0 - (double)n && (c = (double)(n + 5)) > c * c - c / 2.0) break block6;
c = n;
if (!((double)n < 5.0 - v0)) ** GOTO lbl-1000
** GOTO lbl-1000
}
if ((double)n > c) lbl-1000:
// 2 sources
{
System.out.println(c);
c += 2.0;
} else lbl-1000:
// 2 sources
{
c += 5.0;
}
System.out.println(c);
d = n;
x = v1 > 0.0;
if (x) {
System.out.println(d);
}
}
```
--------------------------------
### Vineflower Decompilation: Switch Loop with Labeled Break - Java
Source: https://vineflower.org/output-comparison
Vineflower's output reconstructs the control flow using a while loop with condition checks for the loop bounds and labeled break, correctly placing prints after the loop. It takes int i as input and outputs prints accordingly. Limitations: Converts for loop to while loop, losing original iteration structure.
```java
public void test8(int i) {
switch (i) {
case 0:
int j = 0;
while (true) {
if (j >= 10) {
System.out.println(0);
break;
}
if (j == 3) {
break;
}
j++;
}
System.out.println("after");
case 1:
System.out.println(1);
}
System.out.println("after2");
}
```
--------------------------------
### Java: Shift left operation on long array
Source: https://vineflower.org/output-comparison
Demonstrates the decompilation of a loop involving a left shift operation on a long array element. Fernflower fails to decompile this snippet due to a bug in its statement resugaring, while Vineflower, CFR, Procyon, and JD-GUI successfully decompile it.
```java
public static void test(long[] l) {
long x = l[0];
for (int i = 1; i < 2; i++) {
x <<= 3;
}
x = l[4];
}
```
```java
public static void test(long[] l) {
// $FF: Couldn't be decompiled
}
```
```java
public static void test(long[] l) {
long x = l[0];
for (int i2 = 1; i2 < 2; ++i2) {
x <<= 3;
}
x = l[4];
}
```
```java
public static void test(final long[] l) {
long x = l[0];
for (int i = 1; i < 2; ++i) {
x <<= 3;
}
x = l[4];
}
```
```java
public static void test(long[] l) {
long x = l[0];
for (int i = 1; i < 2; i++)
x <<= 3L;
x = l[4];
}
```
--------------------------------
### Fernflower Decompilation: Nameless Local Class - Java
Source: https://vineflower.org/output-comparison
Fernflower struggles with type inference, using placeholders for the var variable and casting. It reconstructs the anonymous class but fails to name the local variable properly. Outputs: Prints the string via the method. Limitations: Unresolvable types lead to compilation errors.
```java
public void testNamelessTypeVirtual() {
printer = ()(new Object() {
void println(String s) {
System.out.println(s);
}
});
printer.println("goodbye, world!");
}
```
--------------------------------
### Add Vineflower dependency in Maven
Source: https://vineflower.org/usage-code
Adds Vineflower as a dependency in a Maven project. Specifies the group ID, artifact ID, and version for Maven Central.
```XML
org.vineflower
vineflower
1.11.2
```
--------------------------------
### Fernflower Decompilation: Switch Loop with Labeled Break - Java
Source: https://vineflower.org/output-comparison
Fernflower's decompilation uses a while loop similar to Vineflower, with increment via ++j and explicit casts on println arguments. It preserves the control flow but does not recover the for loop. Dependencies: Java runtime. Limitations: Adds unnecessary type casts like (int)0.
```java
public void test8(int i) {
switch (i) {
case 0:
int j = 0;
while(true) {
if (j >= 10) {
System.out.println((int)0);
break;
}
if (j == 3) {
break;
}
++j;
}
System.out.println("after");
case 1:
System.out.println((int)1);
}
System.out.println("after2");
}
```
--------------------------------
### Java: Double casted float precision handling
Source: https://vineflower.org/output-comparison
Compares how different Java decompilers handle the implicit casting of a float constant to a double. Vineflower, Fernflower, and CFR correctly represent the constant as a float, while Procyon and JD-GUI use a rounded double literal. Fernflower also includes an unnecessary explicit cast.
```java
public void test() {
double x = 0.2F;
}
```
```java
public void test() {
double x = (double)0.2F;
}
```
```java
public void test() {
double x = 0.2f;
}
```
```java
public void test() {
final double x = 0.20000000298023224;
}
```
```java
public void test() {
double x = 0.20000000298023224D;
}
```