¿Por qué obtengo un NoClassDefFoundError en Java?


530

Recibo un mensaje NoClassDefFoundErrorcuando ejecuto mi aplicación Java. ¿Cuál es típicamente la causa de esto?


1
Creo que también puede suceder si no ejecuta su programa Java con la sintaxis correcta. Por ejemplo, debe llamar a su clase desde la carpeta bin raíz con el nombre completo del paquete (es decir, my.package.myClass). Sería más específico si pudiera pero no soy muy java. Solo recuerdo haberlo estropeado varias veces.
Frank Hadder

17
@BoltClock Necesitamos una pregunta canónica para señalar los numerosos duplicados. ¿Por qué no puede ser esto?
Raedwald

21
¿Ha considerado cambiar la respuesta aceptada para que la comunidad encuentre más valiosa en la parte superior?
Martin Smith

Respuestas:


264

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.


1
Tuve este error al colocar un archivo fuente debajo del espacio de nombres / paquete incorrecto. Me di cuenta que sólo podía poner en cualquier lugar, y el compilador era feliz. Resulta que también debería haber sido más diligente para que el tiempo de ejecución fuera feliz.
CenterOrbit

1
Tuve este error una vez cuando mi servidor se quedó sin memoria durante la carga de un archivo. Cada vez que intentaba cargar, recibía un error diferente. Finalmente, me dijo que no tenía suficiente espacio de almacenamiento dinámico.
James M. Lay

81
¡Esta respuesta no es necesariamente cierta y será engañosa para muchas personas! Vea la mejor respuesta de Jared a continuación.
Dave L.

44
@DaveL. ¡Gracias! ¡La respuesta de Jared con más de 400 votos a favor está muy por debajo! Una respuesta con -4 votos hacia arriba (abajo) está muy por encima. Hay algo sospechoso en la lógica de ordenamiento de respuestas de SO.
Saurabh Patil

1
Esta es una posibilidad remota para alguien, pero encontré este error porque la clase en cuestión contenía un SimpleDateFormat que se inicializó con un carácter no válido (tenía T en el medio en lugar de 'T').
Ryan D

819

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:

  1. 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.

  2. 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.


30
Gracias por mencionar la causa de un NoClassDefFoundError, ¡esto me ayudó mucho! En mi caso, se lanzó un ExceptionInInitializerError antes, así es como descubrí los errores en los bloques estáticos.
Thomas

@Jared, cuando lo reciba, Error: Could not find or load main classse clasificará en qué categoría de error.
Vikram

@Pops: hizo el lenguaje más detallado para especificar los objetos de los verbos "try" :)
Jared

1
@Vikram "no se pudo encontrar o cargar la clase principal" no es una excepción de Java, es causada por el iniciador (que inspecciona el JAR y el atributo principal del manifiesto).
Eckes

2
ClassNotFoundException también se produce cuando una clase tiene una inicialización estática que arroja un error o una excepción. Probablemente deberían haber elegido un nombre diferente para ese evento.
Coladict

125

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;
}

3
¿Y la razón es que después del primer intento, jvm ya sabe que no va a funcionar y arroja una excepción diferente la segunda vez?
ikamen

@ikamen Al parecer, ¿ha almacenado en algún lugar la inicialización de clase fallida de SimpleCalculatordespués de la división por cero? ¿Alguien tiene una referencia a la documentación oficial de este comportamiento?
ᴠɪɴᴄᴇɴᴛ

44
@PhilipRego No estoy seguro de qué quiere decir con un NoClassDefFoundError 'puro'. La primera vez que 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.
Harperska

36

NoClassDefFoundError en Java

Definición:

  1. Java Virtual Machine no puede encontrar una clase particular en tiempo de ejecución que estaba disponible en tiempo de compilación.

  2. Si una clase estuvo presente durante el tiempo de compilación pero no está disponible en java classpath durante el tiempo de ejecución.

