反序列化二进制类文件内容时出现 ClassNotFoundException

发布于 2024-11-14 15:44:25 字数 2082 浏览 1 评论 0原文

我对Java了解不多。我正在尝试读取一个包含 int 和名为“Automobile”的类的各种实例的文件。但是,当我反序列化它时,程序抛出 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)

I don't know much about Java. I'm trying to read a file containing an int and various instances of a class called "Automobile". When I deserialize it, though, the program throws a ClassNotFoundException and I can't seem to understand why.

Here's the code:

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

Thanks in advance.

EDIT: here's the 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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

夜司空 2024-11-21 15:44:25

当您反序列化序列化对象树时,所有对象的类都必须位于类路径上。在这种情况下,ClassNotFoundException很可能意味着所需的类之一不在类路径上。您必须解决这个问题才能使反序列化工作。

在这种情况下,es4.Automobile 丢失。


问题是否是由我创建的由 Automobile 触发的自定义异常引起的?

我能想到的唯一其他可能性是:

  • es4.Automobile 直接或间接依赖于缺少
  • es4.Automobile 静态初始化的其他类或依赖项类抛出了一个尚未在类内部捕获的异常。

但我认为这两者都应该导致不同的堆栈跟踪。


我刚刚注意到包名称是 es4p2,而不是 es4。为什么说是es4?难道是因为保存文件的程序使用了另一个包名?

我不知道他们为什么不同。您需要与编写代码/生成序列化对象的人交谈。但是,这最有可能是导致您的问题的原因。具有不同包名的类是不同的类。时期。


当捕获意外异常时,您应该始终输出(或者更好的是记录)堆栈跟踪。这将告诉您(和我们)更多有关出了什么问题的信息,在本例中还包括缺少的类的名称。

When you deserialize a serialized object tree, the classes of all the objects have to be on the classpath. In this context, a ClassNotFoundException most likely means that one of the classes required is not on the classpath. You have to address this for deserialization to work.

In this case, the es4.Automobile is missing.


Could the problem be caused by a custom exception I made which is fired by Automobile?

The only other possibilities I can think of are:

  • es4.Automobile has a direct or indirect dependency on some other class that is missing
  • the static initialization of es4.Automobile or a dependent class has thrown an exception that has not been caught internally to the class.

But both of those should (I think) have resulted in a different stack trace.


I just noticed the package name is es4p2, not es4. Why does it say es4? Could it be because the program which saves the file uses another package name?

I've no idea why they are different. You'd need to talk to whoever wrote the code / produced the serialized objects. However, this is most likely the cause of your problem. A class with a different package name is a different class. Period.


You should always output (or better, log) the stacktrace when an unexpected exception is caught. That will tell you (and us) more about what has gone wrong, and in this case the name of the class that is missing.

岛徒 2024-11-21 15:44:25

这是一个老问题,但这可能对其他人有帮助。我遇到了同样的问题,问题是我没有使用当前的线程类加载器。您将在下面找到我在 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
        }
    }
}

This is and old question but this may help someone else. I faced the same issue and the problem was that I was not using the current thread class loader. You will find below the serializer class that I used in a grails project, should be quite straightforward use this in java
Hope this helps

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
        }
    }
}
飘逸的'云 2024-11-21 15:44:25

如果您的类 Automobile 不在运行时类路径中,通常会发生这种情况。

This generally happens if your class Automobile is not in the runtime classpath.

乄_柒ぐ汐 2024-11-21 15:44:25

我用比其他答案更简单的方法修复了它——我的问题是在多个项目中使用该类时发生的。

如果您有多个项目,请确保您要反序列化的特定类位于完全相同的路径中!这意味着该项目中的包名称等相同。否则它将找不到它并导致抛出ClassNotFoundException

所以如果它在

/myPackage/otherPackage/Test.java

然后确保该路径与您的其他项目中的路径完全相同。

I fixed it in an easier way than the other answers -- my problem occurred when using the class in multiple projects.

If you have multiple projects, make sure that the specific class you're deserializing is in the exact same path! That means, the same package names etc inside that project. Otherwise it won't find it and cause the ClassNotFoundException to be thrown.

So if it's in

/myPackage/otherPackage/Test.java

Then make sure, that path is exactly the same in your other project.

夜光 2024-11-21 15:44:25

我在使用 ObjectInputStream 读取序列化对象时遇到了类似的问题。这些对象的类是我在运行时使用 URLClassloader 添加的。问题是 ObjectInputStream 没有使用我设置的 Thread ClassLoader,

Thread.currentThread().setContextClassLoader(cl);

而是使用 AppClassLoader,您无法使用 java 9 自定义它。因此,我将自己的 ObjectInputStream 创建为原始 ObjectInputStream 的子类型,并覆盖了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;
        }
    }
}

Ive had a similar problem with a ObjectInputStream reading serialized Objects. The classes for those Objects i added at runtime with a URLClassloader. The problem was that the ObjectInputStream did not use the Thread ClassLoader which i set with

Thread.currentThread().setContextClassLoader(cl);

but instead the AppClassLoader, which you cannot customize with java 9. So i made my own ObjectInputStream as a subtype of the original one and overidden the resolveClass Method:

@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;
        }
    }
}
孤君无依 2024-11-21 15:44:25

您的 Automobile 类有这样的字段吗?

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

如果没有,请定义一个。让我们知道是否可以解决问题。

Does your Automobile class have a field like this?

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

If not, define one. Let us know if that fixes it.

若能看破又如何 2024-11-21 15:44:25

您可以从 ClassNotFound 异常的消息中访问类名 - 在代码中依赖于此是可怕的 - 但它应该给您一些想法。我希望有一些更好的方法来获取有关序列化对象的信息,而无需提供可用的类。

You can access the class name from the message of the ClassNotFound exception - it's horrible to depend on this in the code - but it should give you some idea. I wish there were some better way of getting information about serialised objects without having to have the class available.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文