¿Qué causa y cuáles son las diferencias entre NoClassDefFoundError y ClassNotFoundException?

¿Cuál es la diferencia entre NoClassDefFoundError y ClassNotFoundException ?

¿Qué causa que sean arrojados? ¿Cómo pueden resolverse?

A menudo encuentro estos throwables cuando modifico el código existente para incluir nuevos archivos jar. Los he visto tanto en el lado del cliente como en el servidor para una aplicación java distribuida a través de webstart.

Posibles razones por las que me he encontrado:

  1. paquetes no incluidos en build.xml para el lado del cliente del código
  2. tiempo de ejecución classpath faltante para los nuevos jar que estamos utilizando
  3. la versión entra en conflicto con el jar anterior

Cuando los encuentro hoy, tomo un enfoque de seguimiento y error para que las cosas funcionen. Necesito más claridad y comprensión.

La diferencia con las especificaciones de API de Java es la siguiente.

Para ClassNotFoundException :

Lanzado cuando una aplicación intenta cargar en una clase a través de su nombre de cadena usando:

  • El método forName en clase Class .
  • El método findSystemClass en la clase ClassLoader .
  • El método loadClass en la clase ClassLoader .

pero no se pudo encontrar ninguna definición para la clase con el nombre especificado.

Para NoClassDefFoundError :

Lanzado si la máquina virtual de Java o una instancia de ClassLoader intenta cargar en la definición de una clase (como parte de una llamada de método normal o como parte de la creación de una nueva instancia utilizando la nueva expresión) y no se pudo encontrar ninguna definición de la clase.

La definición de clase buscada existía cuando se comstackba la clase en ejecución, pero ya no se puede encontrar la definición.

Por lo tanto, parece que NoClassDefFoundError produce cuando la fuente se compiló correctamente, pero en el tiempo de ejecución, no se encontraron los archivos de class requeridos. Esto puede ser algo que puede ocurrir en la distribución o producción de archivos JAR, donde no se incluyeron todos los archivos de class requeridos.

En cuanto a ClassNotFoundException , parece que puede provenir de tratar de hacer llamadas reflexivas a las clases en tiempo de ejecución, pero las clases que el progtwig está tratando de llamar no existe.

La diferencia entre los dos es que uno es un Error y el otro es una Exception . Con NoClassDefFoundError es un Error y surge de la máquina virtual de Java que tiene problemas para encontrar una clase que esperaba encontrar. Un progtwig que se espera que funcione en tiempo de comstackción no se puede ejecutar debido a que no se encuentran los archivos de class , o no es el mismo que se produjo o se encontró en tiempo de comstackción. Este es un error bastante crítico, ya que el progtwig no puede ser iniciado por la JVM.

Por otro lado, ClassNotFoundException es una Exception , por lo que se espera algo, y es algo recuperable. El uso de la reflexión puede ser propenso a errores (ya que existen ciertas expectativas de que las cosas no salgan como se esperaba.) No hay verificación en tiempo de comstackción para ver que existan todas las clases requeridas, por lo que cualquier problema para encontrar las clases deseadas aparecerá en tiempo de ejecución .

Se genera una excepción ClassNotFoundException cuando ClassLoader no encuentra la clase informada. Esto normalmente significa que la clase falta en CLASSPATH. También podría significar que la clase en cuestión está intentando cargarse desde otra clase que se cargó en un cargador de clases principal y, por lo tanto, la clase del cargador de clases hijo no está visible. Este es a veces el caso cuando se trabaja en entornos más complejos, como un servidor de aplicaciones (WebSphere es infame para tales problemas de cargador de clases).

Las personas a menudo tienden a confundir java.lang.NoClassDefFoundError con java.lang.ClassNotFoundException sin embargo, hay una distinción importante. Por ejemplo, una excepción (un error realmente ya que java.lang.NoClassDefFoundError es una subclase de java.lang.Error) como

 java.lang.NoClassDefFoundError: org/apache/activemq/ActiveMQConnectionFactory 

no significa que la clase ActiveMQConnectionFactory no se encuentre en CLASSPATH. De hecho, es todo lo contrario. Significa que la clase ActiveMQConnectionFactory fue encontrada por el ClassLoader, sin embargo, al intentar cargar la clase, se encontró con un error al leer la definición de la clase. Esto normalmente ocurre cuando la clase en cuestión tiene bloques estáticos o miembros que usan una clase que no se encuentra en ClassLoader. Entonces, para encontrar el culpable, vea el origen de la clase en cuestión (ActiveMQConnectionFactory en este caso) y busque el código usando bloques estáticos o miembros estáticos. Si no tiene acceso a la fuente, simplemente descompilela usando JAD.

