Recibo un mensaje NoClassDefFoundError
cuando ejecuto mi aplicación Java. ¿Cuál es típicamente la causa de esto?
Recibo un mensaje NoClassDefFoundError
cuando ejecuto mi aplicación Java. ¿Cuál es típicamente la causa de esto?
Respuestas:
Esto se produce cuando hay un archivo de clase del que depende su código y está presente en tiempo de compilación pero no se encuentra en tiempo de ejecución. Busque diferencias en sus rutas de clase de tiempo de ejecución y tiempo de ejecución.
Si bien es posible que esto se deba a una falta de coincidencia de classpath entre el tiempo de compilación y el tiempo de ejecución, no es necesariamente cierto.
Es importante mantener dos o tres excepciones diferentes directamente en nuestra cabeza en este caso:
java.lang.ClassNotFoundException
Esta excepción indica que la clase no se encontró en el classpath. Esto indica que estábamos intentando cargar la definición de clase, y la clase no existía en el classpath.
java.lang.NoClassDefFoundError
Esta excepción indica que la JVM buscó en su estructura interna de datos de definición de clase la definición de una clase y no la encontró. Esto es diferente a decir que no se pudo cargar desde el classpath. Por lo general, esto indica que anteriormente intentamos cargar una clase desde el classpath, pero falló por alguna razón, ahora estamos tratando de usar la clase nuevamente (y por lo tanto necesitamos cargarla, ya que falló la última vez), pero nosotros ' Ni siquiera vamos a intentar cargarlo, porque no logramos cargarlo antes (y sospechamos razonablemente que volveríamos a fallar). La falla anterior podría ser una ClassNotFoundException o una ExceptionInInitializerError (que indica una falla en el bloque de inicialización estática) o cualquier otro problema. El punto es que un NoClassDefFoundError no es necesariamente un problema de classpath.
Error: Could not find or load main class
se clasificará en qué categoría de error.
Aquí está el código para ilustrar java.lang.NoClassDefFoundError
. Consulte la respuesta de Jared para obtener una explicación detallada.
NoClassDefFoundErrorDemo.java
public class NoClassDefFoundErrorDemo {
public static void main(String[] args) {
try {
// The following line would throw ExceptionInInitializerError
SimpleCalculator calculator1 = new SimpleCalculator();
} catch (Throwable t) {
System.out.println(t);
}
// The following line would cause NoClassDefFoundError
SimpleCalculator calculator2 = new SimpleCalculator();
}
}
SimpleCalculator.java
public class SimpleCalculator {
static int undefined = 1 / 0;
}
SimpleCalculator
después de la división por cero? ¿Alguien tiene una referencia a la documentación oficial de este comportamiento?
new SimpleCalculator()
se llama, obtiene un ExceptionInInitializerError con una causa de ArithmeticException. La segunda vez que llama new SimpleCalculator()
, obtiene un NoClassDefFoundError tan puro como cualquier otro. El punto es que puede obtener un NoClassDefFoundError por una razón que no sea SimpleCalculator.class que no está en el classpath en tiempo de ejecución.
NoClassDefFoundError en Java
Definición:
Java Virtual Machine no puede encontrar una clase particular en tiempo de ejecución que estaba disponible en tiempo de compilación.
Si una clase estuvo presente durante el tiempo de compilación pero no está disponible en java classpath durante el tiempo de ejecución.
Ejemplos:
Un ejemplo simple de NoClassDefFoundError es que la clase pertenece a un archivo JAR faltante o JAR no se agregó a classpath o, a veces, alguien ha cambiado el nombre de jar, como en mi caso uno de mis colegas ha cambiado tibco.jar a tibco_v3.jar y el programa es fallando con java.lang.NoClassDefFoundError y me preguntaba qué está mal.
Solo intente ejecutar explícitamente la opción -classpath con la classpath que cree que funcionará y si está funcionando, entonces es una señal corta y segura de que alguien está anulando java classpath.
Soluciones posibles:
Recursos:
He descubierto que a veces obtengo un error NoClassDefFound cuando el código se compila con una versión incompatible de la clase encontrada en tiempo de ejecución. La instancia específica que recuerdo es con la biblioteca del eje apache. En realidad, había 2 versiones en mi classpath en tiempo de ejecución y estaba recogiendo la versión desactualizada e incompatible y no la correcta, causando un error NoClassDefFound. Esto estaba en una aplicación de línea de comando donde estaba usando un comando similar a este.
set classpath=%classpath%;axis.jar
Pude conseguir que recogiera la versión adecuada usando:
set classpath=axis.jar;%classpath%;
Esta es la mejor solución que encontré hasta ahora.
Supongamos que tenemos un paquete llamado que org.mypackage
contiene las clases:
y los archivos que definen este paquete se almacenan físicamente en el directorio D:\myprogram
(en Windows) o /home/user/myprogram
(en Linux).
La estructura del archivo se verá así:
Cuando invocamos Java, se especifica el nombre de la aplicación se ejecute: org.mypackage.HelloWorld
. Sin embargo, también debemos decirle a Java dónde buscar los archivos y directorios que definen nuestro paquete. Entonces, para iniciar el programa, tenemos que usar el siguiente comando:
Estaba usando Spring Framework con Maven y resolví este error en mi proyecto.
Hubo un error de tiempo de ejecución en la clase. Estaba leyendo una propiedad como número entero, pero cuando leyó el valor del archivo de propiedades, su valor era el doble.
Spring no me dio un seguimiento completo de la pila en qué línea falló el tiempo de ejecución. Simplemente dijo NoClassDefFoundError
. Pero cuando lo ejecuté como una aplicación Java nativa (sacándola de MVC), dio ExceptionInInitializerError
cuál era la verdadera causa y cuál era la forma en que rastreé el error.
La respuesta de @ xli me dio una idea de lo que puede estar mal en mi código.
NoClassDefFoundError
realidad fue causado por ExceptionInInitalizerError
, que fue causado por DateTimeParseException
). Es un poco engañoso, ¿no? Sé que probablemente tenían sus razones para hacerlo así, pero sería bueno tener al menos una pequeña pista, que NoClassDefFoundError
fue el resultado de otra excepción, sin la necesidad de deducirlo. Solo lanzar de ExceptionInInitializerError
nuevo sería mucho más claro. A veces la conexión entre los dos puede no ser tan obvia.
Obtengo NoClassFoundError cuando las clases cargadas por el cargador de clases en tiempo de ejecución no pueden acceder a las clases ya cargadas por el cargador de raíz de Java. Debido a que los diferentes cargadores de clases están en diferentes dominios de seguridad (de acuerdo con Java), jvm no permitirá que las clases ya cargadas por el cargador de raíz se resuelvan en el espacio de direcciones del cargador de tiempo de ejecución.
Ejecute su programa con 'java -javaagent: tracer.jar [YOUR java ARGS]'
Produce una salida que muestra la clase cargada y el entorno del cargador que cargó la clase. Es muy útil rastrear por qué una clase no se puede resolver.
// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5
import java.lang.instrument.*;
import java.security.*;
// manifest.mf
// Premain-Class: ClassLoadTracer
// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class
// java -javaagent:tracer.jar [...]
public class ClassLoadTracer
{
public static void premain(String agentArgs, Instrumentation inst)
{
final java.io.PrintStream out = System.out;
inst.addTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);
// dump stack trace of the thread loading class
Thread.dumpStack();
// we just want the original .class bytes to be loaded!
// we are not instrumenting it...
return null;
}
});
}
}
Un caso interesante en el que puede ver mucho NoClassDefFoundErrors
es cuando:
throw
un RuntimeException
en el static
bloque de tu claseExample
Example
static class Example {
static {
thisThrowsRuntimeException();
}
}
static class OuterClazz {
OuterClazz() {
try {
new Example();
} catch (Throwable ignored) { //simulating catching RuntimeException from static block
// DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
}
new Example(); //this throws NoClassDefFoundError
}
}
NoClassDefError
será arrojado acompañado ExceptionInInitializerError
del bloque estático RuntimeException
.
Este es un caso especialmente importante cuando ve NoClassDefFoundErrors
en las PRUEBAS DE LA UNIDAD .
En cierto modo, está "compartiendo" la static
ejecución del bloque entre pruebas, pero la inicial ExceptionInInitializerError
será solo en un caso de prueba. El primero que usa la Example
clase problemática . Otros casos de prueba que usan la Example
clase simplemente arrojarán NoClassDefFoundErrors
.
La siguiente técnica me ayudó muchas veces:
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
donde TheNoDefFoundClass es la clase que podría "perderse" debido a una preferencia por una versión anterior de la misma biblioteca utilizada por su programa. Esto ocurre con mayor frecuencia con los casos, cuando el software del cliente se implementa en un contenedor dominante, armado con sus propios cargadores de clases y toneladas de versiones antiguas de las bibliotecas más populares.
En caso de que haya generado código (EMF, etc.), puede haber demasiados inicializadores estáticos que consuman todo el espacio de la pila.
Consulte la pregunta sobre desbordamiento de pila ¿ Cómo aumentar el tamaño de pila de Java? .
NoClassDefFoundError
También puede ocurrir cuando un inicializador estático intenta cargar un paquete de recursos que no está disponible en tiempo de ejecución, por ejemplo, un archivo de propiedades que la clase afectada intenta cargar desde el META-INF
directorio, pero no está allí. Si no captura NoClassDefFoundError
, a veces no podrá ver el seguimiento completo de la pila; para superar esto, puede usar temporalmente una catch
cláusula para Throwable
:
try {
// Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}
for example a properties file that the affected class tries to load from the META-INF directory
. Esto realmente me sucedió y pude resolverlo NoClassDefFoundError
agregando el archivo de propiedades que faltaba. Agregué esta respuesta exactamente porque uno no esperaría este error en las circunstancias mencionadas.
static
inicialización ... que desencadenó una excepción no verificada y provocó el inicio de clase fallar Cualquier excepción no comprobada que se propague desde la inicialización estática haría eso.
static
inicialización fallida ), me interesaría ver un ejemplo real (es decir, un MCVE) que demuestre el comportamiento.
Recibí este error cuando agrego la dependencia de Maven de otro módulo a mi proyecto, el problema finalmente se resolvió agregando -Xss2m
a la opción JVM de mi programa (es un megabyte por defecto desde JDK5.0). Se cree que el programa no tiene suficiente pila para cargar la clase.
Si alguien viene aquí por java.lang.NoClassDefFoundError: org/apache/log4j/Logger
error, en mi caso se produjo porque usé log4j 2 (pero no agregué todos los archivos que vienen con él), y alguna biblioteca de dependencia usó log4j 1. La solución fue agregar Log4j Puente 1.x: el jar log4j-1.2-api-<version>.jar
que viene con log4j 2. Más información en la migración log4j 2 .
En mi caso, el problema era la incapacidad de Eclipse para diferenciar entre dos copias diferentes del mismo proyecto. Tengo uno bloqueado en el tronco (control de versión SVN) y el otro trabajando en una rama a la vez. Probé un cambio en la copia de trabajo como un caso de prueba JUnit, que incluía extraer una clase interna privada para ser una clase pública por sí sola y, mientras funcionaba, abro la otra copia del proyecto para mirar a otro parte del código que necesitaba cambios. En algún momento, elNoClassDefFoundError
aparecieron quejándose de que la clase interna privada no estaba allí; hacer doble clic en el seguimiento de la pila me llevó al archivo de origen en la copia del proyecto incorrecta.
Al cerrar la copia troncal del proyecto y ejecutar el caso de prueba nuevamente se eliminó el problema.
Este error puede ser causado por requisitos de versión Java no verificados .
En mi caso, pude resolver este error, al construir un proyecto de código abierto de alto perfil, al cambiar de Java 9 a Java 8 usando SDKMAN. .
sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu
Luego, realice una instalación limpia como se describe a continuación.
Cuando se utiliza Maven como su herramienta de compilación, a veces es útil, y generalmente gratificante, hacer una compilación de 'instalación' limpia con las pruebas deshabilitadas .
mvn clean install -DskipTests
Ahora que todo se ha construido e instalado, puede continuar y ejecutar las pruebas.
mvn test
Obtuve errores NoClassDefFound cuando no exporté una clase en la pestaña "Ordenar y Exportar" en la Ruta de compilación de Java de mi proyecto. Asegúrese de poner una marca de verificación en la pestaña "Ordenar y Exportar" de cualquier dependencia que agregue a la ruta de compilación del proyecto. Consulte la advertencia de Eclipse: XXXXXXXXXXX.jar no se exportará ni se publicará. Tiempo de ejecución ClassNotFoundExceptions puede resultar .
En mi caso, recibí este error debido a una falta de coincidencia en las versiones de JDK. Cuando traté de ejecutar la aplicación desde Intelij no funcionaba, pero funcionó desde la línea de comandos. Esto se debe a que Intelij estaba intentando ejecutarlo con el Java 11 JDK que estaba configurado, pero en la línea de comandos se estaba ejecutando con el Java 8 JDK. Después de cambiar esa configuración en Archivo> Estructura del proyecto> Configuración del proyecto> Project SDK, funcionó para mí.
Todos hablan aquí sobre algunas cosas de configuración de Java, problemas de JVM, etc., en mi caso, el error no estaba relacionado con estos temas y tenía una razón muy trivial y fácil de resolver: tenía una anotación incorrecta en mi punto final en mi Controlador ( Aplicación Spring Boot).
He tenido un problema interesante con NoClassDefFoundError en JavaEE al trabajar con el servidor Liberty. Estaba usando adaptadores de recursos IMS y mi server.xml ya tenía un adaptador de recursos para imsudbJXA.rar. Cuando agregué un nuevo adaptador para imsudbXA.rar, comencé a recibir este error para objetos de instancia para DLIException, IMSConnectionSpec o SQLInteractionSpec. No pude entender por qué, pero lo resolví creando un nuevo server.xml para mi trabajo usando solo imsudbXA.rar. Estoy seguro de que usar múltiples adaptadores de recursos en server.xml está bien, simplemente no tuve tiempo de investigarlo.
Java no pudo encontrar la clase A en tiempo de ejecución. La clase A estaba en el proyecto Maven ArtClient desde un espacio de trabajo diferente. Entonces importé ArtClient a mi proyecto Eclipse. Dos de mis proyectos usaban ArtClient como dependencia. Cambié la referencia de la biblioteca a la referencia del proyecto para estos (Build Path -> Configure Build Path).
Y el problema desapareció.
Tuve el mismo problema y estuve en stock durante muchas horas.
Encontré la solución. En mi caso, estaba el método estático definido debido a eso. La JVM no puede crear el otro objeto de esa clase.
Por ejemplo,
private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");
Recibí este mensaje después de eliminar dos archivos de la biblioteca SRC, y cuando los recuperé seguí viendo este mensaje de error.
Mi solución fue: reiniciar Eclipse. Desde entonces no he vuelto a ver este mensaje :-)
Asegúrese de que esto coincida en module:app
y module:lib
:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
{s
y dos }
). ¿Puedes arreglarlo?