ActiveSerializer. Ultra-fast Java Serialization Library
Tags: java
Published: 2020-11-05 18:24:31

[**ActiveSerializer**](https://serializer.activej.io) 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](https://serializer.activej.io/), it claims to be the fastest JVM-based serializer among the existing according to the results of a popular [JVM Serializer benchmark tool](https://github.com/eishay/jvm-serializers/wiki).
﻿
Such performance of **ActiveSerializer** is a result of well-designed architecture and wide use of [**ActiveCodegen**](https://codegen.activej.io/) 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&lt;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!