Java 反序列化序列化对象时发生ClassNotFound异常

Java 反序列化序列化对象时发生ClassNotFound异常,java,object,exception,serialization,classnotfoundexception,Java,Object,Exception,Serialization,Classnotfoundexception,我正在尝试序列化和反序列化一个对象。此对象可以包含对其他对象、ArrayList和HashMap的引用 当我尝试执行代码时,序列化可以正常工作,但反序列化不行。它会导致以下异常: Exception in thread "main" java.lang.ClassNotFoundException: experiment.Experiment$1 at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at ja

我正在尝试序列化和反序列化一个对象。此对象可以包含对其他对象、ArrayList和HashMap的引用

当我尝试执行代码时,序列化可以正常工作,但反序列化不行。它会导致以下异常:

Exception in thread "main" java.lang.ClassNotFoundException: experiment.Experiment$1
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at javax.crypto.extObjectInputStream.resolveClass(SealedObject.java:490)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
    at javax.crypto.SealedObject.getObject(SealedObject.java:302)
    at experiment.Experiment.main(Experiment.java:52)
Java Result: 1
我的主要课程是实验,如下所示:

public class Experiment {  
    public static void main(String[] args) throws Exception {
        File data = new File("C:\\Users\\Furze\\Desktop\\experiment.dat");   
        // I only execute the following to encrypt the file, which works fine:
        Test test = new Test(new VariableMap<String, String>() {{
            put("Name", "Furze");
        }});   
        Cipher cipher = Cipher.getInstance("Blowfish");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[] {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, "Blowfish"));
        SealedObject sealedObject = new SealedObject(test, cipher);
        CipherOutputStream outputStream = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(data.getPath())), cipher);
        ObjectOutputStream objectOutput = new ObjectOutputStream(outputStream);
        objectOutput.writeObject(sealedObject);     
        objectOutput.close();
        // I then comment out the above code to test the file, which fails.
        Cipher cipher = Cipher.getInstance("Blowfish");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(new byte[] {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, "Blowfish"));
        CipherInputStream inputStream = new CipherInputStream(new BufferedInputStream(new FileInputStream(data.getPath())), cipher);
        ObjectInputStream objectInput = new ObjectInputStream(inputStream);
        SealedObject sealedObject = (SealedObject) objectInput.readObject();
        Test test = (Test) sealedObject.getObject(cipher);
        System.out.println(test.variables.get("Name"));
    }
}
// The VariableMap class is something I added during debugging to test if HashMap simply isn't serializable. It didn't help. It does have to stay a HashMap (or VariableMap!) however, for my code to operate correctly.
class VariableMap<Name, Value> extends HashMap<String, String> implements java.io.Serializable {
    public VariableMap() {
        super();
    }
}

public class Test implements java.io.Serializable {
    VariableMap<String, String> variables = new VariableMap<>();
    public Test() {}
    public Test(VariableMap<String, String> variables) {
        this.variables = variables;
    }
}

有人能解释一下我的代码出了什么问题吗?我已经读过关于更改类路径的内容,但当我尝试更改时,没有任何区别。

您缺少类顶部的包声明,它应该是:

package experiment;

