使用Kryo序列化任意Java对象(获取IllegalAccessError) [英] Serializing an arbitrary Java object with Kryo (getting IllegalAccessError)

查看:211
本文介绍了使用Kryo序列化任意Java对象(获取IllegalAccessError)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了帮助进行远程调试(Java),能够请求远程服务器将任意对象发送到我的本地计算机进行检查非常有用。但是,这意味着远程服务器必须能够序列化运行时预先未知的任意Java对象。

To aid in remote debugging (Java), it's useful to be able to request remote servers to send over arbitrary objects to my local machine for inspection. However, this means that the remote server must be able to serialize an arbitrary java object that is not known in advance at runtime.

所以我四处询问,偶然发现了<一个href = https://github.com/EsotericSoftware/kryo rel = nofollow> Kryo序列化库。根据 Kryo的文档,其主要功能是,它在序列化任意Java对象方面非常强大。对象不必实现 Serializable ,不需要no-arg构造函数就可以反序列化,而且我甚至不需要事先了解对象的结构序列化。完美!

So I asked around and stumbled on the Kryo serialization library. From Kryo's documentation, a major feature is that it's very robust at serializing arbitrary java objects. Objects don't have to implement Serializable, don't need no-arg constructors to be deserializable and I don't even need to know anything about the structure of the object prior to serialization. Perfect!

因此要测试Kryo,我尝试查看是否可以序列化,然后反序列化 PrintWriter 对象(即任意对象):

So to test Kryo out, I tried to see if I could serialize and then deserialize a PrintWriter object (i.e. an arbitrary object):

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

Serialization works fine, but upon deserialization the call to kryo.readClassAndObject(input) on line 39 gives the following 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)

I希望我可以对 PrintWriter 对象 outObj 进行序列化和反序列化,并且该对象的状态将保持不变,因此我可以仍然使用反序列化的对象来写 Hello ,它会被保留在缓冲区中。

I had hoped that I could serialize and deserialize the PrintWriter object outObj, and the object's state would remain in tact so I could still use the deserialized object to write "Hello" which would have been held in buffer.

有人知道这是什么吗?

Does anyone know what's going on and how to rectify this error?

推荐答案

我认为,您想要 kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); 避免构造函数调用。
更多信息此处

I think, you want kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); to avoid constructor invocation. More info here.

但是,如果我要问的话,为什么在世界上要序列化 PrintWriter ?那肯定是自找麻烦。
Kryo不是灵丹妙药,而其默认的序列化器可以与 most 类一起使用,这是很实际的(即使那样,在某些情况下,您仍然需要编写自定义插件),您当然不能指望它能够处理您能想到的每一个异国情调的东西(并序列化由内部特定于jvm的代码(例如 sun。* 绝对符合异国情调。)

But, if I may ask, why in the world would you want to serialize a PrintWriter? That is definitely asking for trouble. Kryo is not a "silver bullet", while its default derializers can work with most classes, that are practical (and even then there are always corner cases for which you need to write custom plugins), you can certainly not expect it to be able to handle every single exotic thing you can come up with (and serializing classes backed by internal jvm-specific code, like sun.* definitely qualifies as exotic).

这篇关于使用Kryo序列化任意Java对象(获取IllegalAccessError)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