# Vineflower: the Java decompiler that forked its way to modern language features

> Five forks deep from JetBrains' Fernflower, Vineflower is the decompiler underneath the IntelliJ plugin most Java reverse engineers actually use, and it is the only one that treats Java 21 pattern matching as a first-class case rather than an afterthought.

**Vineflower/vineflower** — Modern Java decompiler aiming to be as accurate as possible, with an emphasis on output quality. Fork of the Fernflower decompiler.

- Repository: https://github.com/Vineflower/vineflower
- Website: https://vineflower.org/
- Stars: 2,395 · Forks: 152
- Language: Java
- License: Apache-2.0
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/vineflower-vineflower

## What Vineflower is, and where it sits

Vineflower describes itself as a modern general purpose Java and JVM language decompiler focused on providing the best quality, speed and usability. The GitHub description is more specific about the goal: it aims to be as accurate as possible, with an emphasis on output quality. That emphasis is the differentiator. Most decompilers treat the output as a debugging aid. Vineflower treats it as something a human is expected to read, sometimes for hours.

The project carries 2,374 stars, 150 forks and 103 open issues, with the last push recorded on 2026-08-18. It is Apache-2.0 licensed, with `LICENSE.md` at the root, which is a useful contrast with several other decompilers in this space whose licensing is ambiguous or restrictive. It publishes its own documentation site at vineflower.org, and it uses that site for things the README deliberately keeps short: command line argument documentation, output comparisons against other decompilers, library integration instructions, development setup and debugging guides, and a list of social platforms for support.

That division is worth noting if you are evaluating it. The README answers the question you arrive with, which is how do I run this and how do I build it. The website answers the questions you have once you have already decided, which is how do I configure it, is it actually better than the alternative, and how do I patch it. The repository topics are decompiler, fernflower, hacktoberfest and java, and only the second of those is about the software itself.

The scale also tells you something about role. Vineflower is not a research curiosity with a few users. It is infrastructure that sits inside IDEs, build plugins and automated analysis pipelines, which raises the bar on release discipline and explains why the version history has minor releases on dedicated branches rather than only trunk builds.

## The fork lineage, which explains most of the design

Vineflower's history is five steps long and each step left something behind.

The chain runs from JetBrains' Fernflower, created by Stiver, through ForgeFlower maintained by the MinecraftForge team, through FabricMC's fork of Fernflower, into Quiltflower, which Vineflower describes itself as a direct continuation of. The README's special thanks section names all five parties explicitly: Stiver for creating Fernflower, JetBrains for maintaining it, the MinecraftForge Team for maintaining ForgeFlower, the FabricMC Team for maintaining their fork, and CFR for its large suite of very useful tests.

Two of those acknowledgments explain more about Vineflower's priorities than the feature list does.

The modding communities are the reason multithreaded decompilation exists. A Minecraft mod jar is not a single class; it is thousands, and often tens of thousands, and decompiling one serially is an experience you notice. The README lists multithreaded decompilation as one of three headline features, and its origin is a workload where single-threaded throughput was unacceptable rather than merely slow.

CFR is the reason the test suite exists in the shape it does. The tree has `test/`, `testData/` and `testFixtures/` as separate top-level directories, and crediting another decompiler's tests as the basis for that harness is not a throwaway line. Decompilation is a place where it is very easy to improve one construct and silently regress three others, and the only defense is a large fixture corpus compared against known output. The 1.12.0 release adding a system to check for malformed generic types and a flag to verify different types of variable merges is that kind of defensive work.

The practical consequence for you is that Vineflower's correctness bar is set by people who decompile large real-world codebases for a living, not by an academic test corpus. If it produces something, it is usually because someone hit a case where the alternative produced something wrong.

## Running it: the CLI shape is three arguments

The command line interface is small enough to state completely. You download the latest release from the Releases tab, then run:

```bash
java -jar vineflower.jar <arguments> <source> <destination>
```

`<arguments>` is the list of command line arguments you want to pass to the decompiler, documented on the usage page of the website. `<source>` can be a jar, a zip, a folder, or a single class file. `<destination>` can be a folder, a zip, a jar, or omitted, in which case the output goes to the console.

Each of those choices matters in practice. A single class file as input is the fast path when you are reading a stack trace and want one method now. Omitting the destination is what makes the tool pipeable, so you can feed it through less or redirect into a file rather than collecting jars you did not ask for. Accepting a folder means you can point it at an unpacked mod or at a build output directory and not think about repackaging first.

The arguments themselves are the part the README does not enumerate, and that is a reasonable division, since the set changes between versions and a copied list would rot. The two flags worth knowing exist because the 1.12.0 changelog mentions them: a flag to verify different types of variable merges, and a system to check for malformed generic types. Both are debugging aids, which tells you something about where the difficult failures live.

