ClassNotFoundException при десериализации содержимого файла двоичного класса - PullRequest
5 голосов
/ 10 июня 2011

Я не знаю много о Java.Я пытаюсь прочитать файл, содержащий int и различные экземпляры класса под названием «Автомобиль».Когда я десериализирую его, программа выдает исключение ClassNotFoundException, и я не могу понять, почему.

Вот код:

        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");
    }

Заранее спасибо.* РЕДАКТИРОВАТЬ: вот трассировка стека

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)

Ответы [ 7 ]

9 голосов
/ 10 июня 2011

Когда вы десериализуете сериализованное дерево объектов, классы всех объектов должны находиться в пути к классам.В этом контексте ClassNotFoundException, скорее всего, означает, что один из необходимых классов не находится на пути к классам.Вы должны решить эту проблему, чтобы десериализация работала.

В этом случае es4.Automobile отсутствует.


Может ли проблема быть вызвана пользовательским исключением, которое я сделалкоторый запускается Automobile?

Единственные другие возможности, о которых я могу думать:

  • es4.Automobile имеет прямую или косвенную зависимость от какого-либо другого класса, который отсутствует
  • статическая инициализация es4.Automobile или зависимого класса вызвала исключение, которое не было перехвачено внутри класса.

Но оба они должны (я думаю) иметьпривел к другой трассировке стека.


Я только что заметил, что имя пакета - es4p2, а не es4.Почему это говорит es4?Может быть потому, что программа, которая сохраняет файл, использует другое имя пакета?

Я понятия не имею, почему они отличаются.Вам нужно поговорить с тем, кто написал код / ​​создал сериализованные объекты.Тем не менее, это наиболее вероятно причина вашей проблемы.Класс с другим именем пакета - это другой класс.Period.


Вы должны всегда выводить (или, лучше, записывать) трассировку стека при обнаружении непредвиденного исключения.Это расскажет вам (и нам) больше о том, что пошло не так, и в этом случае название класса, который отсутствует.

1 голос
/ 17 марта 2017

Это старый вопрос, но это может помочь кому-то еще. Я столкнулся с той же проблемой, и проблема заключалась в том, что я не использовал текущий загрузчик классов потоков. Ниже вы найдете класс сериализатора, который я использовал в проекте Grails, это довольно просто использовать в Java Надеюсь, это поможет

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 голос
/ 10 июня 2011

Обычно это происходит, если ваш класс Automobile не находится в пути к классам во время выполнения.

0 голосов
/ 16 января 2018

У меня была похожая проблема с ObjectInputStream, читающим сериализованные объекты. Классы для тех объектов, которые я добавил во время выполнения с помощью URLClassloader. Проблема заключалась в том, что ObjectInputStream не использовал Thread ClassLoader, который я установил с

Thread.currentThread().setContextClassLoader(cl);

но вместо этого AppClassLoader, который вы не можете настроить с помощью java 9. Поэтому я создал свой собственный ObjectInputStream как подтип исходного и переопределил метод resolClass:

@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;
        }
    }
}
0 голосов
/ 12 мая 2017

Я исправил это проще, чем другие ответы - моя проблема возникла при использовании класса в нескольких проектах .

Если у вас есть несколько проектов, убедитесь, что конкретный класс, который вы десериализуете, находится на том же пути! Это означает, что те же имена пакетов и т. Д. Внутри этого проекта. В противном случае он не найдет его и не вызовет выброс ClassNotFoundException.

Так что, если он в

/ MyPackage / otherPackage / Test.java

Затем убедитесь, что этот путь точно такой же в вашем другом проекте.

0 голосов
/ 10 июля 2012

Вы можете получить доступ к имени класса из сообщения об исключении ClassNotFound - это ужасно зависеть от этого в коде - но оно должно дать вам некоторое представление. Хотелось бы, чтобы был какой-то лучший способ получения информации о сериализованных объектах без необходимости иметь доступный класс.

0 голосов
/ 10 июня 2011

Есть ли в вашем классе Automobile поле, подобное этому?

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

Если нет, определите один. Дайте нам знать, если это исправит.

...