title: Java Serialization Guide sidebar_position: 0 id: serialization_index license: | Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Apache Fory™ Java provides high-performance binary object serialization, a cross-language random-access row format, and JSON serialization for Java. Binary serialization supports xlang mode for cross-language payloads and native mode for Java-only object graphs. Fory JSON is a high-performance JSON serialization framework for Java applications.
| Format | Use it when | Artifact | Start here |
|---|---|---|---|
| Binary Object Serialization | You need compact object graphs in Java native mode or across supported languages | org.apache.fory:fory-core | Basic Serialization |
| Row Format | You need zero-copy random access, partial reads, or Arrow integration | org.apache.fory:fory-format | Row Format |
| Fory JSON | You need high-throughput standard JSON for Java applications | org.apache.fory:fory-json | JSON Support |
Externalizable in native mode.Add fory-core for binary object serialization. Keep all Fory modules in one application on the same version.
<!-- Binary object serialization --> <dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-core</artifactId> <version>1.5.0</version> </dependency>
// Binary object serialization implementation("org.apache.fory:fory-core:1.5.0")
On JDK 25 and later, open java.lang.invoke to Fory. Use ALL-UNNAMED when Fory is on the classpath:
--add-opens=java.base/java.lang.invoke=ALL-UNNAMED
Use the Fory core module name when Fory is on the module path:
--add-opens=java.base/java.lang.invoke=org.apache.fory.core
Note that Fory creation is not cheap, the Fory instances should be reused between serializations instead of creating it every time. You should keep Fory as a static global variable, or instance variable of some singleton object or limited objects.
import java.util.List; import java.util.Arrays; import org.apache.fory.*; import org.apache.fory.config.*; public class Example { public static void main(String[] args) { SomeClass object = new SomeClass(); // Note that Fory instances should be reused between // multiple serializations of different objects. Fory fory = Fory.builder() .withXlang(true) .requireClassRegistration(true) .build(); // Registering types can reduce class name serialization overhead, but not mandatory. // If class registration enabled, all custom types must be registered. // Registration order must be consistent if id is not specified fory.register(SomeClass.class); byte[] bytes = fory.serialize(object); System.out.println(fory.deserialize(bytes)); } }
import org.apache.fory.*; import org.apache.fory.config.*; public class Example { public static void main(String[] args) { SomeClass object = new SomeClass(); ThreadSafeFory fory = Fory.builder() .withXlang(true) .buildThreadSafeFory(); fory.register(SomeClass.class, 1); byte[] bytes = fory.serialize(object); System.out.println(fory.deserialize(bytes)); } }
import org.apache.fory.*; import org.apache.fory.config.*; public class Example { private static final ThreadSafeFory fory = Fory.builder() .withXlang(true) .buildThreadSafeFory(); static { fory.register(SomeClass.class, 1); } public static void main(String[] args) { SomeClass object = new SomeClass(); byte[] bytes = fory.serialize(object); System.out.println(fory.deserialize(bytes)); } }
Use xlang mode for cross-language payloads and schemas shared with non-Java implementations. It is the default Java wire mode, and Java examples that use it set .withXlang(true) explicitly so the mode choice is visible.
Use native mode for Java-only traffic. Native mode is selected with .withXlang(false) and owns Java-specific object behavior such as JDK serialization hooks, Externalizable, dynamic object graphs, object copy, and Java native-mode zero-copy buffers. It is optimized for the JVM type system and supports a broader Java object surface than xlang mode. Compatible mode is enabled by default. Set .withCompatible(false) only when every reader and writer uses the same class schema and you want faster serialization and smaller size. If you are replacing JDK serialization, Kryo, FST, Hessian, or Java-only Protocol Buffers payloads, start with native mode.
See Native Serialization for Java-only serialization details and Xlang Serialization for Java xlang registration and interoperability rules.
Fory provides two thread-safe Fory instance styles:
buildThreadSafeForyThis is the default choice. It uses a fixed-size shared ThreadPoolFory sized to 4 * availableProcessors() and is the preferred instance form for virtual-thread workloads:
ThreadSafeFory fory = Fory.builder() .withXlang(true) .withRefTracking(false) .withAsyncCompilation(true) .buildThreadSafeFory();
See more details in Virtual Threads.
Use buildThreadLocalFory() only when you explicitly want one Fory instance per long-lived platform thread, or when you want to pin that choice regardless of JDK version:
ThreadSafeFory fory = Fory.builder() .withXlang(true) .buildThreadLocalFory(); fory.register(SomeClass.class, 1); byte[] bytes = fory.serialize(object); System.out.println(fory.deserialize(bytes));
buildThreadSafeForyPoolUse buildThreadSafeForyPool(poolSize) when you want to set that fixed shared pool size explicitly. It eagerly creates poolSize Fory instances, keeps them in shared fixed slots, and then lets any caller borrow one through a thread-agnostic fast path. Calls only block when every pooled instance is already in use; the pool does not key cached instances by thread identity:
ThreadSafeFory fory = Fory.builder() .withXlang(true) .withRefTracking(false) .withAsyncCompilation(true) .buildThreadSafeForyPool(poolSize);
// Single-thread Fory Fory fory = Fory.builder() .withXlang(true) .withRefTracking(false) .withAsyncCompilation(true) .build(); // Thread-safe Fory (thread-safe Fory backed by a pool of Fory instances) ThreadSafeFory fory = Fory.builder() .withXlang(true) .withRefTracking(false) .withAsyncCompilation(true) .buildThreadSafeFory(); // Explicit thread-local Fory instance ThreadSafeFory threadLocalFory = Fory.builder() .withXlang(true) .buildThreadLocalFory();
Fory row format is a separate cache-friendly binary format for random access, partial reads, and analytics workloads.
<dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-format</artifactId> <version>1.5.0</version> </dependency>
implementation("org.apache.fory:fory-format:1.5.0")
See Row Format for encoding, typed field access, partial deserialization, nested values, and Arrow integration.
Fory JSON is a thread-safe JSON serialization framework for Java, extensively optimized for maximum performance across JSON encoding, decoding, and Java object mapping.
fory-json includes fory-core transitively. Keep both modules on the same version when another dependency also brings fory-core into the application.
<dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-json</artifactId> <version>1.5.0</version> </dependency>
implementation("org.apache.fory:fory-json:1.5.0")
On JDK 25 and later, use the same java.lang.invoke module open described in the binary serialization installation section.
ForyJson is immutable and thread-safe after construction. Reuse one instance across threads:
import org.apache.fory.json.ForyJson; public final class JsonExample { private static final ForyJson JSON = ForyJson.builder().build(); public static final class User { public long id; public String name; public User() {} public User(long id, String name) { this.id = id; this.name = name; } } public static void main(String[] args) { User input = new User(7, "Alice"); String text = JSON.toJson(input); User fromText = JSON.fromJson(text, User.class); byte[] utf8 = JSON.toJsonBytes(input); User fromUtf8 = JSON.fromJson(utf8, User.class); System.out.println(fromText.name + " / " + fromUtf8.name); } }
See JSON Support for supported types, annotations, custom codecs, security controls, and platform setup.
fory-core and fory-json support Java 8 and later; Java records require Java 17 or later.fory-format targets Java 11 and later and is not supported on Android.fory-core and fory-json run on standard JDKs, GraalVM native images, and Android API level 26 and later.@ForyField, @Ignore, integer encoding annotations, serializeEnumByName, and @ForyEnumId@ForyStruct