java.lang.NoClassDefFoundError: no se pudo inicializar la clase XXX

165
public class PropHolder {
  public static Properties prop;

  static {
    //code for loading properties from file
  }
}

// Referencing the class somewhere else:
Properties prop = PropHolder.prop;

class PropHolderEs una clase propia. La clase reside en el mismo archivo JAR de la clase principal. Entonces eso no debería porque falta un JAR en classpath.

Cuando busco en el archivo JAR jar tf myjarfile, puedo ver la PropHolder.classlista allí.

Por cierto: el código se está ejecutando bien en mi máquina local. Pero no podría funcionar cuando lo implemento con algún script en un servidor Linux. Así que creo que no es el problema del código. Pero por alguna razón. El proceso de implementación es muy difícil de rastrear.

¿Cual podría ser el problema?

León
fuente
¿La estructura de directorios adecuada en su jar coincide con el paquete de clase?
John B
Necesito ver alguna fuente, muchas cosas pueden causar esto. por ejemplo, una declaración de "paquete" pero el archivo no reside realmente en la ruta correspondiente
jcomeau_ictx
3
Una causa es una excepción durante la inicialización: ¿hay alguna otra salida de error?
Michael Brewer-Davis

Respuestas:

210

Mi mejor apuesta es que hay un problema aquí:

static {
    //code for loading properties from file
}

Al parecer, se produjo una excepción no detectada y se propagó hasta el ClassLoader real que intenta cargar la clase. Sin embargo, necesitaríamos un stacktrace para confirmar esto.

O eso o ocurrió al crear una PropHolder.propvariable estática.

John Vint
fuente
He estado enfrentando el mismo problema una y otra vez. Estoy seguro de que es por el staticproblema. ¿Qué se debe hacer para resolver el problema?
Viper
1
Deberá identificar qué excepción se está lanzando desde el staticbloque. Para depurarlo, coloque un try/catch(Exception e)alrededor de todo el bloque y registre la excepción. Tendrás que arreglar esa excepción. Por lo general, la excepción se registrará, pero puede ser difícil de encontrar, ya que se registra durante la carga de clases, lo que puede suceder muy temprano
John Vint,
Sí, mantuve el código en try catchbloque y decía Failed to initialize ClassA. Creo que es el problema de JVM. Reinicié mi sistema y luego todo funcionó bien. ¿Cómo resuelvo este problema en el futuro sin reiniciar mi sistema y resolver el problema con una solución simple?
Viper
No se pudo inicializar ClassA es un efecto secundario de otra cosa. Querrá ver causesi está disponible. A NoClassDefFoundErrorsiempre está asociado a otro error, deberá buscarlo en los registros o intentar registrarlo de manera más adecuada (como forzar el inicio de sesión en un nuevo archivo en el sistema de archivos)
John Vint
Sería más fácil de rastrear si Java arrojara un error couldNotInitializeStaticPartOfClassError o algo así. Entonces nosotros, como desarrolladores, sabríamos dónde buscar.
Maarten
126

Usted está obteniendo un java.lang.NoClassDefFoundErrorque NO significa que falta su clase (en ese caso obtendría un java.lang.ClassNotFoundException). El ClassLoader se encontró con 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 pueda encontrar el archivo, sin permisos, etc.).

jeha
fuente
1
Una aclaración es que aunque NoClassDefFoundError no implica una ClassNotFoundException, sigue siendo una posible causa de NoClassDefFoundError.
John Vint
1
buf si tuvieras una ClassNotFoundException, entonces el ClassLoader podría / nunca podría intentar cargar la clase, ¿verdad?
jeha
44
Una clase puede estar cargando otra clase que no se encontró. La causa en esa instancia todavía es una ClassNotFoundException
John Vint
1
Debería haber aclarado, solo quise decir una excepción. GetCause ()
John Vint
1
Este fue realmente útil aquí, ya que pasé unos 20 minutos verificando que se incluye el JAR (al que pertenece la clase informada). Una vez que me di cuenta de que estaba mirando en la dirección equivocada, entendí fácilmente que probablemente faltaba una clase de anotación y listo, la informada se declaró como @Stateless, así que simplemente agregué la dependencia correspondiente y pude continuar. ¡Gracias por el consejo!
RAM237
33

