ActiveSerializer. Ultra-fast Java Serialization Library
valerialistratova
Posted on November 5, 2020
ActiveSerializer is a modern bytecode generator of extremely fast and space-efficient serializers for data transferring. It's core features are ultimate performance and streamlined programming model. ActiveSerializer doesn't create redundant layers of data transfer objects and works straight with Java classes with the help of annotations.
ActiveSerializer is a really powerful tool:
- Works directly with Java classes via annotations. No additional layers of intermediate DTO classes.
- Implemented using runtime bytecode generation to be compatible with dynamically created classes.
- Stable binary format with backward binary compatibility.
- Support of the scheme evolution: changeable versions, added or removed fields, etc.
- Can be easily extended - you can write your own plugins for specific classes.
- Includes special hints for even more efficient code: String formats, nullable, varlen, etc.
- Provides little endian format for JVM intrinsics.
- Support of unsafe mode for the best performance.
- Cyclic references of any complexity.
- UTF-8, UTF-16 and ISO8859-1 encoding.
- Compatible even with complex collections, generics and nullable values.
Performance
According to the ActiveSerializer website, it claims to be the fastest JVM-based serializer among the existing according to the results of a popular JVM Serializer benchmark tool.
Such performance of ActiveSerializer is a result of well-designed architecture and wide use of ActiveCodegen library for dynamic runtime code generation. Let's test ActiveSerializer out!
Simple Object Serialization
Let's create a serializable POJO using @Serialize
and @Deserialze
annotations:
public static class Person {
//use @Deserialize annotation with property name in constructor
public Person(@Deserialize("age") int age, @Deserialize("name") String name) {
this.age = age;
this.name = name;
}
// Use @Serialize annotation with order number on properties or their getters.
// The name of the property must be the same as declared in @Deserialize annotation.
// order number provides compatibility.
@Serialize(order = 0)
public int age;
@Serialize(order = 1)
public final String name;
private String surname;
@Serialize(order = 2)
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
This is enough to make a class serializable. Now let's create a Person
instance and a BinarySerializer
(represents a serializer that will encode and decode <Person>
values to byte arrays). So we will also need a byte array to store the result of the serialization.
Person john = new Person(34, "John");
john.setSurname("Smith");
byte[] buffer = new byte[200];
BinarySerializer<Person> serializer = SerializerBuilder.create(getSystemClassLoader())
.build(Person.class);
In order to encode and decode our instance, simply use encode
and decode
methods:
serializer.encode(buffer, 0, john);
Person johnCopy = serializer.decode(buffer, 0);
Let's move on to something a little bit more complicated.
Generics and Interfaces Serialization
ActiveSerializer allows to work with interfaces and generics with a simple DSL. First, let's create a Skill
class:
public static class Skill<K, V> {
private K key;
private V value;
public Skill(@Deserialize("key") K key, @Deserialize("value") V value) {
this.key = key;
this.value = value;
}
@Serialize(order = 0)
public K getKey() {
return key;
}
@Serialize(order = 1)
public V getValue() {
return value;
}
}
Next, we'll create a Person
interface. It will have a method that returns a list of skills:
public interface Person<K, V> {
@Serialize(order = 0)
List<Skill<K, V>> getSkills();
}
Now we need to create a class that will implement Person
interface. Let it be a Developer
:
public static class Developer implements Person<Integer, String> {
private List<Skill<Integer, String>> list;
@Serialize(order = 0)
@Override
public List<Skill<Integer, String>> getSkills() {
return list;
}
public void setSkills(List<Skill<Integer, String>> list) {
this.list = list;
}
}
Now create an instance of Developer
, BinarySerializer<Developer>
, and a byte array:
Developer developer = new Developer();
developer.setSkills(Arrays.asList(
new Skill<>(1, "Java"),
new Skill<>(2, "ActiveSerializer")));
byte[] buffer = new byte[200];
BinarySerializer<Developer> serializer = SerializerBuilder.create(getSystemClassLoader())
.build(Developer.class);
Now you can serialize and deserialize Developer
instance with encode and decode methods:
serializer.encode(buffer, 0, developer);
Developer developer2 = serializer.decode(buffer, 0);
Have any questions? You're welcome in the comment section!
Posted on November 5, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.