Al examinar el código, digamos que encuentra una línea de código como la que se muestra a continuación, asegúrese de que la clase SomeClass esté en su CLASSPATH.

 private static SomeClass foo = new SomeClass(); 

Consejo: Para saber a qué jar pertenece una clase, puede usar el sitio web jarFinder. Esto le permite especificar un nombre de clase usando comodines y busca la clase en su base de datos de jar. jarhoo te permite hacer lo mismo, pero ya no es gratuito.

Si desea ubicar a qué jar pertenece una clase en una ruta local, puede usar una utilidad como jarscan ( http://www.inetfeedback.com/jarscan/ ). Simplemente especifique la clase que desea ubicar y la ruta del directorio raíz donde desea que comience a buscar la clase en archivos jar y zip.

NoClassDefFoundError es básicamente un error de enlace. Ocurre cuando intentas crear una instancia de un objeto (estáticamente con “nuevo”) y no se encuentra cuando estaba durante la comstackción.

ClassNotFoundException es más general y es una excepción de tiempo de ejecución cuando intenta utilizar una clase que no existe. Por ejemplo, tiene un parámetro en una función que acepta una interfaz y alguien pasa en una clase que implementa esa interfaz pero no tiene acceso a la clase. También cubre casos de carga dinámica de clases, como el uso de loadClass () o Class.forName ().

Un NoClassDefFoundError (NCDFE) ocurre cuando su código ejecuta “nueva Y ()” y no puede encontrar la clase Y.

Simplemente puede ser que Y no está cargado en su cargador de clases como sugieren los otros comentarios, pero podría ser que la clase Y no está firmada o tiene una firma no válida, o que Y está cargado por un cargador de clases diferente no visible para su código , o incluso que Y depende de Z, que no se pudo cargar por alguno de los motivos anteriores.

Si esto sucede, entonces la JVM recordará el resultado de cargar X (NCDFE) y simplemente lanzará un nuevo NCDFE cada vez que solicite Y sin decirle por qué:

 clase A {
   clase estática b {}
   public static void main (String args []) {
     System.out.println ("Primer bash nuevo b ():");
     try {new b ();  } catch (Throwable t) {t.printStackTrace ();}
     System.out.println ("\ nSegundo bash nuevo b ():");
     try {new b ();  } catch (Throwable t) {t.printStackTrace ();}
   }
 }

guarda esto como a.java en alguna parte

El código simplemente intenta crear una instancia de una nueva clase “b” dos veces, aparte de eso, no tiene ningún error, y no hace nada.

Comstack el código con javac a.java , luego ejecuta a invocando java -cp . a java -cp . a – solo debería imprimir dos líneas de texto, y debería funcionar bien sin errores.

A continuación, elimine el archivo “a $ b.class” (o llénelo con basura, o copie a.class sobre él) para simular la clase faltante o dañado. Esto es lo que sucede:

 Primer bash nuevo b ():
 java.lang.NoClassDefFoundError: a $ b
     en a.main (a.java:5)
 Causado por: java.lang.ClassNotFoundException: a $ b
     en java.net.URLClassLoader $ 1.run (URLClassLoader.java:200)
     en java.security.AccessController.doPrivileged (método nativo)
     en java.net.URLClassLoader.findClass (URLClassLoader.java:188)
     en java.lang.ClassLoader.loadClass (ClassLoader.java:307)
     en sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:301)
     en java.lang.ClassLoader.loadClass (ClassLoader.java:252)
     en java.lang.ClassLoader.loadClassInternal (ClassLoader.java:320)
     ... 1 más

 Segundo bash nuevo b ():
 java.lang.NoClassDefFoundError: a $ b
     en a.main (a.java:7)

La primera invocación da como resultado una ClassNotFoundException (lanzada por el cargador de clases cuando no puede encontrar la clase), que debe estar envuelta en un NoClassDefFoundError sin marcar, ya que el código en cuestión ( new b() ) debería funcionar.

