The Java Virtual Machine (JVM) is refusing to load a class file because its version number is too high for the installed Java runtime environment.

This error, UnsupportedClassVersionError, fundamentally means that the bytecode compiled by a newer Java Development Kit (JDK) cannot be understood by an older JVM. The "major version" is a specific field within the .class file format that indicates the Java SE version it was compiled against. For example, Java 8 uses major version 52, Java 11 uses 55, and Java 17 uses 61. When a JVM encounters a class file with a major version it doesn’t recognize or support, it throws this error.

Here are the most common reasons you’ll hit this, and how to fix them:

1. Your Runtime JVM is Older Than Your Compilation JDK: This is the absolute most frequent cause. You compiled your code using a newer JDK (e.g., JDK 17) but are trying to run it on an older JRE or JVM (e.g., JRE 8).

  • Diagnosis:
    • Check your project’s build configuration (e.g., pom.xml for Maven, build.gradle for Gradle) to see the sourceCompatibility and targetCompatibility settings.
    • Run java -version in your terminal in the environment where you’re executing the application. This shows the installed JRE version.
    • If you’re using an IDE, check its configured JDK for the project and for running applications.
  • Fix:
    • Option A (Recommended): Upgrade your Runtime Environment. Install a JRE or JDK that is at least as new as the one you used to compile. For example, if you compiled with JDK 17 (major version 61), you need a JRE/JVM that supports at least major version 61. To run Java 17 code, you need a Java 17 JRE or later.
    • Option B: Downgrade your Compilation JDK. If upgrading the runtime isn’t feasible, recompile your project using a JDK that matches or is older than your target runtime. For example, to run on Java 8 (major version 52), ensure your sourceCompatibility and targetCompatibility are set to 1.8 and compile with a JDK 8.
  • Why it works: The JVM understands the bytecode format of its own major version and older ones. By ensuring the JVM is as new or newer than the compiler, you guarantee compatibility.

2. Mismatched JDKs in IDE or Build Tools: Even if you have the correct JDK installed, your IDE or build tool might be configured to use an older one for compilation or execution.

  • Diagnosis:
    • Maven: Check JAVA_HOME environment variable and the maven.compiler.source/maven.compiler.target properties in your pom.xml.
    • Gradle: Check JAVA_HOME environment variable and sourceCompatibility/targetCompatibility in your build.gradle or build.gradle.kts.
    • IDE (IntelliJ IDEA): Go to File -> Project Structure -> Project and File -> Project Structure -> SDKs. Ensure the Project SDK and the SDK used for running applications are set correctly.
    • IDE (Eclipse): Go to Window -> Preferences -> Java -> Compiler and check the Compiler compliance level. Also, check the JRE system libraries added to your project.
  • Fix:
    • Update the JDK settings within your IDE and your build tool configuration to point to the newer JDK you intend to use. For instance, in Maven, ensure JAVA_HOME is set to your JDK 17 installation path and that your pom.xml reflects Java 17 compilation.
  • Why it works: Build tools and IDEs often have their own settings that can override system-wide configurations, leading to a discrepancy between what you think is being used and what’s actually being used. Correcting these internal settings ensures the intended JDK is applied.

3. Corrupted or Incomplete Class Files: Rarely, the .class file itself might be corrupted during transfer, download, or build, leading to an invalid major version field.

  • Diagnosis:
    • Manually inspect the .class file’s header using a hex editor. Look for the magic number CAFEBABE followed by two bytes representing the minor and major version.
    • Try to recompile the specific class or the entire project.
  • Fix:
    • Delete the problematic .class file and recompile the source file(s). If it’s a dependency, try to clear your local artifact repository (e.g., ~/.m2/repository for Maven, ~/.gradle/caches for Gradle) and re-download/rebuild.
  • Why it works: Recompilation generates a fresh, correct .class file. Clearing caches ensures that any potentially corrupted downloaded artifacts are fetched anew.

4. Application Server/Container Classloader Issues: If you’re deploying a WAR or EAR file to an application server (like Tomcat, JBoss/WildFly, WebSphere), the server’s classloader hierarchy might be involved. Sometimes, the server itself is running on an older JRE, or its classloader is prioritizing older JARs from its own libraries over your application’s newer ones.

  • Diagnosis:
    • Check the JVM version the application server is running with (e.g., catalina.sh or catalina.bat for Tomcat often shows this).
    • Examine the server’s lib directory for JRE/JDK JARs.
    • Use tools like jvisualvm to inspect loaded classes and their originating JARs.
  • Fix:
    • Configure the application server to run with a compatible, newer JRE/JDK. This might involve setting JAVA_HOME for the server’s startup script or modifying its configuration files.
    • Ensure your application’s dependencies are correctly packaged and that there are no conflicts with server-provided libraries. You might need to configure the server to prefer your application’s JARs or exclude conflicting server libraries.
  • Why it works: By ensuring the server runs on a compatible JVM and that classloading is managed correctly, you prevent the server’s older environment from interfering with your application’s newer bytecode.

5. Using a JRE Instead of a JDK for Compilation: While less common for UnsupportedClassVersionError, it’s possible to accidentally use a JRE (which doesn’t include the compiler javac) to build or run. If you’re using a tool that tries to compile and it’s configured with a JRE, it can lead to unexpected behavior, though typically it’s a different error. However, if you’re using a build tool that implicitly relies on a JDK’s compiler and it’s pointed to a JRE, you might encounter issues.

  • Diagnosis:
    • Verify your JAVA_HOME environment variable points to a JDK installation, not just a JRE.
    • Check your build tool configuration for explicit compiler paths.
  • Fix:
    • Set JAVA_HOME to a valid JDK directory (e.g., /usr/lib/jvm/jdk-17 or C:\Program Files\Java\jdk-17).
    • Ensure your build tool is configured to use javac from the correct JDK.
  • Why it works: A JRE lacks the javac compiler necessary to generate .class files. A JDK contains both the compiler and the runtime environment. Using a JDK ensures the compilation process itself is valid.

The next error you’ll likely encounter if you’ve fixed this is a NoClassDefFoundError or ClassNotFoundException, indicating that while the class file is loadable, the JVM can’t find a required dependency or the main class itself in the classpath.

Want structured learning?

Take the full Java course →