簡體   English   中英

反序列化序列化對象時,ClassNotFound異常

[英]ClassNotFound Exception when deserializing serialized object

我正在嘗試序列化和反序列化一個對象。 該對象可以包含對其他對象以及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

我的主要課程是Experiment,如下所示:

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

奇怪的是,如果我離開Test test = new Test(...); 回讀時完整部分,但將名稱更改為test_old類的test_old ,似乎可以正常工作。

對象類如下:

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

有人可以在這里解釋我的代碼出什么問題嗎? 我已經閱讀了有關更改CLASSPATH的內容,但是當我嘗試進行更改時沒有什么區別。

您缺少類頂部的包聲明,它應顯示為:

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

情況

什么是Java中的Double Brace初始化?

new VariableMap<String, String>() {{
    put("Name", "Furze");
}}

創建一個匿名內部類( VariableMap類的子類)並創建其對象。

類和對象都在同一位置創建

它仍然可以Serializable因為可序列化類的所有子類型本身都是可序列化的


問題

當你注釋掉類定義本身就消失了

這導致上述ClassNotFoundException


解決方案

  1. 如果可以,請嘗試避免Serialization 實現您自己的數據存儲機制。
  2. 如果必須使用Serialization避免雙括號初始化。
  3. 維護聲明而不使用它( test_old方法)。 但是,這是一個臨時解決方案,也是一種不好的做法。 這令人困惑,無法記住。 也是將來錯誤的可能原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM