web-dev-qa-db-fra.com

Comment résoudre Java.lang.NoClassDefFoundError?

J'ai essayé à la fois l'exemple du tutoriels Java d'Oracle. Ils compilent tous les deux bien, mais au moment de l'exécution, tous deux génèrent cette erreur:

Exception in thread "main" Java.lang.NoClassDefFoundError: graphics/shapes/Square
    at Main.main(Main.Java:7)
Caused by: Java.lang.ClassNotFoundException: graphics.shapes.Square
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:366)
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:355)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Java.net.URLClassLoader.findClass(URLClassLoader.Java:354)
    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

Je pense que je pourrais avoir le fichier Main.Java dans le mauvais dossier. Voici la hiérarchie des répertoires:

graphics
├ Main.Java
├ shapes
|   ├ Square.Java
|   ├ Triangle.Java
├ linepoint
|   ├ Line.Java
|   ├ Point.Java
├ spaceobjects
|   ├ Cube.Java
|   ├ RectPrism.Java

Et voici Main.Java:

import graphics.shapes.*;
import graphics.linepoint.*
import graphics.spaceobjects.*;

public class Main {
    public static void main(String args[]) {
        Square s = new Square(2,3,15);
        Line l = new Line(1,5,2,3);
        Cube c = new Cube(13,32,22);
    }
}

Qu'est-ce que je fais mal ici?

METTRE À JOUR

Après avoir placé la classe Main dans le package graphics (j'y ai ajouté package graphics;), définissez le chemin d'accès aux classes sur "_test" (dossier contenant les graphiques), compilez-le et exécutez-le à l'aide de Java graphics.Main (à partir de la ligne de commande), cela a fonctionné.

Très tard UPDATE # 2

Je n'utilisais pas Eclipse (uniquement Notepad ++ et le JDK) et la mise à jour ci-dessus a résolu mon problème. Cependant, il semble que bon nombre de ces réponses concernent Eclipse et IntelliJ, mais leurs concepts sont similaires.

178
Jonathan Lam

Après avoir compilé votre code, vous vous retrouvez avec des fichiers .class pour chaque classe de votre programme. Ces fichiers binaires sont le bytecode que Java interprète pour exécuter votre programme. La variable NoClassDefFoundError indique que le chargeur de classes (dans ce cas, Java.net.URLClassLoader), chargé du chargement dynamique des classes, ne peut pas trouver le fichier .class de la classe que vous essayez d'utiliser. 

Votre code ne serait pas compilé si les classes requises n'étaient pas présentes (sauf si les classes sont chargées de réflexion), cette exception signifie généralement que votre chemin d'accès aux classes n'inclut pas les classes requises. Rappelez-vous que le chargeur de classe (en particulier Java.net.URLClassLoader) recherchera les classes du paquet a.b.c dans le dossier a/b/c/dans chaque entrée de votre chemin de classe. NoClassDefFoundError peut également indiquer qu'il vous manque une dépendance transitive d'un fichier .jar contre lequel vous avez compilé et que vous essayez d'utiliser.

Par exemple, si vous aviez une classe com.example.Foo, après la compilation, vous auriez un fichier de classe Foo.class. Disons par exemple que votre répertoire de travail est .../project/. Ce fichier de classe doit être placé dans .../project/com/example et vous devez définir votre chemin de classe sur .../project/.

Note latérale: Je vous recommanderais de tirer parti des outils étonnants qui existent pour les langages Java et JVM. Les IDE modernes comme Eclipse et IDEA et la construction d'outils de gestion comme Maven ou Gradle vous aideront à ne pas avoir à vous soucier des classpaths (autant) et à vous concentrer sur le code! Cela dit, ce lien explique comment définir le chemin d'accès aux classes lorsque vous l'exécutez sur la ligne de commande.

186
Samuel

Je voudrais corriger le point de vue des autres sur NoClassDefFoundError.

NoClassDefFoundError peut se produire pour plusieurs raisons, telles que

  1. ClassNotFoundException - .class non trouvé pour cette classe référencée, qu'elle soit disponible au moment de la compilation ou non (c'est-à-dire la classe de base/enfant).
  2. Fichier de classe localisé, mais exception générée lors de l'initialisation de variables statiques
  3. Fichier de classe localisé, exception levée lors de l'initialisation de blocs statiques 

Dans la question initiale, il s'agissait du premier cas pouvant être corrigé en définissant CLASSPATH dans le fichier jar des classes référencées ou dans son dossier de packages. 

Qu'est-ce que cela signifie en disant "disponible dans le temps de compilation"? 

  • La classe référencée est utilisée dans le code. 
    Ex: Deux classes, A Et B (étend A). Si B est référencé directement dans le code, il est disponible au moment de la compilation, c'est-à-dire A a = new B ();

Qu'est-ce que cela signifie en disant "non disponible au moment de la compilation"?

  • La classe de temps de compilation et la classe d'exécution sont différentes, par exemple, la classe de base est chargée à l'aide du nom de classe de la classe enfant, par exemple Class.forName ("nom de classe")
    Exemple: deux classes, A et B (étend A). Code a
    A a = Class.forName ("B"). NewInstance ();
111
p1nkrock

NoClassDefFoundError signifie que la classe est présente dans le chemin d'accès aux classes à Compile time mais qu'elle n'existe pas dans le chemin d'accès aux classes à Runtime.

Si vous utilisez Eclipse, assurez-vous que vous avez les shapes, linepoints et le spaceobjects comme entrées dans le fichier .classpath.

12
Konstantin Yovkov

si vous rencontrez l'une de ces erreurs lors de la compilation et de l'exécution:

* NoClassDefFoundError

* Error: Could not find or load main class hello

* Exception in thread "main" Java.lang.NoClassDefFoundError:javaTest/test/hello 
(wrong name: test/hello)
        at Java.lang.ClassLoader.defineClass1(Native Method)
        at Java.lang.ClassLoader.defineClass(Unknown Source)
        at Java.security.SecureClassLoader.defineClass(Unknown Source)
        at Java.net.URLClassLoader.defineClass(Unknown Source)
        at Java.net.URLClassLoader.access$100(Unknown Source)
        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)
        at Sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

--------------------------SOLUTIION------------- ----------

le problème est principalement dans l'organisation des paquets. Vous devriez organiser vos classes dans des dossiers concernant les classifications de paquets dans votre code source.

On Compiling process use this command:

javac -d . [FileName.Java]

To Run the class please use this command:

Java [Package].[ClassName]
10
sami
Java.lang.NoClassDefFoundError

indique que quelque chose a été trouvé à compiletime mais pas à runtime . vous devez peut-être simplement l'ajouter au classpath.

8
sschrass

Aucune exception de définition de classe se produit lorsque la classe voulue ne figure pas dans le chemin de la classe . Au moment de la compilation Classe: La classe a été générée à partir du compilateur Java, mais d'une manière ou d'une autreat La classe dépendante est introuvable. .

Passons à travers un exemple simple:

public class ClassA{
public static void main(String args[]){
     //Some gibberish Code...
     String text = ClassB.getString();
     System.out.println("Text is :" + text);
}

}

public class ClassB{
    public static String getString(){
      return "Testing Some Exception";
 }
}

Supposons maintenant que les deux codes source Java ci-dessus soient placés dans un dossier, disons "NoClassDefinationFoundExceptionDemo"

Maintenant, ouvrez un shell (en supposant que Java est déjà configuré correctement)

  1. Allez dans le dossier "NoClassDefinationFoundExceptionDemo"
  2. Compiler les fichiers source Java javac ClassB javac ClassA
  3. Les deux fichiers sont compilés avec succès et les fichiers de classe générés dans le même dossier as ClassA.class et ClassB.class
  4. Maintenant que nous recouvrons ClassPath dans le répertoire de travail en cours .__, nous exécutons la commande suivanteJava -cp. ClassA Et cela a fonctionné avec succès et vous verrez la sortie à l'écran
  5. Maintenant, disons que vous avez supprimé le fichier ClassB.class du répertoire actuel . Et maintenant vous exécutez à nouveau la commande .Java -cp. ClassAMaintenant, il va vous accueillir avec NoClassDefFoundException. en tant que ClassB, qui est une dépendance pour ClassA, n’est pas trouvé dans le chemin de classe (répertoire de travail actuel).
