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


The following commit(s) were added to refs/heads/main by this push:
     new c484a5a6d πŸ”„ synced local 'docs/docs/guide/' with remote 'docs/guide/'
c484a5a6d is described below

commit c484a5a6dd655466d07e62905947a6282b0155ea
Author: chaokunyang <[email protected]>
AuthorDate: Thu Dec 4 07:43:11 2025 +0000

    πŸ”„ synced local 'docs/docs/guide/' with remote 'docs/guide/'
---
 docs/docs/guide/graalvm_guide.md | 228 ++++++++++++++++++++++-----------------
 1 file changed, 128 insertions(+), 100 deletions(-)

diff --git a/docs/docs/guide/graalvm_guide.md b/docs/docs/guide/graalvm_guide.md
index 3f85c2c70..2a1f6468f 100644
--- a/docs/docs/guide/graalvm_guide.md
+++ b/docs/docs/guide/graalvm_guide.md
@@ -21,179 +21,207 @@ license: |
 
 ## GraalVM Native Image
 
-GraalVM `native image` can compile java code into native code ahead to build 
faster, smaller, leaner applications.
-The native image doesn't have a JIT compiler to compile bytecode into machine 
code, and doesn't support
-reflection unless configure reflection file.
+GraalVM `native image` compiles Java code into native executables 
ahead-of-time, resulting in faster startup and lower memory usage. However, 
native images don't support runtime JIT compilation or reflection without 
explicit configuration.
 
-Apache Foryβ„’ runs on GraalVM native image pretty well. Apache Foryβ„’ generates 
all serializer code for `Fory JIT framework` and 
`MethodHandle/LambdaMetafactory` at graalvm build time. Then use those 
generated code for serialization at runtime without
-any extra cost, the performance is great.
+Apache Foryβ„’ works excellently with GraalVM native image by using **codegen 
instead of reflection**. All serializer code is generated at build time, 
eliminating the need for reflection configuration files in most cases.
 
-In order to use Apache Foryβ„’ on graalvm native image, you must create Fory as 
an **static** field of a class, and **register** all classes at
-the enclosing class initialize time. Then configure `native-image.properties` 
under
-`resources/META-INF/native-image/$xxx/native-image.properties` to tell graalvm 
to init the class at native image
-build time. For example, here we configure `org.apache.fory.graalvm.Example` 
class be init at build time:
+## How It Works
 
-```properties
-Args = --initialize-at-build-time=org.apache.fory.graalvm.Example
-```
+Fory generates serialization code at GraalVM build time when you:
 
