Question

je reçois un NoClassDefFoundError lorsque j'exécute mon application Java.Quelle en est généralement la cause ?

Était-ce utile?

La solution

Cela se produit lorsqu'il existe un fichier de classe dont dépend votre code et qu'il est présent au moment de la compilation mais introuvable au moment de l'exécution.Recherchez les différences dans votre temps de construction et vos chemins de classe d’exécution.

Autres conseils

Bien qu'il soit possible que cela soit dû à une inadéquation de chemin de classe entre le moment de la compilation et celui de l'exécution, ce n'est pas nécessairement vrai.

Il est important de garder deux ou trois exceptions différentes bien en tête dans ce cas :

  1. java.lang.ClassNotFoundException Cette exception indique que la classe n'a pas été trouvée sur le chemin d'accès aux classes.Cela indique que nous essayions de charger la définition de classe et que la classe n'existait pas sur le chemin de classe.

  2. java.lang.NoClassDefFoundError Cette exception indique que la JVM a recherché dans sa structure de données de définition de classe interne la définition d'une classe et ne l'a pas trouvée.C'est différent de dire qu'il n'a pas pu être chargé à partir du chemin de classe.Habituellement, cela indique que nous avons déjà tenté de charger une classe à partir du chemin de classe, mais que cela a échoué pour une raison quelconque. Nous essayons maintenant d'utiliser à nouveau la classe (et devons donc la charger, car elle a échoué la dernière fois), mais nous Je ne vais même pas essayer de le charger, car nous avons échoué à le charger plus tôt (et nous soupçonnons raisonnablement que nous échouerions à nouveau).L'échec précédent peut être une ClassNotFoundException ou une ExceptionInInitializerError (indiquant un échec dans le bloc d'initialisation statique) ou un certain nombre d'autres problèmes.Le fait est qu’une NoClassDefFoundError n’est pas nécessairement un problème de chemin de classe.

Voici le code pour illustrer java.lang.NoClassDefFoundError.S'il te plait regarde La réponse de Jared pour une explication détaillée.

NoClassDefFoundErrorDemo.java

public class NoClassDefFoundErrorDemo {
    public static void main(String[] args) {
        try {
            // The following line would throw ExceptionInInitializerError
            SimpleCalculator calculator1 = new SimpleCalculator();
        } catch (Throwable t) {
            System.out.println(t);
        }
        // The following line would cause NoClassDefFoundError
        SimpleCalculator calculator2 = new SimpleCalculator();
    }

}

SimpleCalculator.java

public class SimpleCalculator {
    static int undefined = 1 / 0;
}

J'ai constaté que parfois j'obtenais une erreur NoClassDefFound lorsque le code est compilé avec une version incompatible de la classe trouvée au moment de l'exécution.Le cas spécifique dont je me souviens concerne la bibliothèque Apache Axis.Il y avait en fait 2 versions sur mon chemin de classe d'exécution et il récupérait la version obsolète et incompatible et non la bonne, provoquant une erreur NoClassDefFound.C'était dans une application en ligne de commande où j'utilisais une commande similaire à celle-ci.

set classpath=%classpath%;axis.jar

J'ai pu obtenir la version appropriée en utilisant :

set classpath=axis.jar;%classpath%;

NoClassDefFoundError en Java

Définition:

  1. La machine virtuelle Java n'est pas en mesure de trouver une classe particulière au moment de l'exécution qui était disponible au moment de la compilation.

  2. Si une classe était présente lors de la compilation mais n'est pas disponible dans le chemin de classe Java lors de l'exécution.

enter image description here

Exemples:

  1. La classe n'est pas dans Classpath, il n'y a pas de moyen sûr de la connaître, mais plusieurs fois, vous pouvez simplement jeter un œil à print System.getproperty("java.classpath") et il imprimera le chemin de classe à partir de là, vous pourrez au moins obtenir une idée de votre chemin de classe d'exécution réel.
  2. Un exemple simple de NoClassDefFoundError est que la classe appartient à un fichier JAR manquant ou que JAR n'a pas été ajouté au chemin de classe ou parfois le nom de jar a été modifié par quelqu'un comme dans mon cas, un de mes collègues a changé tibco.jar en tibco_v3.jar et le programme est échouer avec java.lang.NoClassDefFoundError et je me demandais ce qui ne va pas.

  3. Essayez simplement d'exécuter explicitement l'option -classpath avec le chemin de classe qui, selon vous, fonctionnera et si cela fonctionne, c'est un signe court et sûr que quelqu'un remplace le chemin de classe Java.

  4. Un problème d'autorisation sur le fichier JAR peut également provoquer NoClassDefFoundError en Java.
  5. Une faute de frappe sur la configuration XML peut également provoquer NoClassDefFoundError en Java.
  6. lorsque votre classe compilée, définie dans un package, n'est pas présente dans le même package lors du chargement, comme dans le cas de JApplet, elle lancera NoClassDefFoundError en Java.

