ClassNotFoundException vs NoClassDefFoundError
J'ai parcouru ce fil Quelles sont les causes et quelles sont les différences entre NoClassDefFoundError et ClassNotFoundException? C'est ce que l'un des ans,qui a max ups, dans le fil est : NoClassDefFoundError :"Ainsi, il semble que la NoClassDefFoundError se produit lorsque la source a été compilée avec succès, mais lors de l'exécution, les fichiers de classe requis n'ont pas été trouvés . Cela peut être quelque chose qui peut se produire dans la distribution ou la production de fichiers JAR, où tous les fichiers de classe requis n'ont pas été inclus."
ClassNotFoundException : Quant à ClassNotFoundException, il semble que cela puisse provenir d'essayer de faire des appels réfléchissants aux classes lors de l'exécution, mais les classes que le programme essaie d'appeler n'existent pas.
J'ai fait une petite expérience . J'ai créé une classe principale, class A et j'ai essayé d'appeler une autre classe, class B à partir de celle-ci , compilée avec succès.
Ensuite, j'ai supprimé la classe B qui est en train d'être appelé en classe A. J'ai le java.lang.ClassNotFoundException {[5] } mais selon la réponse dans la bande de roulement, j'aurais dû obtenir NoClassDefFoundError (la source a été compilée avec succès mais au moment de l'exécution, les fichiers de classe n'ont pas été trouvés) Quelqu'un pourrait-il expliquer ce qui me manque dans l'interprétation du sna dans le fil ?
package com.random;
public class A {
public static void main(String[] args) {
B b= new B();
}
}
package com.random;
public class B {
}
10 answers
NoClassDefFoundError
Lancé si la machine virtuelle Java ou une instance de charge dans la définition d'une classe (dans le cadre d'un appel de méthode ou de dans le cadre de la création d'une nouvelle instance à l'aide de la nouvelle expression) et non définition de la classe peut être trouvé.
La définition de classe recherchée existait lors de l'exécution la classe a été compilée, mais la définition ne peut plus être trouver.
ClassNotFoundException
Lancé lorsqu'une application tente de charger dans une classe via sa chaîne nom en utilisant: La méthode forName dans la classe Class. Le findSystemClass méthode dans la classe ClassLoader . La méthode loadClass dans la classe Chargeur de classe.
Vous devez comprendre que le JVM
ne peut pas réaliser la définition du class
que vous avez supprimé ne peut pas être trouvé, car le class
lui-même ne peut pas être trouvé automatiquement jetez le ClassNotFoundException
.
Cette exception se produit à runtime
donc peu importe s'il a compilé en premier ou non, vous avez supprimé le fichier, donc il ne peut pas être trouvé et lancer le exception
.
Notez que NoClassDefFoundError
n'est pas réellement une exception, c'est un Error
dérivé de LinkageError
tandis que ClassNotFoundException
dérive directement de java.lang.Exception
.
Pour reprendre, le NoClassDefFoundError
globalement signifie simplement que le JVM
a essayé d'accéder à runtime
quelque chose qui, selon le compiled
code devrait exister, mais ne le fait pas existe réellement (ou n'est pas dans le classpath).
Exemple pour reproduire 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 pour reproduire 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 exécutable n .jar
qui exécute la méthode main
. Vous pouvez le spécifier dans le fichier Manifest.txt
dans le .jar
Main-Class: NoClassDefFoundErrorExample
Exécutez maintenant ce qui suit commandes
javac Test.java
javac NoClassDefFoundErrorExample.java
jar cfm NoClassDefFoundErrorExample.jar Manifest.txt NoClassDefFoundErrorExample.class
java -jar NoClassDefFoundErrorExample.jar
Notez le 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 runtime essaie de trouver la classe nommée par certains String
par exemple Class.forName(java.lang.String)
la méthode prend un argument de chaîne et essaie de trouver la classe avec ce nom. Dans ce cas, le nom de classe est une piqûre et ne peut être vérifié au moment de l'exécution. ici, l'exception dit clairement... cette "classe" n'est pas trouvé. Si... il peut arriver pour deux raisons :
Raison 1. Class-name n'est pas une classe java valide (exemple - "java.Bang.le cerf-volant").
// Example
Class cdef = Class.forName( "java.bang.kiting" );
Raison 2. Le nom de classe est était un valide de classe... mais de toute façon il n'a pas été emballé avec le pot ou n'est pas résolu dans le chemin de classe. Pour autant que l'exécution sait... il peut être un mauvais nom de la classe... de manière similaire au cas 1.
// Example
Class cdef =Class.forName( "apache.some.SomeLegitClass" );
Où comme 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 emballée avec le jar ( ou plus généralement - n'est pas résolue dans le chemin de classe ). Dans ce cas, nous obtenons NoClassDefFoundError
.
Ici runtime sait que le la classe est valide car elle a été compilée 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 essaie directement de charger une classe , en passant l'argumentString
représentant un nom complet de la classe.- par exemple
Class.forName(String)
, ouClassLoader.loadClass(String)
.
- par exemple
-
NoClassDefFoundError
est lancé lorsque la JVM est invitée à charger une classe indirectement .- par exemple, lorsque la classe A utilise la classe B et que la classe B n'est pas sur classpath,
NoClassDefFoundError
sera jetée.
- par exemple, lorsque la classe A utilise la classe B et que la classe B n'est pas sur classpath,
NoClassDefFoundError
est généralement appelé lorsque vous utilisez une bibliothèque(par exemple, Goyave, Gson, CommonsIO). Vous mettez la bibliothèque dans classpath de votre projet, mais vous ne l'avez pas exportée ensemble, vous obtiendrez un 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 fichier .jar
.
Maintenant, créez un autre projet. Ajoutez le fichier jar exporté à 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, assurez-vous de ne pas inclure le fichier jar(avec la classe A
). Exécutez le fichier jar nouvellement exporté, vous verrez cette erreur!
1) Je ne sais pas si c'est le cas.]}
2) NoClassDefFoundError Cela se produit lorsque la classe était présente pendant le Dans ce cas, nous il suffit de vérifier le
Class.forName()
ou ClassLoader.loadClass()
ou ClassLoader.findSystemClass()
méthodes, et il pourrait pas trouver la classe requise dans le chemin de classe. class path
et ajouter la classe dans le chemin de la classe si elle est manquante.
compile time
et n'est pas disponible pendant run time
pour certaines raisons. Cela signifie que la classe qui est chargée est present
dans classpath
, mais l'un des classe(s)
dépendants requis par cette classe est suppriméou a échoué à charger par le compilateur.classes which are dependent on this class
.
Comme mentionné dans les réponses précédentes, NoClassDefFoundError se produira lorsque la classe était présente pendant la compilation et n'est pas disponible pendant l'exécution pour certaines raisons.
Il y a un autre scénario que je souhaite ajouter, qui pourrait également entraîner NoClassDefFoundError.
Lorsque vous essayez de charger une classe qui n'a pas réussi à se charger en raison d'une exception, par exemple un échec dans le bloc d'initialisation statique, le système vous lancera ExceptionInInitializerError. Si vous essayez de charger le même classe à nouveau (qui n'a pas réussi à charger précédemment), le système lancera NoClassDefFoundError
Permet de l'explorer avec un échantillon
ClassWithStaticBlock.java
public class ClassWithStaticBlock {
static {
int total = 1/0;
}
}
Principal.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 Principal.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 à nouveau d'utiliser ClassWithStaticBlock (qui n'a pas réussi à s'initialiser plus tôt), le système lance NoClassDefFoundError.
Trouvé l'exemple de Pourquoi est-ce que je reçois une NoClassDefFoundError en Java?
L'un des cas où NoClassDefFoundError se produit est lorsque la classe JVM essaie d'accéder n'est pas trouvée dans classpath. Mais si class est présent dans classpath, Cela entraînera ClassNotFoundException.
En bref, NoClassDefFoundError viendra si une classe était présente pendant la compilation mais non disponible dans java classpath pendant l'exécution.
Essayez simplement de s'exécuter avec l'option explicit-classpath où le classpath ne contient pas de classe B.
ClassNotFoundException et NoClassDefFoundError se produisent lorsqu'une classe particulière n'est pas trouvée lors de l'exécution.Cependant, ils se produisent à différents scénarios.
ClassNotFoundException est une exception qui se produit lorsque vous essayez de charger une classe au moment de l'exécution en utilisant Class.Les méthodes forName() ou loadClass() et les classes mentionnées ne se trouvent pas dans le chemin de classe.
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 était manquante à l'exécution temps.
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 .les fichiers de classe seront générés. L'un est A.class et un autre est B.class. Si vous supprimez le A.class fichier et exécuter le B.class fichier, 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)
Tout sur ClassNotFoundException Vs NoClassDefFoundError l'article explique très clairement la différence entre ClassNotFoundException et NoClassDefFoundError avec exemple et selon lui.
Je ne sais pas si c'est le cas.]}
Est une exception vérifiée qui se produit lorsque nous disons à la JVM de charger une classe par son nom de chaîne en utilisant Class.forName () ou ClassLoader.findSystemClass () ou ClassLoader.Méthodes loadClass () et classe mentionnée ne se trouve pas dans le chemin de classe.
La plupart du temps, cette exception se produit lorsque vous essayez d'exécuter une application sans mettre à jour le chemin de classe avec les fichiers JAR requis. Par exemple, Vous avez peut-être vu cette exception lorsque vous effectuez le code JDBC pour vous connecter à votre base de données, c'est-à-dire MySQL, mais votre classpath n'a pas le jar pour cela.
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");
}
}
NoClassDefFoundError
Est un sous-type de java.lang.Error et Error class indiquent un comportement anormal qui ne devrait vraiment pas se produire avec une application mais et les développeurs d'applications ne devraient pas essayer de l'attraper, il est là pour une utilisation JVM uniquement.
NoClassDefFoundError se produit lorsque JVM essaie de charger une classe particulière qui fait partie de votre exécution de code (dans le cadre d'un appel de méthode normal ou dans le cadre 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 de classe mais était présente une classe qui n'est pas présent compilateur va déclencher 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");
}
}
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");
}
}
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");
}
}
Les autres réponses dans ce fil sont correctes, je veux juste ajouter quelque chose que j'ai passé des heures à essayer de comprendre. Même si
Class.forName("apache.some.SomeLegitClass")
Fonctionne,
Class.forName("apache.some.somelegitclass")
Entraînera une NoClassDefFoundError. classe.forName () est sensible à la casse. Il en résultera différentes exceptions si le nom de classe est mal orthographié ou a simplement un boîtier incorrect.