当前位置: 首页 > 面试题库 >

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

南宫海超
2023-03-14
问题内容

动机:

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

于是我四处询问,偶然发现了Kryo序列化库。根据Kryo的文档,主要功能是在序列化任意Java对象方面非常强大。对象不必实现Serializable,不需要no-
arg构造函数就可以反序列化,而且我甚至不需要在序列化之前就了解对象的结构。完善!

问题:

因此,为了测试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对象outObj,并且该对象的状态将保持不变,因此我仍然可以使用该反序列化的对象进行写入"Hello",该对象将被保存在缓冲区中。

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


问题答案:

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

但是,如果我问,为什么要在世界上序列化一个PrintWriter?那肯定是自找麻烦。Kryo不是“灵丹妙药”,尽管它的默认序列化器可以与 大多数
实用的类一起使用(即使那样,在某些极端情况下也需要编写自定义插件),但是您当然不能指望它能够来处理您能想到的每一个异国情调的东西(并序列化由内部特定于jvm的代码支持的类,就像sun.*绝对符合异国情调一样)。



 类似资料:
  • null 但是,当我以Yar-Client模式提交Spark应用程序时,抛出了以下异常: 线程“main”org.apache.spark.sparkException:Task not serializable at org.apache.spark.util.closureCleaner$.ensureRecleaner.ccala:166)at org.apache.spark.util.c

  • 我正在使用java spark API编写一些测试应用程序。我使用的是一个不扩展可序列化接口的类。因此,为了使应用程序正常工作,我使用kryo序列化器序列化类。但我在调试时观察到的问题是,在反序列化过程中,返回的类对象变为null,并反过来抛出一个null指针异常。这似乎是关闭的问题,事情是错误的,但不确定。因为我是新的这种系列化,我不知道从哪里开始挖掘。 下面是我正在测试的代码: 下面是我正在序

  • 我不明白注册一个类用于kryo序列化是什么意思。为了给出一些背景,这里的链接说 Kryo不支持所有可序列化类型,并且要求您预先注册将在程序中使用的类以获得最佳性能。 还是那句话,我不明白注册一个班级的意义是什么?序列化代码不是静态的吗?就是应用相同的逻辑序列化所有类型的对象。在“高级”中提到将要序列化的类会有什么帮助呢? 谢谢!

  • 我正在尝试使用kryo序列化和反序列化到二进制。我想我已经完成了序列化,但似乎无法反序列化。下面是我正在处理的代码,但最终我想存储一个字节[],然后再次读取它。文档只显示了如何使用文件。

  • 问题内容: 我想将此对象序列化为JSON字符串 并获得如下结果: 我尝试使用 但是相反,我得到了: 人员序列化器: 欢迎任何建议 谢谢,马里奥 问题答案: 为了获得所需的结果,您需要像这样编写串行器: 的结果 将会 完整的代码:

  • 我试图序列化一个对象数组,并将其写入一个名为address.ser的文件,然后从该文件中读取,反序列化对象数组并显示其属性。我尝试一次序列化整个arrayList(读取时在单个会话中反序列化它),也尝试一个接一个地序列化对象数组的每个对象(读取时一个接一个地反序列化它)。问题是,当从address.ser文件读回来时,我只得到最后一个被写入的对象的数据,而不是其他的。 以下是代码片段: 这是用于将