Apache Fory™ Java provides blazingly-fast serialization for the Java ecosystem, delivering up to 170x performance improvement over traditional frameworks through JIT compilation and zero-copy techniques.
writeObject/readObject/writeReplace/readResolve/readObjectNoData/Externalizable| Topic | Description | Source Doc Link | Website Doc Link |
|---|---|---|---|
| Java Serialization | Comprehensive usage guide | java_serialization_guide.md | Java Serialization Guide |
| GraalVM Native Image | Native image support | graalvm_guide.md | GraalVM Guide |
| Java Serialization Spec | Protocol specification | java_serialization_spec.md | Java Serialization Spec |
| Module | Description | Maven Artifact |
|---|---|---|
| fory-core | Core serialization engine | org.apache.fory:fory-core |
| fory-format | Row format and Apache Arrow support | org.apache.fory:fory-format |
| fory-simd | SIMD-accelerated array compression | org.apache.fory:fory-simd |
| fory-extensions | Protobuf support and meta compression | org.apache.fory:fory-extensions |
| fory-test-core | Testing utilities and data generators | org.apache.fory:fory-test-core |
<dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-core</artifactId> <version>0.13.1</version> </dependency> <!-- Optional: Row format support --> <dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-format</artifactId> <version>0.13.1</version> </dependency> <!-- Optional: Serializers for Protobuf data --> <dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-extensions</artifactId> <version>0.13.1</version> </dependency> <!-- Optional: SIMD acceleration (Java 16+) --> <dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-simd</artifactId> <version>0.13.1</version> </dependency>
dependencies { implementation 'org.apache.fory:fory-core:0.13.1' // Optional modules implementation 'org.apache.fory:fory-format:0.13.1' implementation 'org.apache.fory:fory-simd:0.13.1' implementation 'org.apache.fory:fory-extensions:0.13.1' }
Create a Fory instance, register your classes, and start serializing objects. Remember to reuse the Fory instance for optimal performance:
import org.apache.fory.*; import org.apache.fory.config.*; // Create Fory instance (should be reused) Fory fory = Fory.builder() .requireClassRegistration(true) .build(); // Register your classes fory.register(MyClass.class); // Serialize MyClass object = new MyClass(); byte[] bytes = fory.serialize(object); // Deserialize MyClass result = (MyClass) fory.deserialize(bytes);
For multi-threaded environments, use ThreadSafeFory which maintains a pool of Fory instances:
import org.apache.fory.*; import org.apache.fory.config.*; // Create thread-safe Fory instance private static final ThreadSafeFory fory = Fory.builder().buildThreadSafeFory(); static { fory.register(MyClass.class); } // Use in multiple threads byte[] bytes = fory.serialize(object); Object result = fory.deserialize(bytes);
Enable schema compatibility mode to support forward and backward compatibility when your class definitions change over time:
// Enable forward/backward compatibility Fory fory = Fory.builder() .withCompatibleMode(CompatibleMode.COMPATIBLE) .build(); // Serialization and deserialization can use different class versions // New fields will be ignored, missing fields will use default values
Enable reference tracking to properly handle shared references and circular dependencies in your object graphs:
// Enable reference tracking for circular/shared references Fory fory = Fory.builder() .withRefTracking(true) .build(); // Serialize complex object graphs GraphNode node = new GraphNode(); node.next = node; // Circular reference byte[] bytes = fory.serialize(node);
Use XLANG mode to serialize data that can be deserialized by other languages (Python, Rust, Go, etc.):
// Use XLANG mode for cross-language compatibility Fory fory = Fory.builder() .withLanguage(Language.XLANG) .withRefTracking(true) .build(); // Register with cross-language type id/name fory.register(MyClass.class, 1); // fory.register(MyClass.class, "com.example.MyClass"); // Bytes can be deserialized by Python, Go, etc. byte[] bytes = fory.serialize(object);
Configure Fory with various options to suit your specific use case:
Fory fory = Fory.builder() // Language mode: JAVA (fastest) or XLANG (cross-language) .withLanguage(Language.JAVA) // Reference tracking for circular/shared references .withRefTracking(true) // Schema evolution mode .withCompatibleMode(CompatibleMode.COMPATIBLE) // Compression options .withIntCompressed(true) .withLongCompressed(true) .withStringCompressed(false) // Security options .requireClassRegistration(true) .withMaxDepth(50) // Performance options .withCodeGen(true) .withAsyncCompilation(true) // Class loader .withClassLoader(classLoader) .build();
See Java Serialization Guide for detailed configuration options.
Fory fully supports JDK serialization APIs with 100x better performance. You can use standard Java serialization methods and Fory will handle them automatically:
public class MyClass implements Serializable { private void writeObject(ObjectOutputStream out) throws IOException { // Custom serialization logic } private void readObject(ObjectInputStream in) throws IOException { // Custom deserialization logic } private Object writeReplace() { // Return replacement object } private Object readResolve() { // Return resolved object } }
Enable reference tracking during deep copy to preserve object identity and handle circular references correctly:
Fory fory = Fory.builder() .withLanguage(Language.JAVA) .withRefCopy(true) .build(); MyClass original = new MyClass(); MyClass copy = fory.copy(original);
Fory provides a cache-friendly binary row format optimized for random access and analytics:
import org.apache.fory.format.encoder.*; import org.apache.fory.format.row.*; public class Bar { String f1; List<Long> f2; } public class Foo { int f1; List<Integer> f2; Map<String, Integer> f3; List<Bar> f4; } // Create row encoder RowEncoder<Foo> encoder = Encoders.bean(Foo.class); // Serialize to row format Foo foo = new Foo(); foo.f1 = 10; foo.f2 = IntStream.range(0, 1000).boxed().collect(Collectors.toList()); BinaryRow binaryRow = encoder.toRow(foo); // Zero-copy random access to fields BinaryArray f2Array = binaryRow.getArray(1); // Access f2 without deserializing entire object BinaryArray f4Array = binaryRow.getArray(3); // Access f4 // Zero-copy access nested fields BinaryRow barStruct = f4Array.getStruct(10); // Get 11th element long value = barStruct.getArray(1).getInt64(5); // Access nested field // Partial deserialization RowEncoder<Bar> barEncoder = Encoders.bean(Bar.class); Bar partialBar = barEncoder.fromRow(barStruct); // Deserialize only one Bar object // Full deserialization Foo deserializedFoo = encoder.fromRow(binaryRow);
See Row Format Guide for more details.
Use SIMD-accelerated compression for integer and long arrays to reduce memory usage when array elements have small values:
import org.apache.fory.simd.*; Fory fory = Fory.builder() .withIntArrayCompressed(true) .withLongArrayCompressed(true) .build(); // Register compressed array serializers CompressedArraySerializers.registerSerializers(fory); // Arrays with small values are automatically compressed int[] data = new int[1000000]; byte[] bytes = fory.serialize(data);
Fory supports GraalVM native image through code generation, eliminating the need for reflection configuration. Build your native image as follows:
# Generate serializers at build time mvn package -Pnative # Run native image ./target/my-app
See GraalVM Guide for details.
All commands must be executed in the java directory:
# Build mvn -T16 clean package # Run tests mvn -T16 test # Install locally mvn -T16 install -DskipTests # Code formatting mvn -T16 spotless:apply # Code style check mvn -T16 checkstyle:check
# Run all tests mvn -T16 test # Run specific test mvn -T16 test -Dtest=MyTestClass#testMethod # Run with specific JDK JAVA_HOME=/path/to/jdk mvn test
# Format code mvn -T16 spotless:apply # Check code style mvn -T16 checkstyle:check
Language.JAVA instead of Language.XLANG when cross-language support isn't needed. Java mode reduces type metadata overhead and supports more Java-native types not available in xlang modeSee CONTRIBUTING.md for development guidelines.
Licensed under the Apache License 2.0.