Solutions possibles:

  1. La classe n'est pas disponible dans Java Classpath.
  2. Si vous travaillez dans un environnement J2EE, la visibilité de la classe parmi plusieurs Classloader peut également provoquer java.lang.NoClassDefFoundError, voir les exemples et la section scénario pour une discussion détaillée.
  3. Recherchez java.lang.ExceptionInInitializerError dans votre fichier journal.NoClassDefFoundError en raison de l’échec de l’initialisation statique est assez courant.
  4. Étant donné que NoClassDefFoundError est une sous-classe de java.lang.LinkageError, cela peut également survenir si l'une de ses dépendances, comme la bibliothèque native, n'est pas disponible.
  5. Tout script de démarrage remplace la variable d'environnement Classpath.
  6. Vous exécutez peut-être votre programme à l'aide de la commande jar et la classe n'est pas définie dans l'attribut ClassPath du fichier manifeste.

Ressources:

3 façons de résoudre NoClassDefFoundError

java.lang.NoClassDefFoundError Modèles de problèmes

C'est le meilleure solution J'ai trouvé jusqu'à présent.

Supposons que nous ayons un package appelé org.mypackage contenant les classes :

  • HelloWorld (classe principale)
  • Classe de support
  • ClasseUtil

et les fichiers définissant ce package sont stockés physiquement sous le répertoire D:\myprogram (sous Windows) ou /home/user/myprogram (sous Linux).

La structure du fichier ressemblera à ceci :enter image description here

Lorsque nous invoquons Java, nous spécifions le nom de l'application à exécuter : org.mypackage.HelloWorld.Cependant, nous devons également indiquer à Java où chercher les fichiers et répertoires définissant notre package.Donc pour lancer le programme, il faut utiliser la commande suivante :enter image description here

j'utilisais Cadre de printemps avec Maven et résolu cette erreur dans mon projet.

Une erreur d'exécution s'est produite dans la classe.Je lisais une propriété sous forme d'entier, mais lorsqu'il lisait la valeur du fichier de propriétés, sa valeur était double.

Spring ne m'a pas donné de trace complète de la pile sur la ligne sur laquelle le runtime a échoué.Il a simplement dit NoClassDefFoundError.Mais lorsque je l'ai exécuté en tant qu'application Java native (en le retirant de MVC), cela a donné ExceptionInInitializerError quelle était la véritable cause et comment j'ai retracé l'erreur.

La réponse de @xli m'a donné un aperçu de ce qui pourrait ne pas fonctionner dans mon code.

J'obtiens 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 des domaines de sécurité différents (selon Java), le JVM ne permettra pas aux classes déjà chargées par le chargeur root d'être résolues dans l'espace d'adressage du chargeur d'exécution.

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

Il produit 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;
            }
        });
    }
}

Lisez ceci surtout si vous voyez NoClassDefFoundErrors dans TESTS UNITAIRES...


Un cas intéressant dans lequel vous pourriez voir beaucoup de NoClassDefFoundErrors c'est quand vous :

  1. throw un RuntimeException dans le static bloc de votre classe Example
  2. Interceptez-le (ou si cela n'a pas d'importance, comme s'il était jeté dans un cas de test)
  3. Essayez de créer une instance de cette classe Example

static class Example {
    static {
        thisThrowsRuntimeException();
    }
}

static class OuterClazz {

    OuterClazz() {
        try {
            new Example();
        } catch (Throwable ignored) { //simulating catching RuntimeException from static block
            // DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
        }

        new Example(); //this throws NoClassDefFoundError
    }
}

NoClassDefError sera lancé accompagné de ExceptionInInitializerError du bloc statique RuntimeException.


C'est un cas particulièrement important lorsque vous voyez NoClassDefFoundErrors dans ton TESTS UNITAIRES.

D'une certaine manière, vous « partagez » static bloquer l'exécution entre les tests, mais le initial ExceptionInInitializerError ne sera que dans un cas de test.Le premier qui utilise la problématique Example classe.Autres cas de test utilisant le Example la classe va juste lancer NoClassDefFoundErrors.

Si vous avez généré du code (EMF, etc.), il peut y avoir trop d'initialiseurs statiques qui consomment tout l'espace de la pile.

Voir la question sur le débordement de pile Comment augmenter la taille de la pile Java ?.

La technique ci-dessous m'a aidé à plusieurs reprises :

System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());

