反序列化序列化对象时出现 ClassNotFound 异常
ClassNotFound Exception when deserializing serialized object
我正在尝试序列化和反序列化一个对象。此对象可以包含对其他对象以及 ArrayList 和 HashMap 的引用。
当我尝试执行我的代码时,序列化工作正常,但反序列化没有。它会导致以下异常:
Exception in thread "main" java.lang.ClassNotFoundException: experiment.Experiment
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
我有主要的class,实验,如下:
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
之类的名称,它似乎可以正常工作。
对象class如下:
// 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 的内容,但是当我尝试这样做时,它没有任何区别。
您缺少 class 顶部的包裹声明,它应该是:
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"));
}
}
情况
What is Double Brace initialization in Java?
new VariableMap<String, String>() {{
put("Name", "Furze");
}}
创建一个匿名内部 class(class VariableMap
的子class)并创建它的对象。
class和对象都是在同一个地方创建的。
自 all subtypes of a serializable class are themselves serializable 以来仍然是 Serializable
。
问题
当你评论它时,class定义本身消失 .
这导致上述 ClassNotFoundException
。
解决方案
- 如果可以,尽量避免
Serialization
。实现自己的数据存储机制。
- 如果必须使用
Serialization
,请避免双括号初始化。
- 保持声明而不使用它(
test_old
方式)。然而,这是一个临时解决方案和不好的做法。这是令人困惑且无法记住的。也是未来错误的可能原因。
我正在尝试序列化和反序列化一个对象。此对象可以包含对其他对象以及 ArrayList 和 HashMap 的引用。
当我尝试执行我的代码时,序列化工作正常,但反序列化没有。它会导致以下异常:
Exception in thread "main" java.lang.ClassNotFoundException: experiment.Experiment
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
我有主要的class,实验,如下:
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
之类的名称,它似乎可以正常工作。
对象class如下:
// 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 的内容,但是当我尝试这样做时,它没有任何区别。
您缺少 class 顶部的包裹声明,它应该是:
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"));
}
}
情况
What is Double Brace initialization in Java?
new VariableMap<String, String>() {{
put("Name", "Furze");
}}
创建一个匿名内部 class(class VariableMap
的子class)并创建它的对象。
class和对象都是在同一个地方创建的。
自 all subtypes of a serializable class are themselves serializable 以来仍然是 Serializable
。
问题
当你评论它时,class定义本身消失 .
这导致上述 ClassNotFoundException
。
解决方案
- 如果可以,尽量避免
Serialization
。实现自己的数据存储机制。 - 如果必须使用
Serialization
,请避免双括号初始化。 - 保持声明而不使用它(
test_old
方式)。然而,这是一个临时解决方案和不好的做法。这是令人困惑且无法记住的。也是未来错误的可能原因。