6
bharatj

Si votre projet se trouve dans un package tel que com.blahcode et que votre classe s'appelle Main, les fichiers compilés peuvent apparaître dans une structure de répertoires telle que ./out/com/blahcode/Main.class. Cela est particulièrement vrai pour IntelliJ IDEA.

Lorsque vous essayez de vous lancer depuis un shell ou une cmd, vous devez cd à celui qui contient com comme sous-répertoire.

cd out
Java -classpath . com.blahcode.Main
2
Hypershadsy

Après avoir travaillé sur un projet NetBeans pendant plusieurs mois, j'ai soudainement reçu le message NoClassDefFoundError peu de temps après avoir reçu une alerte "Mémoire faible". Faire une reconstruction complète n'a pas aidé, mais fermer Netbeans et rouvrir le projet n'a généré aucun rapport d'erreur.

1
Ed S

NoClassDefFoundError en Java:

Définition: 

NoClassDefFoundError viendra si une classe était présente lors de la compilation mais non disponible dans le chemin de classe Java lors de l'exécution. Normalement, vous verrez la ligne ci-dessous dans le journal lorsque vous obtenez NoClassDefFoundError: Exception dans le fil "principal" Java.lang.NoClassDefFoundError

Causes possibles:

  1. La classe n'est pas disponible dans Java Classpath.

  2. Vous exécutez peut-être votre programme avec la commande jar et la classe n'a pas été définie dans l'attribut ClassPath du fichier manifeste.

  3. Tout script de démarrage remplace la variable d'environnement Classpath.

  4. Comme NoClassDefFoundError est une sous-classe de Java.lang.LinkageError, elle peut également apparaître si l'une de ses dépendances, telle que la bibliothèque native, n'est pas disponible.

  5. Recherchez Java.lang.ExceptionInInitializerError dans votre fichier journal. NoClassDefFoundError en raison de l'échec de l'initialisation statique est assez commun.

  6. Si vous travaillez dans un environnement J2EE, la visibilité de Class entre plusieurs chargeurs de classe peut également entraîner Java.lang.NoClassDefFoundError. Pour plus de détails, reportez-vous à la section Exemples et scénario.

Résolutions possibles:

  1. Vérifiez que toutes les classes Java requises sont incluses dans le chemin de classe de l’application. L'erreur la plus courante est de ne pas inclure toutes les classes nécessaires avant de commencer à exécuter une application Java dépendant de certaines bibliothèques externes.

  2. Le classpath de l’application est correct, mais la variable d’environnement Classpath est remplacée avant l’exécution de l’application.

  3. Vérifiez que l'exception ExceptionInInitializerError susmentionnée n'apparaît pas dans la trace de pile de votre application.

Ressources: 

3 façons de résoudre Java.lang.NoClassDefFoundError en Java J2EE

Java.lang.NoClassDefFoundError - Comment résoudre aucune erreur de classe trouvée

1
Virtual

J'ai fait face au problème aujourd'hui. J'ai un projet Android et après avoir activé multidex, le projet ne démarre plus.

La raison en était que j'avais oublié d'appeler la méthode multidex spécifique qui devait être ajoutée au Application class et appelée avant tout le reste.

 MultiDex.install(this);

Suivez ce tutoriel pour activer multidex correctement. https://developer.Android.com/studio/build/multidex.html

Vous devriez ajouter ces lignes à votre classe d'application

 @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
1
CROSP

Cette réponse est spécifique à une erreur Java.lang.NoClassDefFoundError se produisant dans un service:

Mon équipe a récemment constaté cette erreur après la mise à niveau d'un RPM fournissant un service. Le rpm et le logiciel qu'il contenait avaient été conçus avec Maven, il nous semblait donc que nous avions une dépendance au temps de compilation qui n’avait tout simplement pas été incluse dans le rpm. 

