thread - java.lang.NoClassDefFoundError: no se pudo inicializar la clase XXX
noclassdeffounderror java (7)
public class PropHolder {
public static Properties prop;
static {
//code for loading properties from file
}
}
// Referencing the class somewhere else:
Properties prop = PropHolder.prop;
class PropHolder
es una clase propia. La clase reside en el mismo archivo JAR de la clase principal. Así que no debería porque falta ningún JAR en classpath.
Cuando miro en el archivo JAR mediante jar tf myjarfile
, puedo ver el PropHolder.class
enumerado allí.
Por cierto: el código está funcionando bien en mi máquina local. Pero no podría funcionar cuando lo implemente con algún script en un servidor Linux. Entonces creo que no es el problema del código. Pero por alguna razón. el proceso de implementación es muy difícil de seguir.
¿Cual podría ser el problema?
Como se mencionó anteriormente, esto podría ser una serie de cosas. En mi caso, tenía una variable inicializada estáticamente que dependía de una entrada faltante en mi archivo de propiedades. Se agregó la entrada faltante al archivo de propiedades y se solucionó el problema.
Hace solo unos días, me encontré con la misma pregunta que la tuya. Todo el código funciona bien en mi máquina local, pero resulta en error (noclassdeffound & initialize). Entonces publico mi solución, pero no sé por qué, simplemente avanzo una posibilidad. Espero que alguien lo explique. @ John Vint En primer lugar, te mostraré mi problema. Mi código tiene variable estática y bloqueo estático ambos. Cuando conocí por primera vez este problema, probé la solución de John Vint y traté de detectar la excepción. Sin embargo, no atrapé nada. Así que pensé que era porque la variable estática (pero ahora sé que son lo mismo) y todavía no encontré nada. Entonces, trato de encontrar la diferencia entre la máquina Linux y mi computadora. Luego descubrí que este problema ocurre solo cuando varios hilos se ejecutan en un proceso (por cierto, la máquina Linux tiene doble núcleo y doble proceso). Eso significa que si hay dos tareas (ambas usan el código que tiene un bloque estático o variables) se ejecutan en el mismo proceso, salen mal, pero si se ejecutan en procesos diferentes, ambas están bien. En la máquina Linux, uso
mvn -U clean test -Dtest=path
ejecutar una tarea, y porque mi variable estática es para iniciar un contenedor (o quizás inicializar un nuevo cargador de clases), por lo que permanecerá hasta que se detenga el jvm, y el jvm se detiene solo cuando se detienen todas las tareas en un proceso. Cada tarea iniciará un nuevo contenedor (o cargador de clases) y confundirá a jvm. Como resultado, el error ocurre. Entonces, ¿cómo resolverlo? Mi solución es agregar un nuevo comando al comando maven y hacer que cada tarea vaya al mismo contenedor.
-Dxxx.version=xxxxx #sorry can''t post more
Quizás ya hayas resuelto este problema, pero aún así espero que ayude a otros que enfrentan el mismo problema.
Mi mejor apuesta es que hay un problema aquí:
static {
//code for loading properties from file
}
Parecería que se produjo una excepción no detectada y se propagó al ClassLoader real que intenta cargar la clase. Sin embargo, necesitaríamos una stacktrace para confirmar esto.
O eso o ocurrió al crear la variable estática PropHolder.prop
.
NoClassDefFoundError no da mucha pista de lo que salió mal dentro del bloque estático. Es una buena práctica tener siempre un bloque como este dentro del código de inicialización estático {...}:
static {
try {
... your init code here
} catch (Throwable t) {
LOG.error("Failure during static initialization", t);
throw t;
}
}
Obtendrá java.lang.NoClassDefFoundError
lo que NO significa que su clase falta (en ese caso, obtendría java.lang.ClassNotFoundException
). El ClassLoader encontró un error al leer la definición de la clase al intentar leer la clase.
Ponga un try / catch dentro de su inicializador estático y observe la excepción. Si lee algunos archivos allí y difiere de su entorno local, es muy probable que sea la causa del problema (tal vez no se encuentre el archivo, no haya permisos, etc.).
Si está trabajando en un proyecto de Android, asegúrese de no llamar a ningún método estático en ninguna clase de Android. Solo estoy usando JUnit + Mockito, así que tal vez algunos otros frameworks puedan ayudarte a evitar el problema por completo, no estoy seguro.
Mi problema era llamar a Uri.parse(uriString)
como parte de un inicializador estático para una prueba unitaria. La clase Uri es una API de Android, por lo que la compilación de prueba de unidad no pudo encontrarla. Cambié este valor a null
y todo volvió a la normalidad.
Tuve la misma excepción, así es como resolví el problema:
Condiciones previas:
Clase Junit (y prueba), que extendió otra clase.
ApplicationContext inicializado usando spring, que inicia el proyecto.
El contexto de la aplicación se inicializó en el método @Before
Solución:
Inicie el contexto de la aplicación desde el método @BeforeClass, ya que la clase principal también requiere algunas clases que se inicializaron desde el contexto de la aplicación.
Espero que esto ayude