动机:
为了帮助远程调试 (Java),能够请求远程服务器将任意对象发送到我的本地计算机进行检查非常有用。然而,这意味着远程服务器必须能够序列化运行时事先未知的任意java对象。
于是我四处打听,偶然发现Kryo序列化库. From Kryo 的文档,一个主要特点是它在序列化任意 java 对象方面非常强大。对象不必实现Serializable
,不需要无参数构造函数来反序列化,我什至不需要在序列化之前了解有关对象结构的任何信息。完美的!
Problem:
因此,为了测试 Kryo,我尝试看看是否可以序列化然后反序列化PrintWriter
对象(即任意对象):
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import java.io.*;
public class SerializationTest {
private static final String ioFileName = "someIO.bin";
public static void main(String[] args) {
// Create a PrintWriter object that I will later attempt to serialize
PrintWriter outObj = null;
try {
outObj = new PrintWriter("textfile.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// Change the PrintWriter's state as a test for later to see if state is restored after serialization and deserialization
outObj.println("Hello"); // "Hello" held in PrintWriter's buffer
Kryo kryo = new Kryo(); // Initialize Kryo serialization
writeObj(kryo, outObj); // Save PrintWriter object to file with "Hello" still in its buffer
// Read the previously saved Printwriter object (still with "Hello" in its buffer)
PrintWriter inObj = (PrintWriter) readObj(kryo);
inObj.close(); // commit "Hello" to disk (using deserialized object)
outObj.close(); // commit "Hello" to disk (using original object)
System.out.println(inObj);
}
public static Object readObj(Kryo kryo) {
Object obj = null;
try {
Input input = new Input(new FileInputStream(ioFileName));
obj = kryo.readClassAndObject(input); // ERROR HERE!!
input.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return obj;
}
public static void writeObj(Kryo kryo, Object obj) {
try {
Output output = new Output(new FileOutputStream(ioFileName));
kryo.writeClassAndObject(output, obj);
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
序列化工作正常,但反序列化时调用kryo.readClassAndObject(input)
第 39 行给出以下内容IllegalAccessError
:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class sun.nio.cs.UTF_8 from class sun.nio.cs.UTF_8ConstructorAccess
at sun.nio.cs.UTF_8ConstructorAccess.newInstance(Unknown Source)
at com.esotericsoftware.kryo.Kryo$DefaultInstantiatorStrategy$1.newInstance(Kryo.java:1234)
at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:1086)
at com.esotericsoftware.kryo.serializers.FieldSerializer.create(FieldSerializer.java:547)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:523)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:704)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:106)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:704)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:106)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:704)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:106)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:704)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:106)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528)
at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:786)
at SerializationTest.readObj(SerializationTest.java:39)
at SerializationTest.main(SerializationTest.java:27)
我曾希望能够序列化和反序列化PrintWriter
object outObj
,并且对象的状态将保持不变,因此我仍然可以使用反序列化的对象来编写"Hello"
它将被保存在缓冲区中。
有谁知道发生了什么事以及如何纠正此错误?
我想,你想要kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
以避免构造函数调用。
更多信息here.
但是,如果我可以问的话,你到底为什么要序列化一个PrintWriter
?这绝对是自找麻烦。
Kryo 不是“灵丹妙药”,但它的默认反序列化器可以与most类,这是实用的(即使如此,总是存在需要编写自定义插件的极端情况),您当然不能指望它能够处理您能想到的每一个奇异的东西(以及序列化由内部 jvm 特定代码,例如sun.*
绝对有资格成为异国情调)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)