Kryo
Serialization Library
Kryo
Overview
Kryo is a fast and efficient binary object graph serialization framework for Java. The goals of the project are high speed, low size, and an easy to use API. The project is useful any time objects need to be persisted, whether to a file, database, or over the network.
Details
Kryo provides significantly better performance compared to standard Java serialization and produces smaller serialized data. It supports automatic deep and shallow object copying and properly handles multiple references and circular references.
Key Features
- High Performance: Significantly faster than standard Java serialization
- Compact Output: Smaller serialized data size
- Automatic Serialization: Provides default serializers for primitives, lists, maps, enums, etc.
- Custom Serializers: Define custom serialization processes for specific classes
- Complex Object Graph Support: Properly handles circular references and nested objects
- Not Thread-Safe: Designed for high performance, not thread-safe by design
- Pluggable Architecture: Flexible integration of different serializers
Common Use Cases
- Big Data Processing: Data serialization between distributed nodes in frameworks like Apache Spark
- Network Communication: Applications requiring fast data transmission
- Caching: Fast object serialization in caching solutions
- Persistent Storage: Applications storing large amounts of data efficiently
Pros and Cons
Pros
- High Speed: 50%+ faster than standard Java serialization
- Small Payload Size: 61% size reduction without compression, 80% with compression
- Flexible Serialization: Can serialize classes not implementing
java.io.Serializable - Mature Implementation: Used in production by Twitter, Groupon, Yahoo, Hive, Storm, and more
- Simple API: Intuitive and easy-to-use API design
- Object Copy Feature: Easy implementation of deep and shallow copy
Cons
- Lack of Version Compatibility: Serialization compatibility not guaranteed between releases
- Not Suitable for Long-term Storage: Not recommended for long-term data storage
- Not Thread-Safe: Requires proper synchronization or pooling in multi-threaded environments
- Registration Required: Pre-registration of classes needed for best performance
- No-arg Constructor Required: No-arg constructor needed for optimal performance
Reference Pages
Code Examples
Basic Usage
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import java.io.*;
public class KryoExample {
public static void main(String[] args) throws Exception {
Kryo kryo = new Kryo();
// Register classes for better performance
kryo.register(Person.class);
Person person = new Person("John Doe", 30);
// Serialize to file
Output output = new Output(new FileOutputStream("person.bin"));
kryo.writeObject(output, person);
output.close();
// Deserialize from file
Input input = new Input(new FileInputStream("person.bin"));
Person restoredPerson = kryo.readObject(input, Person.class);
input.close();
System.out.println(restoredPerson);
}
static class Person {
String name;
int age;
// Kryo requires no-arg constructor
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
}
Serialization with Unknown Class
// Write with class information
kryo.writeClassAndObject(output, someObject);
// Read with class information
Object object = kryo.readClassAndObject(input);
// Handle nullable objects
kryo.writeObjectOrNull(output, maybeNullObject);
SomeClass object = kryo.readObjectOrNull(input, SomeClass.class);
Custom Serializer Implementation
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import java.time.LocalDateTime;
public class LocalDateTimeSerializer extends Serializer<LocalDateTime> {
@Override
public void write(Kryo kryo, Output output, LocalDateTime dateTime) {
output.writeLong(dateTime.toEpochSecond(java.time.ZoneOffset.UTC));
output.writeInt(dateTime.getNano());
}
@Override
public LocalDateTime read(Kryo kryo, Input input, Class<LocalDateTime> type) {
long epochSecond = input.readLong();
int nano = input.readInt();
return LocalDateTime.ofEpochSecond(epochSecond, nano, java.time.ZoneOffset.UTC);
}
}
// Usage
Kryo kryo = new Kryo();
kryo.register(LocalDateTime.class, new LocalDateTimeSerializer());
Thread-Safe Usage (Pooling)
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.util.Pool;
public class KryoPool {
private static final Pool<Kryo> kryoPool = new Pool<Kryo>(true, false, 8) {
protected Kryo create() {
Kryo kryo = new Kryo();
// Register required classes
kryo.register(Person.class);
kryo.register(Address.class);
// Other configurations
return kryo;
}
};
public static byte[] serialize(Object object) {
Kryo kryo = kryoPool.obtain();
try (Output output = new Output(1024, -1)) {
kryo.writeClassAndObject(output, object);
return output.toBytes();
} finally {
kryoPool.free(kryo);
}
}
public static Object deserialize(byte[] bytes) {
Kryo kryo = kryoPool.obtain();
try (Input input = new Input(bytes)) {
return kryo.readClassAndObject(input);
} finally {
kryoPool.free(kryo);
}
}
}
Reference Handling
Kryo kryo = new Kryo();
// Enable references (default) - handles circular references but slower
kryo.setReferences(true);
// Disable references - faster but stack overflow with circular references
kryo.setReferences(false);
// Disable references for specific serializer only
kryo.register(SomeClass.class, new FieldSerializer(kryo, SomeClass.class) {{
setReferences(false);
}});
Object Copying
Kryo kryo = new Kryo();
// Deep copy
Person originalPerson = new Person("Jane Smith", 25);
Person deepCopy = kryo.copy(originalPerson);
// Shallow copy
Person shallowCopy = kryo.copyShallow(originalPerson);
// Copy configuration
kryo.setCopyReferences(true); // Preserve references
kryo.setCopyTransient(false); // Don't copy transient fields
Maven Dependency
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>5.6.2</version>
</dependency>
Gradle Dependency
implementation 'com.esotericsoftware:kryo:5.6.2'