El segundo bash, por supuesto, también fallará, pero como puede ver, la excepción envuelta ya no existe, porque el Cargador de clases parece recordar los cargadores de clases fallidos. Solo ves al NCDFE sin ninguna pista de lo que realmente sucedió.

Entonces, si alguna vez ve un NCDFE sin causa raíz, necesita ver si puede rastrear la primera vez que se cargó la clase para encontrar la causa del error.

De http://www.javaroots.com/2013/02/classnotfoundexception-vs.html :

ClassNotFoundException : ocurre cuando el cargador de clases no pudo encontrar la clase requerida en la ruta de clase. Entonces, básicamente, debes verificar la ruta de tu clase y agregar la clase en el classpath.

NoClassDefFoundError : esto es más difícil de depurar y encontrar el motivo. Esto se produce cuando en tiempo de comstackción las clases requeridas están presentes, pero en el tiempo de ejecución las clases se cambian o se eliminan o la clase se inicializa estática lanzó excepciones. Significa que la clase que se está cargando está presente en classpath, pero una de las clases que requiere esta clase se elimina o no se carga por comstackdor. Entonces debería ver las clases que dependen de esta clase.

Ejemplo :

 public class Test1 { } public class Test { public static void main(String[] args) { Test1 = new Test1(); } } 

Ahora, después de comstackr ambas clases, si elimina el archivo Test1.class y ejecuta la clase Test, arrojará

 Exception in thread "main" java.lang.NoClassDefFoundError: Test at Test1.main(Test1.java:5) Caused by: java.lang.ClassNotFoundException: Test at java.net.URLClassLoader$1.run(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) ... 1 more 

ClassNotFoundException : lanzado cuando una aplicación intenta cargar en una clase a través de su nombre, pero no se pudo encontrar ninguna definición para la clase con el nombre especificado.

NoClassDefFoundError : lanzado si la Máquina Virtual Java intenta cargar en la definición de una clase y no se pudo encontrar ninguna definición de la clase.

¿Cuál es el motivo para obtener cada uno de ellos y cualquier proceso de pensamiento sobre cómo lidiar con dichos errores?

Están estrechamente relacionados. Se ClassNotFoundException una ClassNotFoundException cuando Java buscaba una clase en particular por nombre y no podía cargarla con éxito. Se NoClassDefFoundError cuando Java buscaba una clase que estaba vinculada a algún código existente, pero que no podía encontrarla por una razón u otra (p. Ej., Classpath incorrecto, versión incorrecta de Java, versión incorrecta de una biblioteca) y es completamente fatal ya que indica que algo salió mal.

Si tienes un fondo C, un CNFE es como una falla al dlopen() / dlsym() y un NCDFE es un problema con el enlazador; en el segundo caso, los archivos de clase en cuestión nunca deberían haberse comstackdo realmente en la configuración que intentas usar.

Ejemplo 1:

 class A{ void met(){ Class.forName("com.example.Class1"); } } 

Si com/example/Class1 no existe en ninguno de los classpaths, arroja ClassNotFoundException .

Ejemplo # 2:

 Class B{ void met(){ com.example.Class2 c = new com.example.Class2(); } } 

Si com/example/Class2 existió al comstackr B, pero no se encontró durante la ejecución, arroja NoClassDefFoundError .

Ambas son excepciones de tiempo de ejecución.

ClassNotFoundException se lanza cuando se intenta cargar la clase haciendo referencia a ella a través de una cadena. Por ejemplo, el parámetro a en Class.forName () es una Cadena, y esto aumenta el potencial de los nombres binarios no válidos que se pasan al cargador de clases.

La ClassNotFoundException se genera cuando se encuentra un nombre binario potencialmente no válido; por ejemplo, si el nombre de la clase tiene el carácter ‘/’, está obligado a obtener una ClassNotFoundException. También se lanza cuando la clase directamente referenciada no está disponible en el classpath.

Por otro lado, NoClassDefFoundError se lanza

  • cuando la representación física real de la clase – el archivo .class no está disponible,
  • o la clase se ha cargado ya en un cargador de clases diferente (por lo general, un cargador de clases padre habría cargado la clase y, por lo tanto, la clase no se puede cargar de nuevo),
  • o si se ha encontrado una definición de clase incompatible: el nombre en el archivo de clase no coincide con el nombre solicitado,
  • o (más importante) si una clase dependiente no puede ser ubicada y cargada. En este caso, la clase directamente referenciada podría haberse localizado y cargado, pero la clase dependiente no está disponible o no se puede cargar. Este es un escenario donde la clase directamente referenciada puede cargarse a través de un Class.forName o métodos equivalentes. Esto indica una falla en el enlace.

