Serializing an arbitrary Java object with Kryo (getting IllegalAccessError)

Motivation:

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

So I asked and came across the Kryo serialization library . From the Kryo documentation, the main feature is that it is very robust when serializing arbitrary java objects. Objects don't need to be implemented Serializable

, no-arg constructors need to be deserializable, and I don't even need to know anything about the object structure before serialization. Fine!

Problem:

So, to test the output of Kryo, I tried to see if I could serialize and then deserialize an object PrintWriter

(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 state as a test for later to see if state is restored after serialization and deserialization
        outObj.println("Hello");   // "Hello" held in PrintWriter 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();
        }
    }
}

      

Serialization works fine, but upon deserialization, the call 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 was hoping that I could serialize and deserialize the object PrintWriter

outObj

, and the state of the object would remain tactical, so I could use the deserialized object for writing "Hello"

, which would be buffered.

Does anyone know what is going on and how to fix this error?

+3


source to share


2 answers


I think you want to kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());

avoid calling the constructor. More details here .



But, if I may ask, why in the world would you like to serialize PrintWriter

? It definitely takes some trouble. Kryo is not a silver bullet, while its default derivatives can work with most classes, which are practical (and even then there are always corner cases for which you need to write custom plugins), you certainly cannot expect that it will be able to handle every single exotic thing you can think of (and serialize the classes supported by the internal jvm code, for example, sun.*

definitely qualifies as exotic).

+2


source


This bug is quite common with Kryo. The problem is that the UTF_8 class is not public and hence Kryo is failing. Adding below custom serializer helped me solve the problem. It would be nice to post below serializer along with Cryo as many people struggle with this.

Custom serializer for kryo for UTF-8 and other encodings



This tells Kryo to call my own serializer for all registered Charset classes. Where I just emit the string name.

0


source







All Articles