-**The main benefit of using Fory with GraalVM is that you don't need to 
configure [reflection 
json](https://www.graalvm.org/latest/reference-manual/native-image/metadata/#specifying-reflection-metadata-in-json)
 or
-[serialization 
json](https://www.graalvm.org/latest/reference-manual/native-image/metadata/#serialization)
 for your serializable classes!** This eliminates the tedious, cumbersome and 
error-prone configuration process.
+1. Create Fory as a **static** field
+2. **Register** all classes in a static initializer
+3. Call `fory.ensureSerializersCompiled()` to compile serializers
+4. Configure the class to initialize at build time via 
`native-image.properties`
 
-Fory achieves this by using **codegen instead of reflection** - all 
serialization code is generated at build time when you call:
+**The main benefit**: You don't need to configure [reflection 
json](https://www.graalvm.org/latest/reference-manual/native-image/metadata/#specifying-reflection-metadata-in-json)
 or [serialization 
json](https://www.graalvm.org/latest/reference-manual/native-image/metadata/#serialization)
 for most serializable classes.
 
-- `fory.register(YourClass.class)` to register your classes
-- `fory.ensureSerializersCompiled()` to compile serializers at build time
+Note: Fory's `asyncCompilationEnabled` option is automatically disabled for 
GraalVM native image since runtime JIT is not supported.
 
-Note that Fory `asyncCompilationEnabled` option will be disabled automatically 
for graalvm native image since graalvm
-native image doesn't support JIT at the image run time.
+## Basic Usage
 
-## Registering Your Classes
+### Step 1: Create Fory and Register Classes
 
-If you encounter a GraalVM error like:
+```java
+import org.apache.fory.Fory;
 
-```
-Type com.example.MyClass is instantiated reflectively but was never registered
-```
+public class Example {
+  // Must be static field
+  static Fory fory;
 
-This means you need to register your class with Fory. **Do NOT add it to 
reflect-config.json** - instead, register it with Fory's codegen system:
+  static {
+    fory = Fory.builder().build();
+    fory.register(MyClass.class);
+    fory.register(AnotherClass.class);
+    // Compile all serializers at build time
+    fory.ensureSerializersCompiled();
+  }
 
-```java
-static {
-  fory = Fory.builder().build();
-  // register class
-  fory.register(MyClass.class);
-  // ensure all serializers for registered classes being compiled by fory at 
graalvm native image build time.
-  fory.ensureSerializersCompiled();
+  public static void main(String[] args) {
+    byte[] bytes = fory.serialize(new MyClass());
+    MyClass obj = (MyClass) fory.deserialize(bytes);
+  }
 }
 ```
 
-And make sure the class executing static registering is initialized at build 
time in `native-image.properties`:
+### Step 2: Configure Build-Time Initialization
+
+Create 
`resources/META-INF/native-image/your-group/your-artifact/native-image.properties`:
 
 ```properties
-Args = --initialize-at-build-time=com.example.MyForySerializer
+Args = --initialize-at-build-time=com.example.Example
 ```
 
-This approach is much more efficient than reflection-based serialization and 
eliminates the need for complex GraalVM configuration files.
+## ForyGraalVMFeature (Optional)
 
-## Not thread-safe Fory
+For most types with public constructors, the basic setup above is sufficient. 
However, some advanced cases require reflection registration:
 
-Example:
+- **Private constructors** (classes without accessible no-arg constructor)
+- **Private inner classes/records**
+- **Dynamic proxy serialization**
 
-```java
-import org.apache.fory.Fory;
-import org.apache.fory.util.Preconditions;
+The `fory-graalvm-feature` module automatically handles these cases, 
eliminating the need for manual `reflect-config.json` configuration.
+
+### Adding the Dependency
 
-import java.util.List;
-import java.util.Map;
+```xml
+<dependency>
+  <groupId>org.apache.fory</groupId>
+  <artifactId>fory-graalvm-feature</artifactId>
+  <version>${fory.version}</version>
+</dependency>
+```
+
+### Enabling the Feature
 
+Add to your `native-image.properties`:
+
+```properties
+Args = --initialize-at-build-time=com.example.Example \
+       --features=org.apache.fory.graalvm.feature.ForyGraalVMFeature
+```
+
+### What ForyGraalVMFeature Handles
+
+| Scenario                        | Without Feature              | With 
Feature       |
+| ------------------------------- | ---------------------------- | 
------------------ |
+| Public classes with no-arg ctor | βœ… Works                     | βœ… Works      
     |
+| Private constructors            | ❌ Needs reflect-config.json | βœ… 
Auto-registered |
+| Private inner records           | ❌ Needs reflect-config.json | βœ… 
Auto-registered |
+| Dynamic proxies                 | ❌ Needs manual config       | βœ… 
Auto-registered |
+
+### Example with Private Record
+
+```java
 public class Example {
-  public record Record (
-    int f1,
-    String f2,
-    List<String> f3,
-    Map<String, Long> f4) {
-  }
+  // Private inner record - requires ForyGraalVMFeature
+  private record PrivateRecord(int id, String name) {}
 
   static Fory fory;
 
   static {
     fory = Fory.builder().build();
-    // register class
-    fory.register(Record.class);
-    // ensure all serializers for registered classes being compiled by fory at 
graalvm native image build time.
+    fory.register(PrivateRecord.class);
     fory.ensureSerializersCompiled();
   }
-
-  public static void main(String[] args) {
-    Record record = new Record(10, "abc", List.of("str1", "str2"), 
Map.of("k1", 10L, "k2", 20L));
-    System.out.println(record);
-    byte[] bytes = fory.serialize(record);
-    Object o = fory.deserialize(bytes);
-    System.out.println(o);
-    Preconditions.checkArgument(record.equals(o));
-  }
 }
 ```
 
-Then add `org.apache.fory.graalvm.Example` build time init to 
`native-image.properties` configuration:
+### Example with Dynamic Proxy
 
-```properties
-Args = --initialize-at-build-time=org.apache.fory.graalvm.Example
+```java
+import org.apache.fory.util.GraalvmSupport;
+
+public class ProxyExample {
+  public interface MyService {
+    String execute();
+  }
+
+  static Fory fory;
+
+  static {
+    fory = Fory.builder().build();
+    // Register proxy interface for serialization
+    GraalvmSupport.registerProxySupport(MyService.class);
+    fory.ensureSerializersCompiled();
+  }
+}
 ```
 
-## Thread-safe Fory
+## Thread-Safe Fory
+
+For multi-threaded applications, use `ThreadLocalFory`:
 
 ```java
 import org.apache.fory.Fory;
 import org.apache.fory.ThreadLocalFory;
 import org.apache.fory.ThreadSafeFory;
-import org.apache.fory.util.Preconditions;
-
-import java.util.List;
-import java.util.Map;
 
 public class ThreadSafeExample {
-  public record Foo (
-    int f1,
-    String f2,
-    List<String> f3,
-    Map<String, Long> f4) {
-  }
+  public record Foo(int f1, String f2, List<String> f3) {}
 
   static ThreadSafeFory fory;
 
   static {
     fory = new ThreadLocalFory(classLoader -> {
       Fory f = Fory.builder().build();
-      // register class
       f.register(Foo.class);
-      // ensure all serializers for registered classes being compiled by fory 
at graalvm native image build time.
-      fory.ensureSerializersCompiled();
+      f.ensureSerializersCompiled();
       return f;
     });
   }
 
   public static void main(String[] args) {
-    System.out.println(fory.deserialize(fory.serialize("abc")));
-    System.out.println(fory.deserialize(fory.serialize(List.of(1,2,3))));
-    System.out.println(fory.deserialize(fory.serialize(Map.of("k1", 1, "k2", 
2))));
-    Foo foo = new Foo(10, "abc", List.of("str1", "str2"), Map.of("k1", 10L, 
"k2", 20L));
-    System.out.println(foo);
+    Foo foo = new Foo(10, "abc", List.of("str1", "str2"));
     byte[] bytes = fory.serialize(foo);
-    Object o = fory.deserialize(bytes);
-    System.out.println(o);
+    Foo result = (Foo) fory.deserialize(bytes);
   }
 }
 ```
 
-Then add `org.apache.fory.graalvm.ThreadSafeExample` build time init to 
`native-image.properties` configuration:
+## Troubleshooting
 
-```properties
-Args = --initialize-at-build-time=org.apache.fory.graalvm.ThreadSafeExample
+### "Type is instantiated reflectively but was never registered"
+
+If you see this error:
+
+```
+Type com.example.MyClass is instantiated reflectively but was never registered
 ```
 
-## Framework Integration
+**Solution**: Register the class with Fory (don't add to reflect-config.json):
 
-For framework developers, if you want to integrate fory for serialization, you 
can provided a configuration file to let
-the users to list all the classes they want to serialize, then you can load 
those classes and invoke
-`org.apache.fory.Fory.register(Class<?>)` to register those classes in your 
Fory integration class. After all classes are registered, you need to invoke 
`org.apache.fory.Fory.ensureSerializersCompiled()` to compile serializers at 
build time, and configure that class be initialized at graalvm native image 
build time.
+```java
+fory.register(MyClass.class);
+fory.ensureSerializersCompiled();
+```
 
-## Benchmark
+If the class has a private constructor, either:
 
-Here we give two class benchmarks between Fory and Graalvm Serialization.
+1. Add `fory-graalvm-feature` dependency, or
+2. Create a `reflect-config.json` for that specific class
 
-When Fory compression is disabled:
+## Framework Integration
 
-- Struct: Fory is `46x speed, 43% size` compared to JDK.
-- Pojo: Fory is `12x speed, 56% size` compared to JDK.
+For framework developers integrating Fory:
+
+1. Provide a configuration file for users to list serializable classes
+2. Load those classes and call `fory.register(Class<?>)` for each
+3. Call `fory.ensureSerializersCompiled()` after all registrations
+4. Configure your integration class for build-time initialization
+
+## Benchmark
 
-When Fory compression is enabled:
+Performance comparison between Fory and GraalVM JDK Serialization:
 
-- Struct: Fory is `24x speed, 31% size` compared to JDK.
-- Pojo: Fory is `12x speed, 48% size` compared to JDK.
+| Type   | Compression | Speed      | Size |
+| ------ | ----------- | ---------- | ---- |
+| Struct | Off         | 46x faster | 43%  |
+| Struct | On          | 24x faster | 31%  |
+| Pojo   | Off         | 12x faster | 56%  |
+| Pojo   | On          | 12x faster | 48%  |
 
-See 
[[Benchmark.java](https://github.com/apache/fory/blob/main/integration_tests/graalvm_tests/src/main/java/org/apache/fory/graalvm/Benchmark.java)]
 for benchmark code.
+See 
[Benchmark.java](https://github.com/apache/fory/blob/main/integration_tests/graalvm_tests/src/main/java/org/apache/fory/graalvm/Benchmark.java)
 for benchmark code.
 
 ### Struct Benchmark
 


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

Reply via email to