public class Experiment implements Serializable {
    public static void main(String[] args) throws Exception {
        File data = new File("C:\\Users\\Furze\\Desktop\\experiment.dat");   
        // I only execute the following to encrypt the file, which works fine:
        Test test = new Test(new VariableMap<String, String>() {{
            put("Name", "Furze");
        }});   
        Cipher cipher = Cipher.getInstance("Blowfish");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[] {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, "Blowfish"));
        SealedObject sealedObject = new SealedObject(test, cipher);
        CipherOutputStream outputStream = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(data.getPath())), cipher);
        ObjectOutputStream objectOutput = new ObjectOutputStream(outputStream);
        objectOutput.writeObject(sealedObject);     
        objectOutput.close();
        // I then comment out the above code to test the file, which fails.
        Cipher cipher = Cipher.getInstance("Blowfish");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(new byte[] {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, "Blowfish"));
        CipherInputStream inputStream = new CipherInputStream(new BufferedInputStream(new FileInputStream(data.getPath())), cipher);
        ObjectInputStream objectInput = new ObjectInputStream(inputStream);
        SealedObject sealedObject = (SealedObject) objectInput.readObject();
        Test test = (Test) sealedObject.getObject(cipher);
        System.out.println(test.variables.get("Name"));
    }
}
包装实验;
公共类实验实现可序列化{
公共静态void main(字符串[]args)引发异常{
文件数据=新文件(“C:\\Users\\Furze\\Desktop\\Experience.dat”);
//我只执行以下操作来加密文件,效果很好:
测试=新测试(新变量映射(){{
放置(“名称”、“Furze”);
}});   
Cipher Cipher=Cipher.getInstance(“河豚”);
cipher.init(cipher.ENCRYPT_模式,新的SecretKeySpec(新字节[]{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07},“河豚”);
SealedObject SealedObject=新的SealedObject(测试,密码);
CipherOutputStream outputStream=新的CipherOutputStream(新的BufferedOutputStream(data.getPath()),cipher);
ObjectOutputStream objectOutput=新的ObjectOutputStream(outputStream);
objectOutput.writeObject(sealedObject);
objectOutput.close();
//然后我注释掉上面的代码来测试文件,但失败了。
Cipher Cipher=Cipher.getInstance(“河豚”);
cipher.init(cipher.DECRYPT_模式,新的SecretKeySpec(新字节[]{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07},“河豚”);
CipherInputStream inputStream=new CipherInputStream(new BufferedInputStream(new FileInputStream(data.getPath())),cipher);
ObjectInputStream objectInput=新ObjectInputStream(inputStream);
SealedObject SealedObject=(SealedObject)objectInput.readObject();
Test=(Test)sealedObject.getObject(密码);
System.out.println(test.variables.get(“Name”);
}
}

您缺少类顶部的包声明,它应该是:

package experiment;

public class Experiment implements Serializable {
    public static void main(String[] args) throws Exception {
        File data = new File("C:\\Users\\Furze\\Desktop\\experiment.dat");   
        // I only execute the following to encrypt the file, which works fine:
        Test test = new Test(new VariableMap<String, String>() {{
            put("Name", "Furze");
        }});   
        Cipher cipher = Cipher.getInstance("Blowfish");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[] {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, "Blowfish"));
        SealedObject sealedObject = new SealedObject(test, cipher);
        CipherOutputStream outputStream = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(data.getPath())), cipher);
        ObjectOutputStream objectOutput = new ObjectOutputStream(outputStream);
        objectOutput.writeObject(sealedObject);     
        objectOutput.close();
        // I then comment out the above code to test the file, which fails.
        Cipher cipher = Cipher.getInstance("Blowfish");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(new byte[] {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, "Blowfish"));
        CipherInputStream inputStream = new CipherInputStream(new BufferedInputStream(new FileInputStream(data.getPath())), cipher);
        ObjectInputStream objectInput = new ObjectInputStream(inputStream);
        SealedObject sealedObject = (SealedObject) objectInput.readObject();
        Test test = (Test) sealedObject.getObject(cipher);
        System.out.println(test.variables.get("Name"));
    }
}
包装实验;
公共类实验实现可序列化{
公共静态void main(字符串[]args)引发异常{
文件数据=新文件(“C:\\Users\\Furze\\Desktop\\Experience.dat”);
//我只执行以下操作来加密文件,效果很好:
测试=新测试(新变量映射(){{
放置(“名称”、“Furze”);
}});   
Cipher Cipher=Cipher.getInstance(“河豚”);
cipher.init(cipher.ENCRYPT_模式,新的SecretKeySpec(新字节[]{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07},“河豚”);
SealedObject SealedObject=新的SealedObject(测试,密码);
CipherOutputStream outputStream=新的CipherOutputStream(新的BufferedOutputStream(data.getPath()),cipher);
ObjectOutputStream objectOutput=新的ObjectOutputStream(outputStream);
objectOutput.writeObject(sealedObject);
objectOutput.close();
//然后我注释掉上面的代码来测试文件,但失败了。
Cipher Cipher=Cipher.getInstance(“河豚”);
cipher.init(cipher.DECRYPT_模式,新的SecretKeySpec(新字节[]{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07},“河豚”);
CipherInputStream inputStream=new CipherInputStream(new BufferedInputStream(new FileInputStream(data.getPath())),cipher);
ObjectInputStream objectInput=新ObjectInputStream(inputStream);
SealedObject SealedObject=(SealedObject)objectInput.readObject();
Test=(Test)sealedObject.getObject(密码);
System.out.println(test.variables.get(“Name”);
}
}
情况

newvariablemap(){{
放置(“名称”、“Furze”);
}}
创建匿名内部类(类的子类
VariableMap
)并创建其对象

类和对象都是在同一位置创建的

它仍然是可序列化的


问题 当您注释它时,类定义本身消失

这将导致前面提到的
ClassNotFoundException


解决
  • 尽可能避免
    序列化
    。实现您自己的数据存储机制
  • 如果必须使用
    序列化
    ,请避免使用双大括号初始化
  • 在不使用声明的情况下维护声明(
    test\u old
    way)。然而,这是一个临时解决方案,也是一种糟糕的做法。这是混乱的,不可能记住。这也是将来出现错误的可能原因
  • 情况

    newvariablemap(){{
    放置(“名称”、“Furze”);
    }}
    
    创建匿名内部类(类的子类
    VariableMap
    )并创建其对象

    类和对象都是在同一位置创建的

    它仍然是可序列化的


    问题 当您注释它时,类定义本身消失

    这将导致前面提到的
    ClassNotFoundException


    解决
  • 尽可能避免
    序列化
    。实现您自己的数据存储机制
  • 如果必须使用
    序列化
    ,请避免使用双大括号初始化
  • 在不使用声明的情况下维护声明(
    test\u old
    way)。然而,这是一个临时解决方案,也是一种糟糕的做法。这是混乱的,不可能记住。这也是将来出现错误的可能原因

  • 我认为您缺少以下答案,因为我将您的所有代码放在一个文件中,并且运行良好。@Pra