7
votes

ClassNotFoundException lors de la désérialisation d'un contenu de classement binaire

Je ne sais pas grand chose sur Java. J'essaie de lire un fichier contenant une INT et diverses instances d'une classe appelée "Automobile". Lorsque je les désérialisalisalisate, le programme jette une parfaite notefoundException et je ne peux pas sembler comprendre pourquoi.

Voici le code: P>

java.lang.ClassNotFoundException: es4.Automobile
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
    at es4p2.Main.main(Main.java:35)


3 commentaires

S'il vous plaît montrer les détails de l'exception.


Pouvez-vous fournir quelques détails de plus, idéalement la stacktrace?


désérialisez-vous exactement la même classe qui a été écrite? Est-ce que l'automobile est-ce que Tapez votre code de désérialisation dans le package ES4 ?


7 Réponses :


-1
votes

Votre automobile a-t-il un champ comme celui-ci? XXX

sinon, définissez un. Laissez-nous savoir si cela le corrige.


2 commentaires

J'ai ajouté que à la classe, j'ai toujours la question.


Omettre cela ne cause pas ce problème.



1
votes

Cela se produit généralement si votre classe automobile n'est pas dans la classe d'exécution.


0 commentaires

11
votes

Lorsque vous désérialisez une arborescence d'objets sérialisés, les classes de tous les objets doivent être sur la classe de classe. Dans ce contexte, un ClassNotFoundException signifie probablement que l'une des classes requises n'est pas sur la classe de classe. Vous devez résoudre ce problème pour la désérialisation au travail.

Dans ce cas, le es4.Automobile est manquant.


Le problème peut-il être causé par une exception personnalisée que j'ai faite qui est tirée par automobile?

Les seules autres possibilités que je peux penser sont:

  • es4.Automobile a une dépendance directe ou indirecte sur une autre classe qui manque
  • L'initialisation statique de es4.Automobile ou une classe dépendante a lancé une exception qui n'a pas été attrapée à l'intérieur de la classe.

    Mais les deux celles-ci devraient (je pense) ont abouti à une trace de pile différente.


    Je viens de remarquer que le nom du paquet est ES4P2, pas ES4. Pourquoi dit-il es4? Pourrait-il être parce que le programme qui enregistre le fichier utilise un autre nom de paquet?

    Je ne sais pas pourquoi ils sont différents. Vous auriez besoin de parler à celui qui a écrit le code / produit les objets sérialisés. Cependant, c'est probablement la cause de votre problème. Une classe avec un nom de paquet différent est une classe différente. Période.


    Vous devez toujours produire (ou mieux, log) la structure de StackTrace lorsqu'une exception inattendue est capturée. Cela vous dira (et nous) plus sur ce qui a mal tourné, et dans ce cas, le nom de la classe qui manque.


5 commentaires

Qu'entendez-vous par la classe "étant dans la classe de classe"? Le fichier automobile.java est dans le même forfait que Main.java, qui tire l'exception.


Le problème pourrait-il être causé par une exception personnalisée que j'ai faite qui est tirée par automobile?


Je viens de remarquer que le nom du paquet est ES4P2, pas ES4. Pourquoi dit-il es4? Pourrait-il être parce que le programme qui enregistre le fichier utilise un autre nom de paquet?


Merci. J'ai décidé que je vais fusionner les deux projets au lieu de jouer avec eux plus loin


L'automobile sauvée était un ES4.Automobile, et vous voulez désormais désériorialiser «dans» un ES4P2.Automobile (sans avoir l'autre dans votre classe de classe) évidemment que cela ne peut pas fonctionner. Comment la désérialisation devrait-elle savoir que vous voulez maintenant avoir «un type de noeud d'automobile»?



-3
votes

Vous pouvez accéder au nom de la classe à partir du message de l'exception de la classeNotfound - c'est horrible de dépendre de cela dans le code - mais cela devrait vous donner une idée. J'aimerais qu'il y ait un meilleur moyen d'obtenir des informations sur des objets sérialisés sans avoir à avoir la classe disponible.


