This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git

commit 675325d7306e27be30d089bb09a07760801abc6b
Author: chaokunyang <[email protected]>
AuthorDate: Wed May 13 04:18:07 2026 +0000

    🔄 synced local 'docs/guide/' with remote 'docs/guide/'
---
 docs/guide/java/android-support.md              | 184 +++++++++++-------------
 docs/guide/java/configuration.md                |   3 +-
 docs/guide/java/index.md                        |   1 +
 docs/guide/java/schema-evolution.md             |  16 ++-
 docs/guide/java/static-generated-serializers.md | 138 ++++++++++++++++++
 5 files changed, 236 insertions(+), 106 deletions(-)

diff --git a/docs/guide/java/android-support.md 
b/docs/guide/java/android-support.md
index c8f316313a..c3b68088ef 100644
--- a/docs/guide/java/android-support.md
+++ b/docs/guide/java/android-support.md
@@ -19,136 +19,116 @@ license: |
   limitations under the License.
 ---
 
-## Android Support
+## Android Runtime
 
-This page documents the Java `fory-core` Android runtime surface.
+Fory Java supports Android 8.0+ (API level 26+) through the regular 
`fory-core` artifact. No separate
+Android artifact is required for core object serialization.
 
-The target runtime is Android 8.0+ (API level 26+) in the existing `fory-core` 
artifact. Android
-support is selected at runtime by `org.apache.fory.platform.AndroidSupport`; 
no separate Android
-artifact is required for core object serialization.
+Use core object serialization on Android:
 
-`java/fory-format` is not part of the Android support surface. Row-format 
direct-memory APIs remain
-JVM-only.
-
-Android does not allow Fory runtime serialization paths to rely on 
`sun.misc.Unsafe`, private-field
-`MethodHandle` access, dynamic bytecode loading, or `LambdaMetafactory`. 
Android-specific code paths
-must use public platform APIs or fail with targeted exceptions when Android 
cannot preserve JVM
-semantics.
-
-## Target Support Surface
+- `Fory#serialize(Object)` and `Fory#deserialize(byte[])`.
+- `BaseFory#deserialize(ByteBuffer)` for heap, direct, and read-only 
`ByteBuffer` inputs.
+- Stream, channel, and out-of-band buffer APIs through byte-array, 
heap-buffer, or `ByteBuffer` copy
+  paths.
+- Java collections/maps and xlang collections/maps.
 
-The Android target includes:
+`java/fory-format` row-format APIs are JVM-only and are not supported on 
Android.
 
-- `Fory#serialize(Object)` returning `byte[]`.
-- `Fory#deserialize(byte[])`.
-- `BaseFory#deserialize(ByteBuffer)` through copy into a Fory-owned heap 
`MemoryBuffer`.
-- Stream, channel, and out-of-band buffer APIs through safe heap, byte-array, 
or `ByteBuffer` copy
-  paths.
-- Interpreter object serializers with reflection-backed field access.
-- Normal Java collections/maps and xlang collection/map protocols.
+## Runtime Codegen
 
-Unsupported or removed behavior:
+Runtime serializer code generation is disabled on Android. If 
`withCodegen(true)` is set, Fory keeps
+Android serialization on the non-codegen path and logs a warning.
 
-- Runtime serializer code generation and async compilation.
-- Lambda and `SerializedLambda` serialization. Registration still succeeds for 
stable internal type
-  ids, but write/read/copy operations throw an unsupported exception.
-- Native-address serialize/deserialize APIs and native-address `MemoryBuffer` 
wrapping.
-- Raw-address direct `ByteBuffer` zero-copy.
-- Raw unsafe `MemoryBuffer` copy APIs remain JVM-only and throw on Android.
-- `java/fory-format` row-format APIs, including direct-memory binary row copy 
paths.
-- Field type-use annotation metadata that depends on 
`Field#getAnnotatedType()` on the JVM.
-  Android API 26 field metadata uses generic field types and field annotations 
exposed by Android
-  reflection.
-- Object deserialization that cannot be completed through reflection.
-
-## Codegen
-
-`ForyBuilder` stores the codegen request as a nullable `Boolean`. Unset 
codegen defaults to disabled
-on Android and GraalVM native image, and enabled on ordinary JVM. Explicit 
`withCodegen(true)` on
-Android or GraalVM does not throw; build finalization forces codegen off and 
emits an explicit
-warning. Explicit `withCodegen(false)` and platform-default disabled codegen 
do not warn.
-
-Android runtime codegen entry points must fail before Janino, class 
definition, generated accessor
-definition, or generated serializer loading starts.
+Android apps that need generated serializers should use build-time static 
generated serializers
+instead.
 
