J'ai traversé ce fil Quelles sont les causes et quelles sont les différences entre NoClassDefFoundError et ClassNotFoundException? Voici ce que l’un des ans, qui a max ups, dans le fil est: NoClassDefFoundError: "Il semble donc que NoClassDefFoundError se produise lorsque la source a été compilée avec succès, mais au moment de l'exécution, les fichiers de classe requis étaient introuvables. Cela peut se produire lors de la distribution ou de la production de fichiers JAR, où tous les fichiers de classe requis n'étaient pas inclus. "
ClassNotFoundException: comme pour ClassNotFoundException, il semble que cela puisse provenir de la tentative d'appels réflexifs aux classes au moment de l'exécution, mais que les classes que le programme tente d'appeler n'existent pas.
J'ai fait une petite expérience. J'ai créé une classe principale, class A et essayé d'appeler une autre classe, la classe B, compilée avec succès.
Ensuite, j'ai supprimé la classe B qui est appelée dans la classe A . J'ai eu la Java.lang.ClassNotFoundException mais comme le dit la réponse dans la foulée, j'aurais dû avoir NoClassDefFoundError (la source a été compilée avec succès les fichiers de classe d'exécution n'ont pas été trouvés) Quelqu'un pourrait-il expliquer ce qui me manque dans l'interprétation des années dans le fil de discussion?
package com.random;
public class A {
public static void main(String[] args) {
B b= new B();
}
}
package com.random;
public class B {
}
NoClassDefFoundError
Émis si la machine virtuelle Java ou une instance de ClassLoader essaie de charger dans la définition d'une classe (dans le cadre d'un appel de méthode normal ou dans le cadre de la création d'une nouvelle instance à l'aide de la nouvelle expression) et no définition de la classe pourrait être trouvé.
La définition de classe recherchée existait lors de l'exécution de La classe a été compilée, mais la définition est introuvable.
ClassNotFoundException
Lancé lorsqu'une application tente de charger une classe via sa chaîne name using: La méthode forName dans la classe Class. La classe findSystem method dans la classe ClassLoader. La méthode loadClass dans la classe ClassLoader.
Vous devez comprendre que la JVM
ne peut pas réaliser la définition de la class
que vous avez supprimée est introuvable, car la class
elle-même ne peut pas être trouvée et jette automatiquement la ClassNotFoundException
.
Cette exception se produisant à runtime
, peu importe si elle a été compilée en premier ou non, vous avez supprimé le fichier. Par conséquent, il est introuvable et lancez la variable exception
.
Notez que NoClassDefFoundError
n'est pas réellement une exception, c'est une Error
dérivée de LinkageError
tandis que ClassNotFoundException
dérive directement de Java.lang.Exception
.
Pour résumer, NoClassDefFoundError
signifie globalement simplement que JVM
a essayé d'accéder à runtime
quelque chose qui, selon le code compiled
, devrait exister, mais n'existe pas réellement (ou n'est pas dans le chemin de classe).
Exemple de reproduction de ClassNotFoundException
public class ClassNotFoundExceptionExample {
private static final String CLASS_TO_LOAD = "main.Java.Utils";
public static void main(String[] args) {
try {
Class loadedClass = Class.forName(CLASS_TO_LOAD);
System.out.println("Class " + loadedClass + " found successfully!");
}
catch (ClassNotFoundException ex) {
System.err.println("A ClassNotFoundException was caught: " + ex.getMessage());
ex.printStackTrace();
}
}
}
Exemple de reproduction de NoClassDefFoundError
Créer une classe simple Test
public class Test {
public Test() {
System.out.println("A new instance of the Test class was created!");
}
}
Et une classe NoClassDefFoundErrorExample
public class NoClassDefFoundErrorExample {
private static Test test = new Test();
public static void main(String[] args) {
System.out.println("The definition of Test was found!");
}
}
Créez maintenant un n exécutable .jar
qui exécute la méthode main
. Vous pouvez le spécifier dans le fichier Manifest.txt
à l'intérieur du .jar
Main-Class: NoClassDefFoundErrorExample
Maintenant, lancez les commandes suivantes
javac Test.Java
javac NoClassDefFoundErrorExample.Java
jar cfm NoClassDefFoundErrorExample.jar Manifest.txt NoClassDefFoundErrorExample.class
Java -jar NoClassDefFoundErrorExample.jar
Remarquez la NoClassDefFoundError
Exception in thread "main" Java.lang.NoClassDefFoundError: TestClass
at NoClassDefFoundErrorExample.(NoClassDefFoundErrorExample.Java:2)
Caused by: Java.lang.ClassNotFoundException: TestClass
at Java.net.URLClassLoader$1.run(URLClassLoader.Java:372)
at Java.net.URLClassLoader$1.run(URLClassLoader.Java:361)
at Java.security.AccessController.doPrivileged(Native Method)
at Java.net.URLClassLoader.findClass(URLClassLoader.Java:360)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:308)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
... 1 more
Eh bien ... ClassNotFoundException
se produit lorsque le moteur d’exécution tente de trouver la classe nommée par une méthode String
; par exemple, la méthode Class.forName(Java.lang.String)
prend un argument de chaîne et essaie de trouver la classe portant ce nom. Dans ce cas, le nom de la classe est une piqûre et ne peut être vérifié qu'au moment de l'exécution. ici l'exception dit clairement ... cette "classe" est introuvable. Donc ... cela peut arriver pour deux raisons:
Raison 1. Le nom de la classe n'est pas une classe Java valide (exemple - "Java.bang.kiting").
// Example
Class cdef = Class.forName( "Java.bang.kiting" );
Raison 2. Le nom de la classe était une classe valide ... mais il n'a pas été emballé avec le fichier jar ou n'a pas été résolu dans le chemin de la classe. Donc, autant que le runtime le sache ... il peut s'agir d'un nom de classe erroné ... semblable au cas 1.
// Example
Class cdef =Class.forName( "Apache.some.SomeLegitClass" );
Où NoClassDefFoundError
pour les cas où la référence de classe réelle a été utilisée,
// example
import Apache.some.SomeLegitClass
SomeLegitClass i = (SomeLegitClass) instanceOfSomeLegitClass;
Donc fondamentalement, tout était correct mais d'une manière ou d'une autre, la classe n'est pas packagée avec le fichier jar (ou plus généralement - n'est pas résolue dans le chemin de classe). Dans ce cas, nous obtenons NoClassDefFoundError
.
Ici, le moteur d'exécution sait que la classe est valide car il a été compilé avec succès ... mais il ne peut pas trouver la "définition de classe".
La différence dépend de qui a demandé à la classe d'être chargée :
ClassNotFoundException
est lancé lorsque le code tente directement de charger une classe , en passant l'argument String
représentant un nom complet de la classe .Class.forName(String)
ou ClassLoader.loadClass(String)
.NoClassDefFoundError
est renvoyé lorsqu'il est demandé à la JVM de charger une classe indirectement .NoClassDefFoundError
sera lancé.NoClassDefFoundError
est généralement appelé lorsque vous utilisez une bibliothèque (par exemple, Guava, Gson, CommonsIO). Vous avez placé la bibliothèque dans le chemin de classe de votre projet, mais vous ne l'avez pas exportée ensemble. Vous obtiendrez une NoClassDefFoundError
lorsque l'application est en cours d'exécution.
Comment obtenir NoClassDefFoundError
:
Créez un nouveau projet avec cette classe.
public class A
{
public void do()
{
System.out.println("Do!");
}
}
Exportez-le en tant que .jar
file.
Maintenant, créez un autre projet. Ajoutez le fichier JAR exporté au classpath.
import ???.A;
public class Main
{
public static void main(String[] args)
{
A a = new A();
a.do();//NoClassDefFoundError thrown at here.
}
}
Exportez le projet en veillant à ne pas inclure le fichier jar (avec la classe A
). Exécutez le fichier JAR nouvellement exporté, vous verrez cette erreur!
Comme mentionné dans les réponses précédentes, NoClassDefFoundError se produira lorsque la classe était présente au moment de la compilation et n'est pas disponible au moment de l'exécution pour certaines raisons.
Je souhaite ajouter un autre scénario, qui pourrait également entraîner NoClassDefFoundError.
Lorsque vous essayez de charger une classe dont le chargement a échoué en raison d'une exception, par exemple un échec dans un bloc d'initialisation statique, le système vous lève ExceptionInInitializerError. Si vous essayez de charger à nouveau la même classe (qui avait échoué auparavant), le système lancera NoClassDefFoundError
Permet de l'explorer avec un échantillon
ClassWithStaticBlock.Java
public class ClassWithStaticBlock {
static {
int total = 1/0;
}
}
Main.Java
public class Main {
public static void main(String[] args) {
ClassWithStaticBlock cs;
try {
cs = new ClassWithStaticBlock();
}catch(Throwable e){
e.printStackTrace();
}
}
}
Résultat:
Java.lang.ExceptionInInitializerError
at Main.main(Main.Java:6)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
at Java.lang.reflect.Method.invoke(Method.Java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.Java:140)
Caused by: Java.lang.ArithmeticException: / by zero
at ClassWithStaticBlock.<clinit>(ClassWithStaticBlock.Java:7)
... 6 more
Permet de modifier Main.Java
public class Main {
public static void main(String[] args) {
ClassWithStaticBlock cs;
try {
cs = new ClassWithStaticBlock();
}catch(Throwable e){
e.printStackTrace();
}
cs = new ClassWithStaticBlock(); //try to use ClassWithStaticBlock again
}
}
Résultat:
Java.lang.ExceptionInInitializerError
at Main.main(Main.Java:6)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
at Java.lang.reflect.Method.invoke(Method.Java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.Java:140)
Caused by: Java.lang.ArithmeticException: / by zero
at ClassWithStaticBlock.<clinit>(ClassWithStaticBlock.Java:7)
... 6 more
Exception in thread "Main Thread" Java.lang.NoClassDefFoundError: ClassWithStaticBlock
at Main.main(Main.Java:10)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
at Java.lang.reflect.Method.invoke(Method.Java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.Java:140)
Lorsque nous essayons d'utiliser ClassWithStaticBlock à nouveau (ce qui a échoué à initialiser plus tôt), le système lance NoClassDefFoundError.
J'ai trouvé l'échantillon depuis Pourquoi ai-je un message d'erreur NoClassDefFoundError en Java?
1) _ {ClassNotFoundException} _
Class.forName()
ou ClassLoader.loadClass()
ou ClassLoader.findSystemClass()
et qu'il soit non trouver la classe requise dans le chemin d'accès aux classes. class path
et ajouter la classe dans le chemin de la classe s'il en manque.2)NoClassDefFoundError
Cela se produit lorsque la classe était présente pendant le compile time
et n'est pas disponible pendant le run time
pour certaines raisons. Cela signifie que la classe en cours de chargement est present
dans classpath
, mais que l'un des classe(s)
dépendants requis par cette classe soit supprimé ou échoué à charger par le compilateur.
Dans ce cas, il suffit de vérifier le classes which are dependent on this class
.
Tout à propos de ClassNotFoundException contre NoClassDefFoundError article explique très clairement la différence entre ClassNotFoundException et NoClassDefFoundError avec des exemples et en fonction des exemples.
Exception vérifiée qui se produit lorsque nous indiquons à JVM de charger une classe par son nom de chaîne à l'aide de méthodes Class.forName () ou ClassLoader.findSystemClass () ou ClassLoader.loadClass () et que la classe mentionnée est introuvable dans le chemin d'accès aux classes.
La plupart du temps, cette exception se produit lorsque vous essayez d'exécuter une application sans mettre à jour le chemin d'accès aux classes avec les fichiers JAR requis. Par exemple, vous avez peut-être vu cette exception lorsque vous avez utilisé le code JDBC pour vous connecter à votre base de données i.e.MySQL, mais votre chemin d'accès aux classes ne contient pas le fichier jar correspondant.
public class Test {
public static void main(String[] args) throws Exception {
// Provide any class name to Class.forName() which does not exist
// Or compile Test.Java and then manually delete Person.class file so Person class will become unavailable
// Run the program using Java Test
Class clazz = Class.forName("Person");
Person person = (Person) clazz.newInstance();
person.saySomething();
}
}
class Person {
void saySomething() {
System.out.println("Hello");
}
}
Est un sous-type de Java.lang.Error et la classe Error indique un comportement anormal qui ne devrait vraiment pas se produire avec une application, mais les développeurs d’applications ne devraient pas essayer de l’attraper, c’est là uniquement pour une utilisation JVM.
NoClassDefFoundError se produit lorsque la machine virtuelle Java tente de charger une classe particulière faisant partie de l'exécution de votre code (dans le cadre d'un appel de méthode normal ou de la création d'une instance à l'aide du nouveau mot clé) et que cette classe n'est pas présente dans votre chemin d'accès aux classes, mais qu'elle était présente. au moment de la compilation, car pour exécuter votre programme, vous devez le compiler. Si vous essayez d’utiliser une classe qui n’est pas présente, le compilateur générera une erreur de compilation.
public class Test {
public static void main(String[] args) throws Exception {
// Do javac on Test.Java,
// Program will compile successfully because Empoyee class exits
// Manually delete Employee.class file
// Run the program using Java Test
Employee emp = new Employee();
emp.saySomething();
}
}
class Employee {
void saySomething() {
System.out.println("Hello");
}
}
ClassNotFoundException et NoClassDefFoundError se produisent lorsqu'une classe particulière est introuvable à l'exécution. Cependant, elles se produisent dans différents scénarios.
ClassNotFoundException est une exception qui se produit lorsque vous essayez de charger une classe au moment de l'exécution à l'aide des méthodes Class.forName () ou loadClass () et que les classes mentionnées ne sont pas trouvées dans le chemin d'accès aux classes.
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 est une erreur qui se produit lorsqu'une classe particulière est présente au moment de la compilation mais manquait au moment de l'exécution.
class A
{
// some code
}
public class B
{
public static void main(String[] args)
{
A a = new A();
}
}
Lorsque vous compilez le programme ci-dessus, deux fichiers .class seront générés. L'un est A.class et l'autre est B.class. Si vous supprimez le fichier A.class et exécutez le fichier B.class, Java Runtime System lancera NoClassDefFoundError comme ci-dessous:
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)
L'un des cas où NoClassDefFoundError se produit est lorsque la JVM de classe tente d'accéder n'est pas trouvé dans classpath . Mais si class est présent dans classpath, cela se traduira par ClassNotFoundException.
En bref, NoClassDefFoundError viendra si une classe était présente au moment de la compilation mais n'était pas disponible dans le chemin de classes Java lors de l'exécution.
Essayez simplement de vous lancer avec l'option -classpath explicite, où classpath ne contient pas la classe B.