ingrese la descripción de la imagen aquí

Ejemplos:

  1. La clase no está en Classpath, no hay una forma segura de saberlo, pero muchas veces puedes echar un vistazo para imprimir System.getproperty ("java.classpath") e imprimirá el classpath desde allí, al menos puedes obtener una idea de tu classpath de tiempo de ejecución real.
  2. 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.

  3. 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.

  4. El problema de permisos en el archivo JAR también puede causar NoClassDefFoundError en Java.
  5. El error tipográfico en la configuración XML también puede causar NoClassDefFoundError en Java.
  6. cuando su clase compilada que se define en un paquete, no se presenta en el mismo paquete mientras se carga como en el caso de JApplet, arrojará NoClassDefFoundError en Java.

Soluciones posibles:

  1. La clase no está disponible en Java Classpath.
  2. Si está trabajando en un entorno J2EE, la visibilidad de Class entre múltiples Classloader también puede causar java.lang.NoClassDefFoundError, consulte la sección de ejemplos y escenarios para una discusión detallada.
  3. Verifique java.lang.ExceptionInInitializerError en su archivo de registro. NoClassDefFoundError debido a la falla de la inicialización estática es bastante común.
  4. Debido a que NoClassDefFoundError es una subclase de java.lang.LinkageError, también puede venir si una de sus dependencias, como la biblioteca nativa, puede no estar disponible.
  5. Cualquier script de inicio anula la variable de entorno Classpath.
  6. Es posible que esté ejecutando su programa utilizando el comando jar y la clase no se definió en el atributo ClassPath del archivo de manifiesto.

Recursos:

3 formas de resolver NoClassDefFoundError

java.lang.NoClassDefFoundError Patrones del problema


1
Gran respuesta. Creo que he intentado todo lo que sugieres y todavía tengo ese problema. Puedo excluir algunos de estos debido a que el jar funciona con spring, pero parece que java.sql no me gusta (en mi caso, el controlador sap db para Hana).
JE Carter II

En realidad se llama System.getproperty ("java.class.path")
RIJIK

33

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%;

44
Tuve el mismo problema. Resulta que compilé el archivo war con Java7, pero mi instalación de Tomcat estaba usando Java6. Tuve que actualizar mis variables ambientales
duvo

44
Si esto sucede así, diré que Java está en un desastre. +2 si esto es cierto. No puedo verificar esto todavía. Si se encuentra verdadero, hará + 1 nuevamente (en comentarios)
supernova

7

Esta es la mejor solución que encontré hasta ahora.

Supongamos que tenemos un paquete llamado que org.mypackagecontiene las clases:

  • HelloWorld (clase principal)
  • Clase de apoyo
  • UtilClass

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í: ingrese la descripción de la imagen aquí

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: ingrese la descripción de la imagen aquí


6

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 ExceptionInInitializerErrorcuá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.


1
Lo mismo me sucedió al programar un Servlet (en NoClassDefFoundErrorrealidad 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 NoClassDefFoundErrorfue el resultado de otra excepción, sin la necesidad de deducirlo. Solo lanzar de ExceptionInInitializerErrornuevo sería mucho más claro. A veces la conexión entre los dos puede no ser tan obvia.
Bartłomiej Zieliński

5

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;
            }
        });
    }
}

1
Link está muerto. Pruebe la versión archivada: web.archive.org/web/20131216000019/https://blogs.oracle.com/…
avgvstvs

5

Un caso interesante en el que puede ver mucho NoClassDefFoundErrorses cuando:

  1. throwun RuntimeExceptionen el staticbloque de tu claseExample
  2. Interceptarlo (o si simplemente no importa como si fuera lanzado en un caso de prueba )
  3. Intenta crear una instancia de esta clase 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
    }
}

NoClassDefErrorserá arrojado acompañado ExceptionInInitializerErrordel bloque estático RuntimeException.