-## ByteBuffer
+## Static Generated Serializers
 
-On Android, `BaseFory#deserialize(ByteBuffer)` copies the remaining input 
bytes into a Fory-owned
-heap `MemoryBuffer`, then deserializes from that buffer. Heap, direct, and 
readonly inputs are
-supported through the copy path. The caller buffer position and limit are not 
changed.
+Use `@ForyStruct` static generated serializers for Android application 
classes. They are generated by
+javac during the app build and work without runtime bytecode generation.
 
-Raw direct-buffer address wrapping remains a JVM-only fast path and is not 
used on Android.
+### Install The Annotation Processor
 
-## Direct Memory And Row Format
+Add `fory-annotation-processor` to the annotation processor path of the module 
that compiles your
+Android model classes:
 
-Android `fory-core` paths do not execute `sun.misc.Unsafe` operations. 
Direct-memory copy APIs are
-JVM-only paths for existing JVM users such as `java/fory-format`; they throw 
before unsafe execution
-when Android is detected.
+```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>
+```
 
-Use core object serialization on Android. Do not use `java/fory-format` 
row-format APIs on Android.
+Then annotate Android model classes with `@ForyStruct`.
 
-## JDK Collection And Map Wrappers
+Static generated serializers are required on Android when a serialized class 
uses Fory type-use
+annotations, for example:
 
-In native Java mode, Android does not add a new wrapper protocol branch and 
does not rewrite normal
-collection/map serializers globally.
+```java
+import java.util.List;
+import org.apache.fory.annotation.ForyStruct;
+import org.apache.fory.annotation.UInt8Type;
 
-For `UnmodifiableSerializers` and `SynchronizedSerializers`, Android keeps the 
outer wrapper
-serializer and writes a public source collection/map payload in the existing 
backing-value slot:
+@ForyStruct
+public class ImageBlock {
+  public List<@UInt8Type Integer> pixels;
+}
+```
 
-- list wrappers use `ArrayList` source type info.
-- set wrappers use `HashSet` source type info.
-- sorted or navigable set wrappers use `TreeSet` source type info.
-- map wrappers use `HashMap` source type info.
-- sorted or navigable map wrappers use `TreeMap` source type info.
+Without the generated static descriptors, Android reflection may not expose 
the nested type-use
+metadata needed for annotations such as `@Ref`, `@Int8Type`, `@UInt8Type`, 
`@Float16Type`, or
+`@BFloat16Type`. Serialization for those classes will not have the schema 
information Fory needs.
 
-The wrapper read path rewraps that source through `Collections.unmodifiable*` 
or
-`Collections.synchronized*`. Synchronized wrapper write and copy paths must 
hold the wrapper lock
-while iterating public contents.
+See [Static Generated Serializers](static-generated-serializers.md) for setup 
instructions.
 
-Sublist views keep a unified serializer protocol. Android writes visible 
elements; JVM may write
-source-list view metadata when supported. Both Android and JVM readers accept 
both payload modes.
+## Object Model Requirements
 
-Other JDK collection serializers keep their existing Java native protocol 
shape while avoiding
-hidden-field unsafe access on Android. `Arrays.asList` writes the existing 
array payload,
-`Collections.newSetFromMap` writes a `HashMap` backing-map payload, bounded 
blocking queues derive
-capacity through public APIs, non-empty `EnumMap` derives its key type from 
the first key, empty
-Android `EnumMap` writes a self-describing Java-serialization fallback, and 
immutable JDK
-collections are materialized through public unmodifiable containers on Android.
+Android serializers use public Android runtime capabilities. For application 
classes, prefer:
 
-In xlang mode, collection and map serialization uses the xlang collection/map 
protocol and does not
-encode Java wrapper/view internals.
+- accessible no-argument constructors, or records with supported constructors.
+- public, protected, or package-private serialized fields.
+- non-private getters and setters for private serialized fields.
+- `@ForyStruct` static generated serializers for Android model classes.
 
-## JDK Dynamic Proxies
+Final fields in ordinary classes are not suitable for generated read/copy 
methods. Use records for
+constructor-based immutable values.
 
-The Android design supports `java.lang.reflect.Proxy` serialization.
+## Unsupported Features
 
-The Android proxy path must use only public proxy APIs:
+The following JVM features are not supported on Android:
 
