Android - Java Version
Question
This may be an interesting question for you: "What version of Java are you using for your Android projects and why?"
Updates
We've just had a big update the AGP 9.0, Kotlin 2.3.0, and also Gradle 9.3.0. Most of you will be using Kotlin Compose, but, of course, Kotlin is running on top of Java.
As of 2.3.0, Kotlin supports Java 25 bytecode (as referenced in this Jetbrains video). Does that mean we can use it directly in our Android projects? To save you skipping for an answer, it's 'no'.
Remember, we are compiling Android -> Java Bytecode -> ART for our Android apps. We will not get the performance increases from pure Java bytecode.
IMPORTANT: I do not recommend suddenly upgrading Java versions for production code unless you fully understand what you are doing. This blog post is more something to think about and something to play with.
Disclaimer: I am no expert in this area so I am sure I have some things wrong here. Think of this as more of something to look into rather than definitive instructions. Hopefully, this post will make you think and not blindly follow what I'm trying.
New Project (Android Studio Otter 3)
Starting a new project on the latest stable Android studio, my build.gradle.kts (app) gives me the following configuration:
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
So does that mean my Kotlin is being compiled to Java 11 bytecode?
Let's check my build settings:
According to that, I'm running Java 21. Of course, you may have something different set here. By the way, using GRADLE_LOCAL_JAVA_HOME is the recommended practice for Android Studio projects.
But wait, that's for my Gradle builds and not what my app is actually running on.
So how do I check what my app runs?
Let's check in the terminal with this command:
./gradlew -q javaToolchains
That reports the following information
+ JetBrains JDK 21 (21.0.8+-14196175-b1038.72)
| Location: X:\Android\Android Studio\jbr
| Language Version: 21
| Vendor: JetBrains
| Architecture: amd64
| Is JDK: true
| Detected by: Current JVM
So we must be using Java 21 bytecode for our apps!!
No. That means we're using Java 21 for Gradle. This is fun, isn't it.
Note: It says amd64, but I'm running an Intel CPU. This is fine; it's the technical name for the 64-bit extension of x86. It's the original technical name for what is often called x64 (a vendor-neutral version).
Fine - How Can We Check?
Open up your MainActivity.kt file and click on Tools->Kotlin->Show Kotlin Bytecode
At the top of the file, you'll see the following:
// ================project/MainActivity.class =================
// class version 52.0 (52)
The class version 52 relates means we are on Java 8, but really? Java 8? That's ancient!
This is not what you need to look at. We we really need to use the Javap.exe tool one one of our files.
The easiest way to do this is to find your Javap.exe file and copy the file you want to examine into that folder. I would not recommend this for general practice, but doing this as a one off is fine. Make sure to delete the .class file after. See the path below (in the app/build..) for where to find the .class file.
You should be able to find it in a similar path to below:
Or, you can find the paths and do it the long way (copying shortcuts makes this quite easy), but the path is very long:
- "X:\Android\Android Studio\jbr\bin\javap.exe" -v "X:\ProjectFolder\app\build\intermediates\built_in_kotlinc\debug\compileDebugKotlin\classes\com\github\d9l9\tests\projectName\MainActivity.class"
This path version is more sustainable as you can just replace the target when you want to check a new file. I actually ended up making a batch file to do this automatically.
This gives the following result:
So now we can see what version we are compiling our bytecode to! By default, we're getting major version: 55 which translates to Java 11 as we have specified in our build file.
Let's Upgrade
Alright, let's move up to Java 21.
Update your build.gradle.kts (app):
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
Build your project and check the output with Javap.exe. Your version number should be higher.
What happens?
Your version number is still 55.... That' doesn't work then.
We need to make another change and add jvmToolchain(21):
kotlin {
jvmToolchain(21)
}
And this will now report major version: 65! That means we're getting our bytecode as Java 21 as intended. If we remove the compileOptions and try again, we get the same result.
The kotlin jvmToolchain affects both Kotlin and Java Kotlin compilation. By default, this was using Java 11. I assume this is for compatibility with older projects.
The compileOptions affect any Java code and language support in your project (including imported libraries).You can just set jvmToolchain but keeping the compileOptions is fine.
Note: You can safely remove buildFeatures as this is no longer required. This is a legacy flag to show your project needs compose. This is active by default if you import Compose now.
The Difference
Java 21 should give some advantages for your builds. If you have trouble with Java 21, consider dropping back to Java 17. If that doesn't work, revert to Java 11.
Most importantly, you will not get all the raw Kotlin -> Java benefits as your code is being changed into Android ART bytecode. A lot of the benefits will be lost with ART, but there are still advantages.
Why Not 25?
It's too early! As of January 2026, Java 21 is the current default shipping with Android Studio Otter 3. I would not move ahead of that unless you have a very specific reason and are sure it won't cause problems.
Here's the official link to explain the Java versions.
AGP, D8, and R8 versions required for Kotlin versions
Summary
Benefits
- Faster compile times (newer JDK tooling)
- Access to newer Java language features
- Better IDE integration and tooling support
- Potential (minimal?) performance benefits
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}
kotlin {
jvmToolchain(21)
}
dependencies {
...
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
}
Desugaring allows you to use newer Java language features and APIs in your code by converting them at build time into equivalent code that works on older Android versions.
This should allow you to keep some of the Java 21 benefits. If you have trouble with Java 21 in your project, try this before downgrading to earlier versions.
Note: For Raw Kotlin, you can remove compileOptions. That should only be needed for Android applications.
plugins {
id("java-library")
alias(libs.plugins.jetbrains.kotlin.jvm)
}
kotlin {
jvmToolchain(21)
}
dependencies {...
Final Thoughts
- Performance benefits
- Understand more about the build system
- It's interesting!
Comments
Post a Comment