Toutefois, lors de l’examen, la classe non trouvée se trouvait dans le même module que plusieurs des classes de la trace de pile. De plus, ce module n’a pas été ajouté récemment à la construction. Ces faits indiquent qu’il ne s’agit peut-être pas d’un problème de dépendance Maven.

La solution éventuelle: Redémarrez le service!

Il semble que la mise à niveau rpm ait invalidé le descripteur de fichier du service sur le fichier jar sous-jacent. Le service a alors vu une classe qui n'avait pas été chargée en mémoire, l'a recherchée dans sa liste de descripteurs de fichier jar et n'a pas réussi à la trouver car le descripteur de fichier à partir duquel il pouvait charger la classe avait été invalidé. Le redémarrage du service l'a forcé à recharger tous ses descripteurs de fichiers, ce qui lui a ensuite permis de charger cette classe qui n'avait pas été trouvée en mémoire juste après la mise à niveau rpm.

J'espère que ce cas spécifique aide quelqu'un.

1
John Chesshir

Mes deux cents dans cette chaîne:

Assurez-vous que le classpath contient full chemins (/home/user/lib/some_lib.jar au lieu de ~/lib/some_lib.jar), sinon vous pouvez toujours faire face à une erreur NoClassDefFoundError.

0
khkarens

J'ai eu le même problème avec mon développement Android en utilisant le studio Android . Les solutions fournies sont générales et ne m'a pas aidé (du moins pour moi) . Après des heures de recherche, j'ai trouvé la solution suivante et peut aider les développeurs Android qui sont en train de développer à l'aide d'Android studio . modifiez les paramètres comme suit Préférences -> Construire, Exécution, Déploiement -> Exécution instantanée -> Désélectionnez la première option.

Avec ce changement, je suis opérationnel. J'espère que cela aidera mes amis dev.

0
mask

J'utilise le plugin FileSync pour Eclipse afin de pouvoir déboguer en direct sur Tomcat et j'ai reçu NoClassFoundError car j'avais ajouté une entrée de synchronisation pour le répertoire bin dans l'espace de travail Eclipse => classes dans metadata synchronisation de dossier pour le répertoire extlib dans Eclipse =>

C:\Users\Stuart\Eclipse-workspace\.metadata\.plugins\org.Eclipse.wst.server.core\tmp0\webapps\myApp\WEB-INF\lib 

0
Stuart Cardall

si vous avez récemment ajouté la prise en charge multidex dans Android Studio, procédez comme suit:

// To Support MultiDex
implementation 'com.Android.support:multidex:1.0.1'

votre solution doit donc être étendue à partir de MultiDexApplication au lieu de Application.

public class MyApp extends MultiDexApplication {
0
do01

Cela m'est arrivé dans Android Studio.

La solution qui a fonctionné pour moi: Il suffit de redémarrer le studio.

0
yanish

Vérifiez cela si vous avez un gestionnaire statique dans votre classe. Si c'est le cas, soyez prudent, car le gestionnaire statique ne peut être lancé que dans un thread avec une boucle, le crash pourrait être déclenché de cette façon

1. Tout d’abord, créez l’instance de classe dans un simple thread et attrapez le crash.

2.alors appelez la méthode de champ de la classe dans le fil principal, vous obtiendrez le NoClassDefFoundError.

voici le code de test:

public class MyClass{
       private static  Handler mHandler = new Handler();
       public static int num = 0;
}

dans votre méthode d'activité principale OnCrete, ajoutez une partie de code de test:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //test code start
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                MyClass myClass = new MyClass();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }).start();

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    MyClass.num = 3;
    // end of test code
}

il existe un moyen simple de le réparer en utilisant un handlerThread pour init handler: 

private static Handler mHandler;
private static HandlerThread handlerThread = new HandlerThread("newthread");
static {
    handlerThread.start();
    mHandler = new Handler(handlerThread.getLooper(), mHandlerCB);
}
0
Michael