-- `Proxy.getInvocationHandler(proxy)` to read the handler during write and 
copy.
-- `Proxy.newProxyInstance(classLoader, interfaces, handler)` to construct 
proxies during read and
-  copy.
-- Normal Fory reference serialization for the proxy interface array and 
invocation handler.
+- Runtime serializer code generation and async compilation.
+- Lambda and `SerializedLambda` serialization.
+- Native-address serialization APIs and native-address `MemoryBuffer` wrapping.
+- Raw unsafe memory copy APIs.
+- `java/fory-format` row-format APIs.
 
-Android must not read or write the private `Proxy.h` field, request a field 
offset for that field,
-or use `Unsafe` to replace the handler after proxy construction.
+## ByteBuffer
 
-For non-cyclic proxies, read constructs the proxy directly with the 
deserialized invocation handler.
-For cyclic proxy graphs with reference tracking, Android uses a private 
deferred invocation handler:
+`BaseFory#deserialize(ByteBuffer)` supports heap, direct, and read-only 
buffers on Android by copying
+the remaining bytes into a Fory-owned heap buffer. The caller buffer position 
and limit are not
+changed.
 
-1. Create the proxy with a deferred handler.
-2. Register the proxy in the read or copy reference table before reading or 
copying the real handler.
-3. Read or copy the real handler through the normal Fory object path.
-4. Install the real handler into the deferred handler.
+Raw direct-buffer address wrapping is a JVM-only fast path and is not used on 
Android.
 
-This preserves cycles where an invocation handler references its own proxy 
without mutating private
-JDK fields. The deferred handler is an internal implementation detail and must 
never be written as
-the user handler. When writing or copying a proxy, `JdkProxySerializer` 
unwraps any deferred handler
-before serializing or copying the handler.
+## Collections, Maps, And Proxies
 
-A proxy must not be invoked, logged, or used as a key whose hash or equality 
calls the handler while
-the deferred handler is still unresolved during deserialization or copy. If 
that happens, Fory throws
-a targeted exception instead of silently invoking an incomplete proxy.
+Common JDK collection and map implementations are supported on Android. In 
xlang mode, collection and
+map serialization uses the xlang protocol and does not encode Java 
wrapper/view internals.
 
-The JVM path may keep the existing optimized private-handler replacement path 
when benchmarks
-require it. The Android path must remain separate and must not resolve 
JVM-only proxy handler offset
-state.
+`java.lang.reflect.Proxy` serialization is supported for normal proxy usage. 
Do not invoke, log, or
+use a proxy as a map/set key while it is still being deserialized; the 
invocation handler may not be
+ready yet.
diff --git a/docs/guide/java/configuration.md b/docs/guide/java/configuration.md
index 1a0342aabb..e7c09b123e 100644
--- a/docs/guide/java/configuration.md
+++ b/docs/guide/java/configuration.md
@@ -43,7 +43,7 @@ This page documents all configuration options available 
through `ForyBuilder`.
 | `scopedMetaShareEnabled`            | Scoped meta share focuses on a single 
serialization process. Metadata created or identified during this process is 
exclusive to it and is not shared with by other serializations.                 
                                                                                
                                                                                
                                                                                
                  [...]
 | `metaCompressor`                    | Set a compressor for meta compression. 
Note that the passed MetaCompressor should be thread-safe. By default, a 
`Deflater` based compressor `DeflaterMetaCompressor` will be used. Users can 
pass other compressor such as `zstd` for better compression rate.               
                                                                                
                                                                                
                        [...]
 | `deserializeUnknownClass`           | Enables or disables 
deserialization/skipping of data for non-existent or unknown classes.           
                                                                                
                                                                                
                                                                                
                                                                                
                                 [...]
-| `codeGenEnabled`                    | Disabling may result in faster initial 
serialization but slower subsequent serializations. When unset, codegen 
defaults to enabled on ordinary JVMs and disabled on Android and GraalVM native 
image. Explicit `withCodegen(true)` on Android or GraalVM native image is 
accepted, but final build configuration forces interpreter serializers and 
emits a warning.                                                                
                                 [...]
+| `codeGenEnabled`                    | Disabling may result in faster initial 
serialization but slower subsequent serializations. When unset, codegen 
defaults to enabled on ordinary JVMs and disabled on Android and GraalVM native 
image. Explicit `withCodegen(true)` on Android or GraalVM native image is 
accepted, but final build configuration forces interpreter serializers and 
emits a warning. If a build-time `@ForyStruct` static serializer is available, 
ordinary JVM `withCodegen(false)` [...]
 | `asyncCompilationEnabled`           | If enabled, serialization uses 
