blob: fa14f6bd244d14ceae2ffe061692461e274ddd83 [file] [view]
---
title: Static Generated Serializers
sidebar_position: 8
id: static_generated_serializers
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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---
Static generated serializers are Java serializers generated by javac during your application build.
They are useful when runtime code generation is disabled or unavailable.
Use them when:
- you run on Android.
- you run an ordinary JVM with `ForyBuilder#withCodegen(false)` and want generated serializers.
- your Android model classes use Fory type-use annotations such as `@Ref`, `@UInt8Type`, or
`@Float16Type`.
For GraalVM native images, follow [GraalVM Support](graalvm-support.md) instead.
## Install The Annotation Processor
Add `fory-annotation-processor` to the annotation processor path of the module that compiles your
serializable classes:
```xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.apache.fory</groupId>
<artifactId>fory-annotation-processor</artifactId>
<version>${fory.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
```
The generated serializers depend on `fory-core` at runtime. Applications opt in by adding the
annotation processor; `fory-core` does not depend on it.
## Annotate Classes
Annotate each serializable class with `@ForyStruct`:
```java
import org.apache.fory.annotation.ForyStruct;
@ForyStruct
public class Order {
public long id;
public String note;
public Order() {}
}
```
The processor generates serializer classes in the same Java package as the annotated class. For
`Order`, the generated classes are:
- `Order_ForySerializer` for xlang mode.
- `Order_ForyNativeSerializer` for Java native mode.
For a static nested type such as `Outer.Inner`, the generated top-level classes are
`Outer_Inner_ForySerializer` and `Outer_Inner_ForyNativeSerializer`.
## Field Debug Tracing
Add `@ForyDebug` next to `@ForyStruct` when you need generated serializers to include field-level
debug tracing hooks. The generated code prints those traces only when
`ENABLE_FORY_DEBUG_OUTPUT=1`.
```java
import org.apache.fory.annotation.ForyDebug;
import org.apache.fory.annotation.ForyStruct;
@ForyStruct
@ForyDebug
public class DebugOrder {
public long id;
public String note;
public DebugOrder() {}
}
```
## Runtime Use
Fory uses static generated serializers when they are available on:
- Android.
- ordinary JVMs with `ForyBuilder#withCodegen(false)`.
- compatible-mode reads when the target struct has a generated serializer.
On an ordinary JVM with `codegen=true`, Fory continues to prefer runtime-generated serializers.
Fory resolves generated serializers from the registered target class name. Application code
should not reference generated serializer classes directly.
## Field Access Rules
Generated serializers must be able to access serialized fields or their accessors at compile time.
- Public, protected, and package-private fields can be accessed directly when Java package access
allows same-package generated serializers to use them.
- Private serialized fields must have accessible non-private getter and setter methods, or be
excluded with `transient` or Fory `@Ignore`.
- Public, protected, and package-private getter/setter methods are accepted when they are accessible
from the generated serializer package.
- Final fields are not supported for normal mutable classes because generated read and copy methods
must assign fields. Use records for constructor-based immutable values.
For records, generated serializers use public record accessors and construct values through the
canonical record constructor. Ignored record components are skipped by serialization and copy, and
their constructor arguments use Java default values during generated read/copy.
## Type-Use Annotations On Android
On Android, static generated serializers are required when a class uses Fory type-use annotations on
nested types:
```java
import java.util.List;
import org.apache.fory.annotation.ForyStruct;
import org.apache.fory.annotation.UInt8Type;
@ForyStruct
public class ImageBlock {
public List<@UInt8Type Integer> pixels;
}
```
Without the generated serializer metadata, Android may not expose enough nested type information for
Fory to preserve annotations such as `@Ref`, `@Int8Type`, `@UInt8Type`, `@Float16Type`, or
`@BFloat16Type`.
The annotation processor emits generated consumer R8/ProGuard rules under `META-INF/proguard/` for
the exact serializer constructors used by Fory. Android applications should not add broad generated
serializer keep rules by hand.
## Compatible Reads
Static generated serializers support both normal serialization and compatible-mode reads. Compatible
reads match remote fields to local fields, skip fields that no longer exist locally, and keep Java
default values for fields that are missing from the remote payload.