Este es un caso especialmente importante cuando ve NoClassDefFoundErrorsen las PRUEBAS DE LA UNIDAD .

En cierto modo, está "compartiendo" la staticejecución del bloque entre pruebas, pero la inicial ExceptionInInitializerErrorserá solo en un caso de prueba. El primero que usa la Exampleclase problemática . Otros casos de prueba que usan la Exampleclase simplemente arrojarán NoClassDefFoundErrors.


44
Este es un consejo muy útil en la vida real. Acabo de tener la misma situación con los inicializadores de atributos de clase. Solo tiene una oportunidad de ver el problema real en el registro. Una vez que se carga la clase (o se intenta de todos modos), debe reiniciar todo.
DailyFrankPeter

4

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.



1

Solucioné mi problema deshabilitando las bibliotecas preDexLibrary para todos los módulos:

dexOptions {
        preDexLibraries false
        ...

1

NoClassDefFoundErrorTambié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-INFdirectorio, 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 catchclá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);
}

Esto es incorrecto. Un recurso faltante no le dará este error. Solo lo obtendrá si falta una clase .
Stephen C

@StephenC Tal vez debería enfatizar esa parte más, pero escribí for example a properties file that the affected class tries to load from the META-INF directory. Esto realmente me sucedió y pude resolverlo NoClassDefFoundErroragregando el archivo de propiedades que faltaba. Agregué esta respuesta exactamente porque uno no esperaría este error en las circunstancias mencionadas.
ᴠɪɴᴄᴇɴᴛ

1
Entonces se ha perdido algo muy importante en su explicación, porque la única forma en que un archivo de recursos faltante podría desencadenar esa excepción es si está intentando cargar el archivo de recursos en una staticinicializació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.
Stephen C

Si estoy equivocado (es decir, esto no se debe a una staticinicialización fallida ), me interesaría ver un ejemplo real (es decir, un MCVE) que demuestre el comportamiento.
Stephen C

1
@StephenC Tienes toda la razón, sin embargo :( Busqué el caso en el que me encontré con este problema y de hecho involucró un inicializador estático que intenta cargar un paquete de recursos. Aumentaré / corregiré mi descripción de la causa. Gracias por señalar esto a cabo.
ᴠɪɴᴄᴇɴᴛ

1

Recibí este error cuando agrego la dependencia de Maven de otro módulo a mi proyecto, el problema finalmente se resolvió agregando -Xss2ma 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.


0

Si alguien viene aquí por java.lang.NoClassDefFoundError: org/apache/log4j/Loggererror, 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>.jarque viene con log4j 2. Más información en la migración log4j 2 .


0

Dos copias de pago diferentes del mismo proyecto

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.


0

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


0

También podría deberse a que copia el archivo de código de un IDE con un nombre de paquete determinado y desea intentar ejecutarlo usando la terminal. Primero deberá eliminar el nombre del paquete del código. Esto me pasa a mi.


0

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í.


0

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).


0

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.


-1

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ó.


-1

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");

-6

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 :-)


44
Eso se explica por la respuesta más votada, cuando compiló por primera vez, los archivos estaban allí, luego eliminó algunos archivos, se eliminaron las clases, por lo que en el tiempo de ejecución, obtuvo ClassNotFound, luego los recuperó, pero Eclipse aún no lo hizo. observe que las clases generadas aún faltaban, pero después de reiniciar Eclipse, el espacio de trabajo se actualizó y las clases volvieron a estar disponibles, pero en general esto no es una solución o solución, la solución es encontrar qué clase / jar falta en el tiempo de ejecución classpath
Jose Manuel Gomez Alvarez

-7

Asegúrese de que esto coincida en module:appy module:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }

3
¿De qué manera su solución es relevante para este problema común?
Taavi Ilves

La configuración de muestra no está equilibrada (tres {sy dos }). ¿Puedes arreglarlo?
Peter Mortensen
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.