Pour mon projet, le problème était que le navigateur Chrome et chromedriver n'étaient pas compatibles. J'avais une très ancienne version du pilote qui ne pouvait même pas ouvrir le navigateur. Je viens de télécharger la dernière version des deux et le problème a été résolu. Comment ai-je découvert le problème? Parce que j'ai exécuté mon projet en utilisant le pilote firefox natif Selenium avec une ancienne version de FF intégrée à mon application, j'ai alors réalisé que le problème était une incompatibilité entre le navigateur et le pilote.

J'espère que cela pourra aider quiconque ayant un problème similaire au mien, ayant généré le même message d'erreur.

0
Kyon Perez

Si vous utilisez plusieurs modules, vous devriez avoir 

dexOptions {
    preDexLibraries = false
}

dans votre fichier de construction.

0
Matin Petrulak

Je développe une application basée sur Eclipse, également connue sous le nom RCP (Rich Client Platform) . Et je suis confrontée à ce problème après le refactoring (déplacement d'une classe d'un plugin vers un nouveau).

Nettoyer le projet et la mise à jour Maven n’a pas aidé.

Le problème provient de Bundle-Activator qui n'a pas été mis à jour automatiquement. La mise à jour manuelle de Bundle-Activator sous MANIFEST.MF dans le nouveau plug-in a corrigé mon problème.

0

Je reçois NoClassFoundError lorsque les classes chargées par le chargeur de classes d'exécution ne peuvent pas accéder aux classes déjà chargées par le rootloader Java. Étant donné que les différents chargeurs de classes se trouvent dans différents domaines de sécurité (selon Java), jvm ne permet pas aux classes déjà chargées par le rootloader d'être résolues dans l'espace adresse du chargeur d'exécution.

Exécutez votre programme avec 'Java -javaagent: tracer.jar [YOUR Java ARGS]'

Il génère une sortie montrant la classe chargée et l’environnement de chargement qui a chargé la classe. Il est très utile de déterminer pourquoi une classe ne peut pas être résolue.

// ClassLoaderTracer.Java
// From: https://blogs.Oracle.com/sundararajan/entry/tracing_class_loading_1_5

import Java.lang.instrument.*;
import Java.security.*;

// manifest.mf
// Premain-Class: ClassLoadTracer

// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class

// Java -javaagent:tracer.jar  [...]

public class ClassLoadTracer 
{
    public static void premain(String agentArgs, Instrumentation inst) 
    {
        final Java.io.PrintStream out = System.out;
        inst.addTransformer(new ClassFileTransformer() {
            public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

                String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
                out.println(className + " loaded by " + loader + " at " + new Java.util.Date() + " in " + pd);

                // dump stack trace of the thread loading class 
                Thread.dumpStack();

                // we just want the original .class bytes to be loaded!
                // we are not instrumenting it...
                return null;
            }
        });
    }
}
0
codeDr

Une source d'erreur pour cette exception pourrait provenir de définitions incohérentes pour Proguard, par exemple. un manquant

-libraryJars "path.to.a.missing.jar.library". 

Cela explique pourquoi la compilation et l’exécution fonctionnent bien, étant donné que le fichier jar est là, alors que le nettoyage et la construction échouent. N'oubliez pas de définir les bibliothèques de fichiers jar récemment ajoutées dans proguard setup!

Notez que les messages d'erreur de Proguard ne sont pas vraiment à la hauteur, car ils peuvent facilement être confondus avec des messages ant similaires qui arrivent lorsque le pot n'est pas du tout là. Tout en bas, il y aura un petit soupçon de proguard en difficulté. Par conséquent, il est tout à fait logique de commencer à rechercher les erreurs de classpath traditionnelles, etc., mais ce sera en vain.

À l’évidence, l’exception NoClassDefFound sera le résultat lors de l’exécution, par exemple. le fichier jar exécutable résultant est construit et basé sur un manque de cohérence de proguard. Certains l'appellent proguard "Hell" 

0
carl

Cela arrive souvent avec mes appareils Genymotion . Assurez-vous de disposer d’une bonne quantité de mémoire sur votre lecteur où Genymotion est installé.

0
totteire