The IntelliJ plugin is the path most people end up on. The README states that the Vineflower Intellij IDEA plugin replaces Fernflower in IDEA with Vineflower, and the plugin is published under id 18032-quiltflower, a leftover from its Quiltflower days. Replacing rather than adding to is the right behavior here, because Fernflower is IDEA's built-in decompiler and having both available in the same context mostly produces inconsistent results depending on which one the reader happened to invoke. Install the plugin and IDEA's decompile action is Vineflower everywhere, with no per-file choice to forget.

## Using it as a library, and the Java version floor

Vineflower is consumable as a library, distributed through Maven Central, and the README gives the Gradle form directly:

```groovy
dependencies {
    implementation 'org.vineflower:vineflower:<version>'
}
```

The coordinates are `org.vineflower:vineflower`. The version is a placeholder in the README because releases move, which is the normal convention, but it means you pin a specific release rather than tracking a branch.

The runtime requirement is the detail that bites people, and it has moved twice. Vineflower 1.9 and later requires Java 11 or higher to run. Vineflower 1.11 and later requires Java 17 or higher to run. There is no separate requirement for consuming it as a library versus running the jar, because it is the same artifact, so a build on Java 11 can use up to the 1.9 line and a build on Java 17 can use 1.11 and beyond. If you maintain a toolchain matrix, that is the line to encode.

More integration detail lives at the usage-code page on the website rather than in the README, which suggests the API surface is larger than the two sentences the README spends on it. It is, if the release notes are any guide: 1.11.2 improved extensibility of `StructAttribute` and `ResultSaver` implementations, which are hooks meant to be implemented by embedders rather than consumed. That is the vocabulary you care about if you are writing a plugin, and it tells you the library anticipates third-party output processors.

Two runtime requirements worth stating because they are easy to miss. The plugin loading fix in 1.11.2, for plugins not loading when a ZipFS has already been opened for the current jar, matters if you embed Vineflower in an application that itself touches jar files, which includes most JVM build tools and servers. And the 1.12.0 slim jar exists for a specific reason: the regular jar contains the main decompiler plus three bundled plugins, while the slim jar contains only the main decompiler. If you are shipping Vineflower inside something with a strict classpath, the slim classifier is the one you want.

## Modern Java support, which is the actual differentiator

The README lists its features as three bullets, and the first one carries the weight: Java 21+ support, including records, sealed classes, switch expressions, pattern matching, and more. The trailing and more is doing honest work, since the release notes show the long tail of individual constructs.

Each of those language features breaks naive decompilers in a specific way, and the release notes document the breakage.

Record pattern matching was fragile enough to produce a null pointer exception, fixed in 1.11.1 with credit to a contributor. The same release fixed a switch over an enum being decompiled as a record pattern match, which is the kind of bug that produces code that compiles and is wrong, which is worse than a crash. It also fixed a switch expression over int being turned into char, a missing cast for varargs, a stack overflow with clashing names and another with generic type inference.

Records got dedicated work in 1.12.0 with compact canonical constructor support. That sounds narrow and is not, because a record with a compact canonical constructor is a different code path than an explicit one, and getting it wrong means the decompiled constructor body does not match what the compiler generated.

The theme running through all of it is that these are not parse failures. The bytecode is valid and the decompiler reads it fine. The failures are in reconstructing intent, which is the harder half of the problem and the half that determines whether the output is usable without editing. A decompiler that crashes tells you to try something else. A decompiler that silently mis-renders a switch expression costs you an afternoon.

Two other 1.12.0 entries speak to output quality directly, which is the stated priority. There is a prettifier for if-else statements that removes else statements when the if body unconditionally returns, and a fix for field initializers being dropped from line mapping. The first makes output read like code a person wrote; the second keeps debuggers and line-accurate tooling working. Both are the kind of change that never appears in a benchmark and matters constantly in daily use.

Kotlin support improves in the same release, with support for ranges in Kotlin loops, removal of semicolons in Kotlin output, and a reduced Kotlin plugin file size. Kotlin on the JVM decompiles to Java, so a Kotlin-aware plugin is really a post-processing layer over the Java output, and it is where the library earns its reach into the Android and server modding world its fork history came from.

## Releases, contribution flow and what to expect from the project

The release history shows a project that maintains stable branches rather than only moving forward. There are three releases in the collected set, and they span a year and a half.

Version 1.11.1 shipped on 2025-03-06 as a bugfix release for the 1.11 branch, fixing issues that had appeared over the preceding week. Version 1.11.2 shipped on 2025-11-05 as a minor release on the same branch, adding type annotation support and fixing the ZipFS plugin loading issue. Version 1.12.0 shipped on 2026-04-29 as the next major release, with the variable handling, output beautification and Kotlin work described above.

