Pregunta

No sé mucho sobre Java. Estoy tratando de leer un archivo que contenga un INT y varias instancias de una clase llamada "Automóvil". Sin embargo, cuando lo merezco, el programa lanza una ClassNotFoundException y parece que no puedo entender por qué.

Aquí está el código:

        try {
        FileInputStream fin = new FileInputStream(inputFile);
        ObjectInputStream input = new ObjectInputStream(fin);

        conto = input.readInt();

        Automobile[] macchine = new Automobile[conto];

        for(int i = 0; i < conto; i++) {
            macchine[i] = (Automobile)input.readObject();
        }

        String targa;
        System.out.print("\nInserire le cifre di una targa per rintracciare l'automobile: ");
        targa = sc1.nextLine();

        for(int i = 0; i < conto; i++) {
            if(macchine[i].getTarga().equals(targa))
                System.out.println(macchine[i]);
        }

    } catch(IOException e) {
        System.out.println("Errore nella lettura del file "+inputFile);
    } catch(java.lang.ClassNotFoundException e) {
        System.out.println("Class not found");
    }

Gracias por adelantado.

Editar: aquí está el Stacktrace

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)
¿Fue útil?

Solución

Cuando deserializas un árbol de objetos serializado, las clases de todos los objetos deben estar en el classpath. En este contexto, un ClassNotFoundException Lo más probable es que una de las clases requeridas no esté en la clase. Debe abordar esto para que la deserialización funcione.

En este caso, el es4.Automobile Está perdido.


¿Podría el problema ser causado por una excepción personalizada que hice que el automóvil dispara?

Las únicas otras posibilidades que puedo pensar son:

  • es4.Automobile tiene una dependencia directa o indirecta de otra clase que falta
  • la inicialización estática de es4.Automobile o una clase dependiente ha lanzado una excepción que no ha sido atrapada internamente a la clase.

Pero ambos deberían (creo) haber resultado en un rastro de pila diferente.


Acabo de notar que el nombre del paquete es ES4P2, no ES4. ¿Por qué dice ES4? ¿Podría ser porque el programa que guarda el archivo usa el nombre de otro paquete?

No tengo idea de por qué son diferentes. Debería hablar con quien escribió el código / produjo los objetos serializados. Sin embargo, esto es más probable la causa de su problema. Una clase con un nombre de paquete diferente es una clase diferente. Período.


Siempre debe emitir (o mejor, registrar) la StackTrace cuando se atrapa una excepción inesperada. Eso le dirá (y a nosotros) más sobre lo que ha salido mal, y en este caso el nombre de la clase que falta.

Otros consejos

Esto generalmente sucede si tu clase Automobile no está en la clase de tiempo de ejecución.

Esta es una vieja pregunta, pero esto puede ayudar a alguien más. Me enfrenté al mismo problema y el problema era que no estaba usando el cargador de clase de subproceso actual. Encontrará a continuación la clase Serializer que utilicé en un proyecto de Grials, debería ser bastante sencillo usar esto en Java, espero que esto ayude

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
        }
    }
}

Tu Automobile ¿La clase tiene un campo como este?

private static final long serialVersionUID = 140605814607823206L; // some unique number

Si no, defina uno. Háganos saber si eso lo soluciona.

Lo arreglé de manera más fácil que las otras respuestas: mi problema ocurrió al usar la clase en múltiples proyectos.

Si tiene múltiples proyectos, ¡asegúrese de que la clase específica que está deserializando esté en el mismo camino! Eso significa que los mismos nombres de paquetes, etc. dentro de ese proyecto. De lo contrario no lo encontrará y causará el ClassNotFoundException ser arrojado.

Entonces si está en

/mypackage/otherpackage/test.java

Luego, asegúrese de que ese camino sea exactamente el mismo en su otro proyecto.

He tenido un problema similar con un ObjectInputStream Reading Objects serializados. Las clases para esos objetos que agregué en tiempo de ejecución con un URLClassLoader. El problema era que el ObjectInputStream no usaba el cargador de clases de subprocesos con el que configuré

Thread.currentThread().setContextClassLoader(cl);

Pero en su lugar, el AppClassLoader, que no puede personalizar con Java 9. Así que hice mi propio ObjectInputStream como un subtipo de la original y Overidden el método resolveclass:

@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
    String name = desc.getName();
    try {
        return Class.forName(name, false, Thread.currentThread()
                .getContextClassLoader());
    } catch (ClassNotFoundException ex) {
        Class<?> cl = primClasses.get(name);
        if (cl != null) {
            return cl;
        } else {
            throw ex;
        }
    }
}

Puede acceder al nombre de clase desde el mensaje de la excepción ClassNotFound, es horrible depender de esto en el código, pero debería darle alguna idea. Desearía que hubiera una mejor manera de obtener información sobre objetos serializados sin tener que tener la clase disponible.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top