En resumen, normalmente se lanza un NoClassDefFoundError en instrucciones new () o invocaciones de métodos que cargan una clase previamente ausente (en oposición a la carga de clases basada en cadenas para ClassNotFoundException), cuando el cargador de clases no puede encontrar o cargar la definición de clase ( s).

Eventualmente, depende de la implementación de ClassLoader lanzar una instancia de ClassNotFoundException cuando no puede cargar una clase. La mayoría de las implementaciones de cargadores de clases personalizadas realizan esto ya que amplían el URLClassLoader. Por lo general, los cargadores de clases no lanzan explícitamente un NoClassDefFoundError en ninguna de las implementaciones de métodos; esta excepción generalmente se genera desde la JVM en el comstackdor de HotSpot, y no desde el cargador de clases.

Diferencia entre ClassNotFoundException Vs NoClassDefFoundError

enter image description here

Con los nombres en sí podemos identificar fácilmente uno desde Exception y otro desde Error .

Excepción: las excepciones ocurren durante la ejecución del progtwig. Un progtwigdor puede manejar estas excepciones mediante try catch block. Tenemos dos tipos de excepciones. Excepción marcada que arroja en tiempo de comstackción. Excepciones de tiempo de ejecución que se lanzan en tiempo de ejecución, estas excepciones generalmente ocurren debido a una mala progtwigción.

Error: estas no son excepciones en absoluto, está más allá del scope del progtwigdor. Estos errores generalmente son lanzados por JVM.


enter image description here fuente de imagen

Diferencia:

ClassNotFoundException:

  • El cargador de clases no puede verificar un código de byte de clase que mencionamos en la fase de Enlace del subsistema de carga de clases obtenemos ClassNotFoundException .
  • ClassNotFoundException es una Excepción comprobada derivada directamente de la clase java.lang.Exception y necesita proporcionar un manejo explícito para ella
  • ClassNotFoundException aparece cuando hay una carga explícita de la clase al proporcionar el nombre de la clase en el tiempo de ejecución utilizando ClassLoader.loadClass (), Class.forName () y ClassLoader.findSystemClass ().

No Error Clase Def Encontrado:

  • El cargador de clases no puede resolver las referencias de una clase en la fase de Enlace del subsistema de carga de clases obtenemos NoClassDefFoundError .
  • NoClassDefFoundError es un error derivado de la clase LinkageError , que se utiliza para indicar casos de error, donde una clase tiene una dependencia en alguna otra clase y esa clase ha cambiado de manera incompatible después de la comstackción.
  • NoClassDefFoundError es el resultado de la carga implícita de clase debido a una llamada a un método de esa clase o cualquier acceso variable.

Semejanzas

  • Tanto NoClassDefFoundError como ClassNotFoundException están relacionados con la falta de disponibilidad de una clase en tiempo de ejecución.
  • Tanto ClassNotFoundException como NoClassDefFoundError están relacionadas con Java classpath.

Teniendo en cuenta las acciones del sistema del cargador de clase:

http://www.artima.com/insidejvm/ed2/images/fig7-1.gif

Este es un artículo que me ayudó mucho a entender la diferencia: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

Si se produce un error durante la carga de clases, se debe lanzar una instancia de una subclase de LinkageError en un punto del progtwig que (directa o indirectamente) usa la clase o la interfaz que se está cargando.

Si la Máquina Virtual Java alguna vez intenta cargar una clase C durante la verificación (§5.4.1) o resolución (§5.4.3) (pero no la inicialización (§5.5)), y el cargador de clases que se utiliza para iniciar la carga de C arroja una instancia de ClassNotFoundException , entonces Java Virtual Machine debe lanzar una instancia de NoClassDefFoundError cuya causa es la instancia de ClassNotFoundException .

Entonces, una excepción ClassNotFoundException es una causa raíz de NoClassDefFoundError .
Y un NoClassDefFoundError es un caso especial de tipo error de carga, que se produce en el paso de vinculación .

Agregue una posible razón en la práctica:

  • ClassNotFoundException: como dijo cletus, usas la interfaz mientras que la clase heredada de la interfaz no está en la ruta de clases. Por ejemplo, patrón de proveedor de servicio (o localizador de servicio ) intenta localizar alguna clase no existente
  • NoClassDefFoundError: la clase dada se encuentra mientras no se encuentra la dependencia de la clase dada

