重构包后反序列化时的ClassNotFoundException

时间:2016-02-23 08:59:19

标签: java classnotfoundexception

当我尝试执行程序时,我遇到了一个问题(破坏了类路径?)。 .class文件位于: C:\...\...\...\StoreDirectorySystem4.0\bin\build\classes\system,所以我将类路径指向system文件夹。我也尝试过指向jar文件,但无济于事,继续:

  

指定.zip或.jar文件的路径时,必须以文件名结束路径。指定.class文件的路径时,该路径应以包含.class文件的文件夹结束。    (source

然而,当我构建项目(使用ant)时,它会抛出ClassNotFoundException。这是堆栈跟踪:

    [java] java.lang.ClassNotFoundException: com.company.Clerk
    [java]     at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    [java]     at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    [java]     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    [java]     at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    [java]     at java.lang.Class.forName0(Native Method)
    [java]     at java.lang.Class.forName(Class.java:348)
    [java]     at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java :626)
    [java]     at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream. java:1613)
    [java]     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
    [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
    [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    [java]     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
    [java]     at java.util.ArrayList.readObject(ArrayList.java:791)
    [java]     at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)
    [java]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    [java]     at java.lang.reflect.Method.invoke(Method.java:497)
    [java]     at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
    [java]     at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1900)
    [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
    [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    [java]     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
    [java]     at system.Directory.readFile(Unknown Source)
    [java]     at system.Directory.<init>(Unknown Source)
    [java]     at system.DirectoryServer.main(Unknown Source)

问题是,Clerk中不再存在com.company类(我在IntelliJ IDEA中重构了包的名称)。它存在于前面提到的system包中。 Clerk类已在其中声明package system;。 当我尝试在Directory类中读取序列化集合时出现异常,特别是在这里:

public ArrayList<Employee> readFile() {
    try (ObjectInputStream inputStream =
                 new ObjectInputStream(new FileInputStream(this.file))) {
        employeeList = (ArrayList<Employee>) inputStream.readObject();
    } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
    }
    return employeeList;
}

jar文件包含:

META-INF/
META-INF/MANIFEST.MF
system/
system/Clerk.class
system/Directory.class
system/DirectoryServer.class
system/Employee.class
system/FullTime.class
system/Manager.class
system/PartTime.class

所以我的问题是,问题是什么,以及如何解决?

2 个答案:

答案 0 :(得分:1)

  

ClassNotFoundException:com.company.Clerk

这意味着找不到课程com.company.Clerk,因此您需要在JAR com/company/Clerk.class中找到,或者在您的课程路径中有com/company/Clerk.class上方的目录。

简而言之,包必须与该类所在的目录相匹配。

  

他说他修改了代码并更改了包,并希望反序列化在重构之前序列化的内容

这不会更改序列化格式,标准序列化不支持别名或重命名。您需要反序列化原始类并在运行时将其转换为新类。

答案 1 :(得分:0)

存储在文件中的对象具有com.company.Clerk类。当你改名时,那个类停止存在,所以显然不可能再读取这些对象了。您的选择是:将类的名称更改回原来的名称,或者创建一个程序将文件从一种格式转换为另一种格式,或者接受您将丢失文件中的数据并继续您的生活,或者添加将旧类名解析为新类的代码(覆盖resolveClass方法)。