NoClassDefFoundError no da mucha idea 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;
  }
}
Mark Hansen
fuente
¿Cómo hacer esto en Kotlin?
Marlon
Gracias por dar la pista. En mi caso, estaba obteniendo NPE en la inicialización de línea estática.
Abhishek
3

Tuve la misma excepción, así es como resolví el problema:

Condiciones previas

  1. Clase Junit (y prueba), que extendió otra clase.

  2. ApplicationContext inicializado usando spring, que inicia el proyecto.

  3. 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 requería algunas clases que se inicializaron desde el contexto de la aplicación.

Espero que esto ayude.

KerenSi
fuente
2

Como se mencionó anteriormente, esto podría ser una serie de cosas. En mi caso, tenía una variable inicializada estáticamente que se basaba en una entrada que faltaba en mi archivo de propiedades. Se agregó la entrada que falta al archivo de propiedades y se resolvió el problema.

TriMix
fuente
1

Hace solo unos días, me encontré con la misma pregunta como la tuya. Todo el código funciona bien en mi máquina local, pero resulta un error (noclassdeffound & initialize). Así que publico mi solución, pero no sé por qué, simplemente adelanto una posibilidad. Espero que alguien lo explique. @ John Vint En primer lugar, le mostraré mi problema. Mi código tiene variable estática y bloque estático ambos. Cuando conocí este problema por primera vez, probé la solución de John Vint e intenté detectar la excepción. Sin embargo, no atrapé nada. Entonces pensé que es 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 subprocesos se ejecutan en un proceso (por cierto, la máquina Linux tiene núcleos dobles y procesos dobles). Eso significa que si hay dos tareas (ambas usan el código que tiene un bloque estático o variables) que se ejecutan en el mismo proceso, sale mal, pero si se ejecutan en procesos diferentes, ambas están bien. En la máquina Linux, yo uso

mvn -U clean  test -Dtest=path 

para ejecutar una tarea, y debido a que mi variable estática es iniciar un contenedor (o tal vez usted inicializa un nuevo cargador de clases), por lo que permanecerá hasta que se detenga el jvm, y el jvm se detiene solo cuando todas las tareas en un proceso se detienen. Cada tarea iniciará un nuevo contenedor (o cargador de clases) y confundirá a jvm. Como resultado, ocurre el error. 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

Tal vez ya haya resuelto este problema, pero todavía espera que ayude a otros que se encuentran con el mismo problema.

Rey Mono
fuente
Además, cuando el código se ejecuta en la máquina Linux, siga el error anterior, hay otro problema: java.lang.ExceptionInInitializerError: nullsignifica que no puede encontrar la clase en el cargador de clases o no sabe cargar cuál (supongo). ¿Lo conociste?
MonkeyKing
1

Tuve la misma excepción, pero solo mientras se ejecutaba en modo de depuración, así es como resolví el problema (después de 3 días completos): en build.gradle tenía: "multiDexEnabled true" establecido en la sección defaultConfig.

        defaultConfig {
    applicationId "com.xxx.yyy"
    minSdkVersion 15
    targetSdkVersion 28
    versionCode 5123
    versionName "5123"
    // Enabling multidex support.
    multiDexEnabled true
}

pero aparentemente esto no fue suficiente. pero cuando cambié:

public class MyAppClass  extends Application 

a:

public class MyAppClass  extends MultiDexApplication 

Esto lo resolvió. Espero que esto ayude a alguien

Elad
fuente
0

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, por lo que quizás otros marcos podrían ayudarlo a evitar el problema por completo, no estoy seguro.

Mi problema era llamar 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 construcción de prueba unitaria no pudo encontrarla. En su lugar, cambié este valor nully todo volvió a la normalidad.

Lifeson106
fuente
0

Tuve los mismos problemas: java.lang.NoClassDefFoundError: No se pudo inicializar la clase com.xxx.HttpUtils

static {
    //code for loading properties from file
}

es el problema del entorno. ¡Eso significa que las propiedades en application.yml son incorrectas o están vacías!

usuario8503957
fuente
0

Me encuentro con el mismo problema. Inicié un objeto bean en bloque estático como a continuación:

static {
    try{
        mqttConfiguration = SpringBootBeanUtils.<MqttConfiguration>getBean(MqttConfiguration.class);
    }catch (Throwable e){
        System.out.println(e);
    }
 }

Solo porque el proceso de mi petición de frijol causó un NPE, tengo problemas. Así que creo que deberías revisar tu bloque de código estático cuidadosamente.

lai nan
fuente