interpreter mode first and switches to JIT serialization after async serializer 
JIT for a class is finished. This option is forced off on Android and GraalVM 
native image because runtime code generation is unavailable there.              
                                                                                
                                                                                
                        [...]
 | `scalaOptimizationEnabled`          | Enables or disables Scala-specific 
serialization optimization.                                                     
                                                                                
                                                                                
                                                                                
                                                                                
                  [...]
 | `copyRef`                           | When disabled, the copy performance 
will be better. But fory deep copy will ignore circular and shared reference. 
Same reference of an object graph will be copied into different objects in one 
`Fory#copy`.                                                                    
                                                                                
                                                                                
                    [...]
@@ -77,3 +77,4 @@ Fory fory = Fory.builder()
 - [Schema Evolution](schema-evolution.md) - Compatible mode and meta sharing
 - [Compression](compression.md) - Int, long, and array compression details
 - [Type Registration](type-registration.md) - Class registration options
+- [Static Generated Serializers](static-generated-serializers.md) - 
Annotation-processor static generated serializers for `@ForyStruct`, 
`codegen=false`, and Android
diff --git a/docs/guide/java/index.md b/docs/guide/java/index.md
index 59cca958fc..3e4d29d493 100644
--- a/docs/guide/java/index.md
+++ b/docs/guide/java/index.md
@@ -210,4 +210,5 @@ ThreadSafeFory threadLocalFory = Fory.builder()
 - [Type Registration](type-registration.md) - Class registration and security
 - [Custom Serializers](custom-serializers.md) - Implement custom serializers
 - [Cross-Language Serialization](cross-language.md) - Serialize data for other 
languages
+- [Static Generated Serializers](static-generated-serializers.md) - 
Annotation-processor static generated serializers for `@ForyStruct`
 - [GraalVM Support](graalvm-support.md) - Build-time serializer compilation 
for native images
diff --git a/docs/guide/java/schema-evolution.md 
b/docs/guide/java/schema-evolution.md
index d2db111388..b99a3c5465 100644
--- a/docs/guide/java/schema-evolution.md
+++ b/docs/guide/java/schema-evolution.md
@@ -48,14 +48,24 @@ System.out.println(fory.deserialize(bytes));
 
 This compatible mode involves serializing class metadata into the serialized 
output. Despite Fory's use of sophisticated compression techniques to minimize 
overhead, there is still some additional space cost associated with class 
metadata.
 
-### Disable Evolution for Stable Classes
+### Per-Class Evolution Policy
 
-If a class schema is stable and will not change, you can opt out of schema 
evolution on a per-class basis to avoid compatible metadata overhead. Annotate 
the class with `@ForyStruct(evolving = false)` to force `STRUCT/NAMED_STRUCT` 
type IDs even when Compatible mode is enabled.
+`@ForyStruct` can set a per-class evolution policy:
+
+- `Evolution.INHERIT`: follow the Fory instance's compatible/meta-share 
configuration. This is the default.
+- `Evolution.ENABLED`: require schema evolution metadata for this class. 
Registration or type resolution fails if the Fory instance cannot emit that 
metadata.
+- `Evolution.DISABLED`: force fixed-schema `STRUCT/NAMED_STRUCT` encoding even 
when compatible metadata is otherwise enabled.
+
+Use `@ForyStruct(evolution = Evolution.DISABLED)` for fixed-schema structs. 
The legacy boolean
+form `@ForyStruct(evolving = false)` is still supported as a fixed-schema 
opt-out.
+
+If a class schema is stable and will not change, opt out of schema evolution 
on that class to avoid compatible metadata overhead:
 
 ```java
 import org.apache.fory.annotation.ForyStruct;
+import org.apache.fory.annotation.ForyStruct.Evolution;
 
-@ForyStruct(evolving = false)
+@ForyStruct(evolution = Evolution.DISABLED)
 public class StableMessage {
   public int id;
   public String name;
diff --git a/docs/guide/java/static-generated-serializers.md 
b/docs/guide/java/static-generated-serializers.md
new file mode 100644
index 0000000000..ec101027c5
--- /dev/null
+++ b/docs/guide/java/static-generated-serializers.md
@@ -0,0 +1,138 @@
+---
+title: Static Generated Serializers
+sidebar_position: 15
+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 cross-language 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__`.
+
+## 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.
+
+## 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`.
+
+## 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.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to