où TheNoDefFoundClass est la classe qui pourrait être "perdue" en raison d'une préférence pour une ancienne version de la même bibliothèque utilisée par votre programme.Cela se produit le plus souvent lorsque le logiciel client est déployé dans un conteneur dominant, armé de ses propres chargeurs de classes et de tonnes d'anciennes versions des bibliothèques les plus populaires.

J'ai résolu mon problème en désactivant les preDexLibraries pour tous les modules :

dexOptions {
        preDexLibraries false
        ...

NoClassDefFoundError peut également se produire lorsqu'un statique L'initialiseur tente de charger un ensemble de ressources qui n'est pas disponible au moment de l'exécution, par exemple un fichier de propriétés que la classe affectée tente de charger à partir du META-INF répertoire, mais il n’y est pas.Si tu n'attrapes pas NoClassDefFoundError, parfois vous ne pourrez pas voir la trace complète de la pile ;pour surmonter ce problème, vous pouvez utiliser temporairement un catch clause pour Throwable:

try {
    // Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
    Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}

Si quelqu'un vient ici à cause de java.lang.NoClassDefFoundError: org/apache/log4j/Logger erreur, dans mon cas, elle a été produite parce que j'ai utilisé log4j 2 (mais je n'ai pas ajouté tous les fichiers qui l'accompagnent) et qu'une bibliothèque de dépendances a utilisé log4j 1.La solution était d'ajouter le pont Log4j 1.x :le pot log4j-1.2-api-<version>.jar qui vient avec log4j 2.Plus d'infos dans le log4j 2 migration.

Deux copies de paiement différentes du même projet

Dans mon cas, le problème était l'incapacité d'Eclipse à faire la différence entre deux copies différentes du même projet.J'en ai un verrouillé sur le tronc (contrôle de version SVN) et l'autre travaillant dans une branche à la fois.J'ai essayé une modification dans la copie de travail en tant que scénario de test JUnit, qui comprenait l'extraction d'une classe interne privée pour en faire une classe publique à part entière et pendant qu'elle fonctionnait, j'ouvre l'autre copie du projet pour en examiner une autre. partie du code qui nécessitait des modifications.À un moment donné, le NoClassDefFoundError est apparu en se plaignant que la classe interne privée n'était pas là ;un double-clic dans la trace de la pile m'a amené au fichier source dans la mauvaise copie du projet.

La fermeture de la copie principale du projet et l'exécution à nouveau du scénario de test ont résolu le problème.

Cette erreur peut être causée par une vérification non cochée Version Java exigences.

Dans mon cas, j'ai pu résoudre cette erreur, lors de la création d'un projet open source de grande envergure, en passant de Java 9 à Java 8 en utilisant SDKMAN !.

sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu

Ensuite, effectuez une nouvelle installation comme décrit ci-dessous.


Lors de l'utilisation Maven en tant qu'outil de construction, il est parfois utile - et généralement gratifiant - de faire un faire le ménage version 'installer' avec les tests désactivés.

mvn clean install -DskipTests

Maintenant que tout a été construit et installé, vous pouvez continuer et exécuter les tests.

mvn test

J'ai reçu des erreurs NoClassDefFound lorsque je n'ai pas exporté une classe dans l'onglet "Commander et exporter" dans le chemin de construction Java de mon projet.Assurez-vous de cocher l'onglet "Commander et exporter" de toutes les dépendances que vous ajoutez au chemin de construction du projet.Voir Avertissement d'éclipse :XXXXXXXXXXXX.jar ne sera ni exporté ni publié.Des exceptions ClassNotFoundException au moment de l'exécution peuvent en résulter.

Java n'a pas pu trouver la classe A lors de l'exécution.La classe A se trouvait dans le projet Maven ArtClient à partir d'un autre espace de travail.J'ai donc importé ArtClient dans mon projet Eclipse.Deux de mes projets utilisaient ArtClient comme dépendance.J'ai changé la référence de la bibliothèque en référence du projet pour ceux-ci (Build Path -> Configure Build Path).

Et le problème a disparu.

J'ai eu le même problème et je suis resté en stock pendant plusieurs heures.

J'ai trouvé la solution.Dans mon cas, la méthode statique a été définie à cause de cela.La JVM ne peut pas créer un autre objet de cette classe.

Par exemple,

private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");

J'ai reçu ce message après avoir supprimé deux fichiers de la bibliothèque SRC, et lorsque je les ai ramenés, j'ai continué à voir ce message d'erreur.

Ma solution était :Redémarrez Eclipse.Depuis, je n'ai plus revu ce message :-)

Assurez-vous que cela correspond dans le module:app et module:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top