Tecnología · GUÍA PRÁCTICA
¿UnsupportedClassVersionError? Prueba la clase y la JVM real antes de cambiar Java
El error nombra ambos lados de la incompatibilidad. Conserva el major, el artefacto y el lanzador real; decide entre subir el runtime o retargetear la compilación; elimina salidas antiguas y verifica el mismo artefacto en local, CI y un entorno similar a producción.

El error nombra ambos lados de la incompatibilidad. Conserva el major, el artefacto y el lanzador real; decide entre subir el runtime o retargetear la compilación; elimina salidas antiguas y verifica el mismo artefacto en local, CI y un entorno similar a producción.
Una JVM solo carga versiones de clase compatibles; rechaza un major superior antes de ejecutar la aplicación. Java 8 a Java 25 corresponden a majors de clase 52 a 69.
1. Congela la incompatibilidad exacta
Copia el primer UnsupportedClassVersionError completo: clase, versión de archivo, máximo reconocido, comando lanzador y hora. Registra java -version y javac -version dentro del contexto que falla, no en otro shell abierto después.
Traduce ambos majors con la especificación JVM, pero no te quedes en la tabla. Un mismatch normal y un minor 65535 de preview exigen cosas distintas; conserva major y minor cuando aparezcan.
2. Identifica el artefacto rechazado
Localiza el .class o JAR exacto del primer frame. Registra ruta, hash, coordenadas o digest de imagen y procedencia de compilación. Usa javap -verbose sobre la clase extraída cuando sea posible para confirmar el major sin ejecutarla.
Decide si pertenece a aplicación, plugin de build, procesador, ayudante IDE o dependencia transitiva. Cambiar el target de la aplicación no retargetea un plugin externo ya publicado.
3. Prueba el runtime que realmente carga
Sigue el proceso que carga la clase. Captura ruta java resuelta, línea de comando, JAVA_HOME o toolchain, directorio e imagen. En servicios revisa la unidad; en CI el paso runner; en IDE y daemons reinicia y revisa su runtime.
No uses which java del shell como única prueba. Wrappers, gestores SDK, symlinks, reutilización de daemon, PATH y capas de contenedor pueden escoger otra JVM.
4. Elige una sola dirección compatible
Si se necesita el bytecode nuevo y las dependencias lo permiten, actualiza el runtime del lanzador propietario y revisa su soporte. Cambia servicio, imagen CI, IDE o contenedor, no solo el shell, y reinicia daemons persistentes.
Si debe quedarse el runtime viejo, retargetea código controlado con --release o equivalente y elige dependencias o plugins con bytecode compatible. No edites cabeceras ni confundas compatibilidad fuente con runtime.
5. Elimina salidas antiguas y mezcladas
Borra o aísla outputs, cachés y paquetes que puedan conservar clases nuevas. Haz un build limpio con el toolchain elegido, registra el hash y revisa clases de aplicación, generadas y dependencias.
En módulos múltiples, un módulo, tarea generada o plugin puede usar otro JDK. Prueba log, selección de toolchain y paquete final; compilar con éxito no basta.
6. Verifica cada punto de entrada real
Ejecuta el mismo hash en shell, IDE o build tool, CI, servicio y contenedor similar a producción. La primera clase debe cargar, las pruebas pasar y no debe aparecer otra clase incompatible.
Guarda una matriz con lanzador, ruta java, versión runtime, hash, major, resultado y rollback. Solo termina cuando una política documentada controla build y loaders.