En la práctica, el error puede producirse de forma silenciosa , por ejemplo, si envía una tarea de temporizador y en la tarea del temporizador arroja un error , mientras que en la mayoría de los casos, su progtwig solo detecta Excepción . Luego, el ciclo principal del temporizador finaliza sin ninguna información. Un error similar a NoClassDefFoundError es ExceptionInInitializerError , cuando el inicializador estático o el inicializador de una variable estática arroja una excepción.

Me recuerdo a mí mismo lo siguiente una y otra vez cuando necesito actualizar

ClassNotFoundException

Jerarquía de clase

 ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable 

Mientras se depura

  1. Jar requerido, clase falta en classpath.
  2. Verifique que todos los archivos jar requeridos estén en classpath de jvm.

No Error Clase Def Encontrado

Jerarquía de clase

 NoClassDefFoundError extends LinkageError extends Error extends Throwable 

Mientras se depura

  1. Problema al cargar una clase dinámicamente, que se compiló correctamente
  2. Problema con bloques estáticos, constructores, métodos init () de clase dependiente y el error real está envuelto por varias capas [especialmente cuando se usa spring, hibernate se envuelve la excepción real y obtendrá NoClassDefError]
  3. Cuando te enfrentas a “ClassNotFoundException” en un bloque estático de clase dependiente
  4. Problema con las versiones de clase. Esto ocurre cuando tienes dos versiones v1, v2 de la misma clase en diferentes jar / packages, que se comstackron correctamente usando v1 y v2 cargadas en el tiempo de ejecución que no tiene los métodos / vars relevantes y verás esta excepción. [Una vez resolví este problema eliminando el duplicado de la clase relacionada con log4j en varios archivos jar que aparecían en el classpath]

ClassNotFoundException es una excepción comprobada que ocurre cuando le decimos a JVM que cargue una clase por su nombre de cadena utilizando los métodos Class.forName () o ClassLoader.findSystemClass () o ClassLoader.loadClass () y la clase mencionada no se encuentra en classpath.

La mayoría de las veces, esta excepción se produce cuando intenta ejecutar una aplicación sin actualizar el classpath con los archivos JAR necesarios. Por ejemplo, es posible que haya visto esta excepción al hacer el código JDBC para conectarse a su base de datos ieMySQL pero su classpath no tiene JAR para ello.

El error NoClassDefFoundError se produce cuando JVM intenta cargar una clase particular que es parte de la ejecución del código (como parte de una llamada a método normal o como parte de crear una instancia usando la palabra clave nueva) y esa clase no está presente en su classpath, pero presente en tiempo de comstackción porque para ejecutar su progtwig necesita comstackrlo y si está intentando usar una clase que no está presente, el comstackdor generará un error de comstackción.

A continuación se encuentra la breve descripción

enter image description here

Puedes leer Everything About ClassNotFoundException Vs NoClassDefFoundError para más detalles.

ClassNotFoundException y NoClassDefFoundError se producen cuando una clase particular no se encuentra en tiempo de ejecución. Sin embargo, ocurren en diferentes escenarios.

ClassNotFoundException es una excepción que se produce cuando intenta cargar una clase en tiempo de ejecución utilizando los métodos Class.forName () o loadClass () y las clases mencionadas no se encuentran en classpath.

  public class MainClass { public static void main(String[] args) { try { Class.forName("oracle.jdbc.driver.OracleDriver"); }catch (ClassNotFoundException e) { e.printStackTrace(); } } } java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at pack1.MainClass.main(MainClass.java:17) 

NoClassDefFoundError es un error que ocurre cuando una clase en particular está presente en el momento de la comstackción, pero faltaba en el tiempo de ejecución.

  class A { // some code } public class B { public static void main(String[] args) { A a = new A(); } } 

Cuando compile el progtwig anterior, se generarán dos archivos .class. Uno es A.class y el otro es B.class. Si elimina el archivo A.class y ejecuta el archivo B.class, Java Runtime System lanzará NoClassDefFoundError como se muestra a continuación:

  Exception in thread "main" java.lang.NoClassDefFoundError: A at MainClass.main(MainClass.java:10) Caused by: java.lang.ClassNotFoundException: A at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)