Context
JavaParser currently targets Java 8 as both its compilation source/target and its minimum supported runtime. A recent pull request (#5018) proposes jumping directly to Java 17. Before considering any specific PR, we think it is worth opening a broader discussion with the community: should we raise the baseline at all, and if so, to which version and when?
This issue is a request for comment. No decision has been made.
Why this question matters now
Java 8 was released in 2014. Maintaining compatibility with it carries a real cost:
We cannot use language features introduced after Java 8 (pattern matching, text blocks, var, records, sealed classes).
Some build tooling has reached its Java-8-compatible version ceiling (e.g. checkstyle-maven-plugin, spotless-maven-plugin).
The CI matrix currently tests against JDK 8 through 18, adding maintenance overhead.
At the same time, dropping Java 8 support is a one-way door for our users. Anyone who cannot migrate would have to freeze on the last compatible release.
The case for Java 11 as a first step
Rather than jumping directly to Java 17, a migration to Java 11 seems like a more measured first step, for the following reasons:
Java 11 is an LTS release that has been available since September 2018. Most projects that have left Java 8 have landed on Java 11 or later. The population we would be excluding is smaller and has had ample time to migrate.
The language and API modernizations unlocked by Java 11 (String.isBlank(), String.lines(), Path.of(), var in lambda parameters) are useful but modest in scope — meaning the resulting changes to the codebase would be small and easy to review.
It sets up a natural two-step path: Java 8 → Java 11 now, Java 11 → Java 17 later, as Java 11 adoption declines.
Known technical implications
Before committing to any upgrade, the community should be aware of the following:
-
Binary compatibility is broken for users on Java 8–10
Compiling with a Java 11 target produces class files that cannot run on earlier JVMs. This is a major version bump under semver and requires a migration guide and changelog entry.
-
ReflectionTypeSolver behaviour changes silently
The symbol solver resolves types by loading classes from the currently running JVM. If JavaParser runs on Java 11 (or higher), ReflectionTypeSolver will expose Java 11 APIs (e.g. List.copyOf(), List.of()) when resolving types — even if the user is analysing Java 8 source code. This is a silent semantic change. Users who need accurate Java 8 type resolution should use JarTypeSolver pointed at a Java 8 rt.jar. This should be clearly documented.
-
rt.jar is gone from Java 9 onwards
The JarTypeSolver workaround above requires a separately installed JDK 8. Users cannot point to the currently installed JDK's rt.jar because it no longer exists as of Java 9. This should be called out in the migration guide.
-
A future conflict in NodeList at Java 21
NodeList defines getFirst() and getLast() returning Optional, and addFirst()/addLast() returning NodeList for fluent chaining. Java 21 added methods with the same names to java.util.List but with incompatible return types (E and void respectively). This is not a Java 11 or 17 problem, but any version upgrade is a good moment to track this explicitly so we are not caught off guard.
Questions for the community
Is there appetite for dropping Java 8 support? Are there users or integrators who would be blocked by this change?
Java 11 or Java 17 as the first target? Is there a strong reason to skip Java 11 entirely?
Timing: should this happen in the next minor release, or be reserved for a dedicated major version?
Migration guide: who would be willing to help document the transition, in particular the ReflectionTypeSolver behaviour change?
We would like to hear from maintainers, contributors, and users before moving forward. Please share your use case and constraints below.
Context
JavaParser currently targets Java 8 as both its compilation source/target and its minimum supported runtime. A recent pull request (#5018) proposes jumping directly to Java 17. Before considering any specific PR, we think it is worth opening a broader discussion with the community: should we raise the baseline at all, and if so, to which version and when?
This issue is a request for comment. No decision has been made.
Why this question matters now
Java 8 was released in 2014. Maintaining compatibility with it carries a real cost:
We cannot use language features introduced after Java 8 (pattern matching, text blocks, var, records, sealed classes).
Some build tooling has reached its Java-8-compatible version ceiling (e.g. checkstyle-maven-plugin, spotless-maven-plugin).
The CI matrix currently tests against JDK 8 through 18, adding maintenance overhead.
At the same time, dropping Java 8 support is a one-way door for our users. Anyone who cannot migrate would have to freeze on the last compatible release.
The case for Java 11 as a first step
Rather than jumping directly to Java 17, a migration to Java 11 seems like a more measured first step, for the following reasons:
Java 11 is an LTS release that has been available since September 2018. Most projects that have left Java 8 have landed on Java 11 or later. The population we would be excluding is smaller and has had ample time to migrate.
The language and API modernizations unlocked by Java 11 (String.isBlank(), String.lines(), Path.of(), var in lambda parameters) are useful but modest in scope — meaning the resulting changes to the codebase would be small and easy to review.
It sets up a natural two-step path: Java 8 → Java 11 now, Java 11 → Java 17 later, as Java 11 adoption declines.
Known technical implications
Before committing to any upgrade, the community should be aware of the following:
Binary compatibility is broken for users on Java 8–10
Compiling with a Java 11 target produces class files that cannot run on earlier JVMs. This is a major version bump under semver and requires a migration guide and changelog entry.
ReflectionTypeSolver behaviour changes silently
The symbol solver resolves types by loading classes from the currently running JVM. If JavaParser runs on Java 11 (or higher), ReflectionTypeSolver will expose Java 11 APIs (e.g. List.copyOf(), List.of()) when resolving types — even if the user is analysing Java 8 source code. This is a silent semantic change. Users who need accurate Java 8 type resolution should use JarTypeSolver pointed at a Java 8 rt.jar. This should be clearly documented.
rt.jar is gone from Java 9 onwards
The JarTypeSolver workaround above requires a separately installed JDK 8. Users cannot point to the currently installed JDK's rt.jar because it no longer exists as of Java 9. This should be called out in the migration guide.
A future conflict in NodeList at Java 21
NodeList defines getFirst() and getLast() returning Optional, and addFirst()/addLast() returning NodeList for fluent chaining. Java 21 added methods with the same names to java.util.List but with incompatible return types (E and void respectively). This is not a Java 11 or 17 problem, but any version upgrade is a good moment to track this explicitly so we are not caught off guard.
Questions for the community
Is there appetite for dropping Java 8 support? Are there users or integrators who would be blocked by this change?
Java 11 or Java 17 as the first target? Is there a strong reason to skip Java 11 entirely?
Timing: should this happen in the next minor release, or be reserved for a dedicated major version?
Migration guide: who would be willing to help document the transition, in particular the ReflectionTypeSolver behaviour change?
We would like to hear from maintainers, contributors, and users before moving forward. Please share your use case and constraints below.