Java 21 Gradle Unsupported class file major version 65
Problem Statement
When using Gradle 8.5 with Java 21, you may encounter an error during compilation when introducing new dependencies: Unsupported class file major version 65
. This error typically appears as:
startup failed:
General error during conversion: Unsupported class file major version 65
java.lang.IllegalArgumentException: Unsupported class file major version 65
at groovyjarjarasm.asm.ClassReader.<init>(ClassReader.java:199)
...
Key observations:
- The error occurs when adding new dependencies to your project
- Compilation succeeds with Java 17 (JDK 17)
- A workaround exists: compiling with Java 17, cleaning the build, then switching to Java 21
- Error code 65 corresponds to Java 21 class files (major version 65 = Java 21)
The core issue involves compatibility between your Gradle version, JDK, and dependencies—specifically older components that don't recognize Java 21's class file format.
Why This Happens
The error occurs because:
- Java 21 uses class file major version 65
- Older versions of Gradle (pre-8.6) and related tooling contain outdated ASM libraries that don't support version 65
- Dependency resolution mechanisms may unexpectedly trigger incompatible components
The workaround you discovered works because the initial Java 17 build generates compatible class files, but this isn't a sustainable solution.
Recommended Solutions
1. Upgrade Gradle to Java 21-Compatible Version
Minimum Requirements:
- Gradle 8.6+ (first version with full Java 21 support)
- Gradle 8.7+ (recommended for latest stability patches)
Update your gradle-wrapper.properties
:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2. Configure Java Toolchain (Recommended Approach)
Add to your build.gradle
:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
Benefits of Java Toolchains:
- Automatically detects compatible JDKs
- Ensures consistent compilation across environments
- Eliminates manual JDK path configuration
3. Set Explicit Compatibility Flags
In your build.gradle
:
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
WARNING
This alone may not resolve the issue if your Gradle version is outdated or cache is corrupted. Combine with Solution 1.
4. Clear Gradle Cache and Verify Environment
Delete project-specific caches:
bash./gradlew clean rm -rf .gradle
Verify environment variables:
bash# Check JAVA_HOME matches Java 21 installation echo $JAVA_HOME # Example output should point to JDK 21: # /Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home
Update system PATH to include JDK 21 binaries first
5. For Android Projects
Update Android Gradle Plugin (AGP) in settings.gradle
:
pluginManagement {
plugins {
id 'com.android.application' version '8.4.0' // Min for Java 21
id 'com.android.library' version '8.4.0'
}
}
Update Gradle wrapper (as shown in Solution 1)
Solution Comparison Table
Approach | Benefit | When to Use |
---|---|---|
Java Toolchain (Recommended) | Automatic JDK handling | All new projects Multi-developer environments |
Gradle Upgrade | Resolves core compatibility | Required for any Java 21 setup |
Compatibility Flags | Explicit version targeting | Projects requiring specific bytecode output |
Cache Clean + Env Check | Resolves configuration conflicts | After changing JDK installations |
Android Plugin Update | Fixes Android-specific issues | Android projects using Java 21 |
Why These Solutions Work
- Gradle 8.6+ includes updated ASM libraries (9.5+) that support class file version 65
- The Java toolchain feature ensures consistent JDK usage across all compilation tasks
- Cache clearing eliminates corrupted class files from previous builds
- Environment verification prevents conflicts between multiple JDK installations
Best Practices
- Verify Gradle version with
./gradlew --version
- Use SDKMAN! for managing multiple JDK versions
- Prefer toolchains over manual JDK path configuration
Preventing Future Version Conflicts
- Create
gradle.properties
with explicit version:
# gradle.properties
javaVersion=21
org.gradle.java.home=/path/to/jdk21
- Reference in
build.gradle
:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(providers.gradleProperty("javaVersion").get().toInteger())
}
}
These solutions resolve the core compatibility conflict while establishing a sustainable configuration for Java 21 development with Gradle. The Java toolchain approach provides the most robust long-term solution by decoupling your project from specific JDK installations.