So 1.11 received two maintenance releases eight months apart, and 1.12 is the current major line. If you are on 1.11, the type annotation support in 1.11.2 is a real feature gap, not a patch, and the stable branch pattern means you can take it without moving to 1.12.

The contribution flow is unusually specific in one respect: the README instructs contributors to target the latest `develop/1.xx.y` branch rather than the default branch. That matches the release history, since work happens on a development branch per minor version and is cut into a release from there. The tree supports a conventional Gradle project with `build.gradle`, `settings.gradle`, `gradle.properties`, `buildSrc/`, a `plugins/` directory, `src/`, and the three test directories. `ARCHITECTURE.md` at the root is the file to read before your first patch, and `CONTRIBUTING.md` sits beside it.

Building is one command:

```bash
./gradlew build
```

That is the whole documented build, and the presence of `gradlew` and `gradlew.bat` in the tree means it is reproducible without a local Gradle install. Development setup and debugging instructions are on the website, which is where you should look for how to run against the test fixtures.

The project's public posture is friendly to newcomers in a way worth noting given it has a `hacktoberfest` topic: contributions are called welcome in the README, issues are directed to the Issues tab, and questions go to the listed social platforms. For a tool this heavily embedded, the practical read is that the issue tracker is where correctness reports belong, and output comparison against CFR or Procyon using the test fixtures is the fastest way to find a case worth filing.

## Conclusion

Vineflower's case rests on lineage plus a willingness to ship. It inherits a decompiler JetBrains built, that Minecraft modding communities forked twice for their own bytecode problems, and that Quiltflower carried forward, and it has spent that inheritance on the parts of modern Java that break older decompilers: record patterns, sealed hierarchies, switch expressions and pattern matching. The practical route for most people is the IntelliJ plugin, which replaces Fernflower outright rather than sitting beside it, and the practical route for tooling is the Maven artifact, which has been on Central long enough to depend on. If you are picking a decompiler for anything from a stack trace down to a jar you have never seen, this is the one whose output you will end up reading rather than translating.

## FAQ

### What is a decompiler used for?

A decompiler turns compiled bytecode back into readable source-like code. In the JVM world you point one at a class file, jar or zip and get Java back, usually without the original comments, variable names or formatting. People use them for reading a stack trace that references a class you do not have sources for, for understanding how a third-party library behaves, for recovering source from a jar you are shipping, and for modding or reversing software where no source exists. The output is close to the original rather than identical to it, so a good decompiler's value is in how little manual cleanup its results need.

### Which Java decompiler is best?

For modern Java, Vineflower. It forked from JetBrains' Fernflower through ForgeFlower and FabricMC's fork into Quiltflower, and it supports Java 21+ including records, sealed classes, switch expressions and pattern matching. Its README states an emphasis on output quality, which in practice means fewer manual fixes to decompiled code. The practical caveat is that quality is subjective and case-dependent, so Vineflower publishes output comparisons against other decompilers on vineflower.org. The other names worth testing are CFR, which has the largest test suite and Vineflower credits it as a basis for its own, and Procyon.

### How do I use Vineflower in IntelliJ IDEA?

Install the Vineflower IntelliJ IDEA plugin, published as plugin id 18032-quiltflower. It replaces Fernflower in IDEA with Vineflower, so there is no per-file choice to make and no need to disable the built-in decompiler yourself. Because it replaces the built-in, decompiled output is consistent everywhere in the IDE. Vineflower requires Java 11 or higher for the 1.9 line and Java 17 or higher for 1.11 and later, so check your IDE runtime matches the version you install.

### Does Vineflower run on Minecraft or Fabric mods?

It descends from exactly that ecosystem. Vineflower is a fork of MinecraftForge's ForgeFlower and of FabricMC's fork of Fernflower, continuing Quiltflower, and its multithreaded decompilation exists largely because mod jars contain tens of thousands of classes. It also has a Kotlin plugin, since Kotlin on the JVM is common in mods, with 1.12.0 adding Kotlin loop range support and a smaller plugin file. The Forge and Fabric build toolchains both integrate a Java decompiler, so a pipeline that decompiled mods in the past likely already has a slot for this one.

## Sources

- [License: Apache-2.0](https://github.com/Vineflower/vineflower/blob/master/LICENSE)
- [Project website](https://vineflower.org/)
- [README](https://github.com/Vineflower/vineflower/blob/master/README.md)
- [Releases](https://github.com/Vineflower/vineflower/releases)
- [Vineflower/vineflower on GitHub](https://github.com/Vineflower/vineflower)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/vineflower-vineflower
