gpt4 book ai didi

java - 使用 Kryo 序列化任意 Java 对象(获取 IllegalAccessError)

转载 作者:搜寻专家 更新时间:2023-11-01 03:04:22 24 4
gpt4 key购买 nike

动机:

为了帮助远程调试 (Java),能够请求远程服务器将任意对象发送到我的本地机器以供检查是很有用的。然而,这意味着远程服务器必须能够在运行时序列化一个事先不知道的任意 java 对象。

所以我四处询问并偶然发现了 Kryo serialization library .来自 Kryo's documentation ,一个主要特点是它在序列化任意 java 对象时非常健壮。对象不必实现 Serializable,不需要无参数构造函数即可反序列化,我什至不需要在序列化之前了解任何有关对象结构的信息。完美!

问题:

所以为了测试 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();
}
}
}

序列化工作正常,但在反序列化时,第 39 行对 kryo.readClassAndObject(input) 的调用给出以下 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 对象 outObj,并且该对象的状态将保持完整,因此我仍然可以使用反序列化的对象来编写 "Hello" 应该保存在缓冲区中。

有谁知道发生了什么以及如何纠正这个错误?

最佳答案

我认为,您希望 kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); 避免调用构造函数。更多信息 here .

但是,如果我可能会问,您究竟为什么要序列化一个 PrintWriter?那绝对是自找麻烦。Kryo 不是“ Elixir ”,虽然它的默认反序列化器可以与 大多数 类一起工作,这些类很实用(即便如此,总会有一些极端情况需要您编写自定义插件),您可以当然不要指望它能够处理你能想到的每一个奇异的东西(并且序列化由内部 jvm 特定代码支持的类,比如 sun.* 绝对符合奇异的条件)。

关于java - 使用 Kryo 序列化任意 Java 对象(获取 IllegalAccessError),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27731969/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com