1 commentaires

Vous n'avez pas à «dépendre de cela dans le code». Vous devez juste déployer votre application correctement. Aucune idée de ce que vous souhaitez exactement dans votre dernière phrase.



1
votes

C'est et c'est une question ancienne, mais cela peut aider quelqu'un d'autre. Je suis confronté au même problème et que le problème était que je n'utilisais pas le chargeur de classe de thread actuel. Vous trouverez ci-dessous la classe Serializer que j'ai utilisé dans un projet Grails, devrait être assez simple, utilisez-le en Java J'espère que cela aide

public final class Serializer<T> {

/**
 * Converts an Object to a byte array.
 *
 * @param object, the Object to serialize.
 * @return, the byte array that stores the serialized object.
 */

public static byte[] serialize(T object) {

    ByteArrayOutputStream bos = new ByteArrayOutputStream()
    ObjectOutput out = null
    try {
        out = new ObjectOutputStream(bos)
        out.writeObject(object)

        byte[] byteArray = bos.toByteArray()
        return byteArray

    } catch (IOException e) {
        e.printStackTrace()
        return null

    } finally {
        try {
            if (out != null)
                out.close()
        } catch (IOException ex) {
            ex.printStackTrace()
            return null
        }
        try {
            bos.close()
        } catch (IOException ex) {
            ex.printStackTrace()
            return null
        }
    }

}

/**
 * Converts a byte array to an Object.
 *
 * @param byteArray, a byte array that represents a serialized Object.
 * @return, an instance of the Object class.
 */
public static Object deserialize(byte[] byteArray) {
    ByteArrayInputStream bis = new ByteArrayInputStream(byteArray)
    ObjectInput input = null
    try {
        input = new ObjectInputStream(bis){
            @Override protected Class<?> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
                ClassLoader cl = Thread.currentThread().getContextClassLoader();
                if (cl == null)  return super.resolveClass(desc);
                return Class.forName(desc.getName(), false, cl);
            }
        };
        Object o = input.readObject()
        return o

    } catch (ClassNotFoundException | IOException e) {
        e.printStackTrace()
        return null
    } finally {
        try {
            bis.close()
        } catch (IOException ex) {
        }
        try {
            if (input != null)
                input.close()
        } catch (IOException ex) {
            ex.printStackTrace()
            return null
        }
    }
}


1 commentaires

Pourquoi ne pas utiliser le chargeur de classe actuel ?! Merci pour votre inspiration.



0
votes

Je l'ai réparé de manière plus facile que les autres réponses - mon problème s'est produit lors de l'utilisation de la classe dans plusieurs projets . .

Si vous avez plusieurs projets, assurez-vous que la classe spécifique que vous désérialisez est dans le même chemin! Cela signifie que les mêmes noms d'emballages, etc. à l'intérieur de ce projet. Sinon, il ne trouvera pas et causera le classnotfoundexception à lancer.

donc si c'est dans

/mypackage/otherpackage/test.java

alors assurez-vous que ce chemin est exactement le même dans votre autre projet.


1 commentaires

Classes avec le même nom simple, mais différents noms de colis sont différentes classes . C'est un élément fondamental du système de type Java. (Et le "chemin" est dérivé du nom du paquet.)



0
votes

ive avait un problème similaire avec un objet useinputtream lecture d'objets sérialisés. Les classes pour ces objets que j'ai ajoutés au moment de l'exécution avec un URLClassloader. Le problème était que l'ObjectInputStream n'utilisait pas le chargeur de fil de thread que j'ai défini avec xxx

mais plutôt le chargeur d'applass, que vous ne pouvez pas personnaliser avec Java 9. Donc, j'ai donc fait mon propre objetInputStream en tant que sous-type de L'original et la méthode de résolution de la résolution: xxx


0 commentaires