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 b9eabf3cf πŸ”„ synced local 'docs/guide/' with remote 'docs/guide/'
b9eabf3cf is described below

commit b9eabf3cf70ffbb19bb9683a54c06a9c5968fe0e
Author: chaokunyang <[email protected]>
AuthorDate: Mon Apr 20 05:39:44 2026 +0000

    πŸ”„ synced local 'docs/guide/' with remote 'docs/guide/'
---
 docs/guide/java/advanced-features.md   |   2 +-
 docs/guide/java/basic-serialization.md |   4 +
 docs/guide/java/cross-language.md      |   2 +-
 docs/guide/java/graalvm_support.md     | 329 +++++++++++++++++++++++++++++
 docs/guide/java/index.md               |   2 +
 docs/guide/java/migration.md           |   2 +-
 docs/guide/java/object-copy.md         | 375 +++++++++++++++++++++++++++++++++
 docs/guide/java/row-format.md          |   2 +-
 docs/guide/java/schema-evolution.md    |   2 +-
 docs/guide/java/troubleshooting.md     |   2 +-
 docs/guide/java/virtual-threads.md     |   2 +-
 11 files changed, 717 insertions(+), 7 deletions(-)

diff --git a/docs/guide/java/advanced-features.md 
b/docs/guide/java/advanced-features.md
index c45d700d1..765b00247 100644
--- a/docs/guide/java/advanced-features.md
+++ b/docs/guide/java/advanced-features.md
@@ -1,6 +1,6 @@
 ---
 title: Advanced Features
-sidebar_position: 10
+sidebar_position: 11
 id: advanced_features
 license: |
   Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/docs/guide/java/basic-serialization.md 
b/docs/guide/java/basic-serialization.md
index caa9c1fd2..abc6d58dc 100644
--- a/docs/guide/java/basic-serialization.md
+++ b/docs/guide/java/basic-serialization.md
@@ -73,6 +73,9 @@ System.out.println(fory.deserialize(bytes));
 
 Fory provides efficient deep copy functionality:
 
+For the full copy semantics, custom copy hooks, and troubleshooting guidance, 
see
+[Object Copy](object-copy.md).
+
 ### With Reference Tracking
 
 ```java
@@ -123,5 +126,6 @@ MyClass obj = fory.deserialize(bytes, MyClass.class);
 ## Related Topics
 
 - [Configuration](configuration.md) - All ForyBuilder options
+- [Object Copy](object-copy.md) - Deep-copy semantics and custom copy hooks
 - [Type Registration](type-registration.md) - Class registration
 - [Troubleshooting](troubleshooting.md) - Common API usage issues
diff --git a/docs/guide/java/cross-language.md 
b/docs/guide/java/cross-language.md
index 31776ab7c..f1dfd4eb6 100644
--- a/docs/guide/java/cross-language.md
+++ b/docs/guide/java/cross-language.md
@@ -1,6 +1,6 @@
 ---
 title: Cross-Language Serialization
-sidebar_position: 11
+sidebar_position: 12
 id: cross_language
 license: |
   Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/docs/guide/java/graalvm_support.md 
b/docs/guide/java/graalvm_support.md
new file mode 100644
index 000000000..607211ec3
--- /dev/null
+++ b/docs/guide/java/graalvm_support.md
@@ -0,0 +1,329 @@
+---
+title: GraalVM Support
+sidebar_position: 13
+id: graalvm_support
+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.
+---
+
+## GraalVM Native Image
+
+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β„’ 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.
+
+## How It Works
+
+Fory generates serialization code at GraalVM build time when you:
+
+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`
+
+**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.
+
+Note: Fory's `asyncCompilationEnabled` option is automatically disabled for 
GraalVM native image since runtime JIT is not supported.
+
+## Basic Usage
+
+### Step 0: Add the GraalVM Support Dependency
+
+Add `fory-graalvm-feature` to your application dependencies when building a 
native image:
+
+```xml
+<dependency>
+  <groupId>org.apache.fory</groupId>
+  <artifactId>fory-graalvm-feature</artifactId>
+  <version>${fory.version}</version>
+</dependency>
+```
+
+This dependency already ships GraalVM feature metadata in 
`META-INF/native-image`, so adding it
+automatically enables `org.apache.fory.graalvm.feature.ForyGraalVMFeature` 
during native-image
+builds.
+
+### Step 1: Create Fory and Register Classes
+
+```java
+import org.apache.fory.Fory;
+
+public class Example {
+  // Must be static field
+  static Fory fory;
+
+  static {
+    fory = Fory.builder().build();
+    fory.register(MyClass.class);
+    fory.register(AnotherClass.class);
+    // Compile all serializers at build time
+    fory.ensureSerializersCompiled();
+  }
+
+  public static void main(String[] args) {
+    byte[] bytes = fory.serialize(new MyClass());
+    MyClass obj = (MyClass) fory.deserialize(bytes);
+  }
+}
+```
+
+### 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.Example
+```
+
+## What `fory-graalvm-feature` Handles
+
+After you add the `fory-graalvm-feature` dependency, Fory automatically 
registers the extra
+GraalVM metadata needed by advanced cases such as:
+
+- **Private constructors** (classes without accessible no-arg constructor)
+- **Private inner classes/records**
+- **Dynamic proxy serialization**
+
+This removes the need for manual `reflect-config.json` in most applications. 
Your own
+`native-image.properties` still only needs to configure your build-time 
initialized bootstrap
+class, for example:
+
+```properties
+Args = --initialize-at-build-time=com.example.Example
+```
+
+| 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 {
+  // Private inner record - requires ForyGraalVMFeature
+  private record PrivateRecord(int id, String name) {}
+
+  static Fory fory;
+
+  static {
+    fory = Fory.builder().build();
+    fory.register(PrivateRecord.class);
+    fory.ensureSerializersCompiled();
+  }
+}
+```
+
+### Example with Dynamic Proxy
+
+```java
+import org.apache.fory.util.GraalvmSupport;
+
+public class ProxyExample {
+  public interface MyService {
+    String execute();
+  }
+
+  public interface Audited {
+    String traceId();
+  }
+
+  static Fory fory;
+
+  static {
+    fory = Fory.builder().build();
+    // Register the exact interface list used by Proxy.newProxyInstance(...)
+    GraalvmSupport.registerProxySupport(MyService.class, Audited.class);
+    fory.ensureSerializersCompiled();
+  }
+}
+```
+
+Use `registerProxySupport(MyService.class)` for a single-interface proxy. For 
proxies that implement
+multiple interfaces, pass the full interface list in the same order used to 
create the proxy. With
+`fory-graalvm-feature` on the classpath, this replaces manual 
`proxy-config.json` entries for those
+registered proxy shapes.
+
+## 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;
+
+public class ThreadSafeExample {
+  public record Foo(int f1, String f2, List<String> f3) {}
+
+  static ThreadSafeFory fory;
+
+  static {
+    fory = new ThreadLocalFory(builder -> {
+      Fory f = builder.build();
+      f.register(Foo.class);
+      f.ensureSerializersCompiled();
+      return f;
+    });
+  }
+
+  public static void main(String[] args) {
+    Foo foo = new Foo(10, "abc", List.of("str1", "str2"));
+    byte[] bytes = fory.serialize(foo);
+    Foo result = (Foo) fory.deserialize(bytes);
+  }
+}
+```
+
+## Troubleshooting
+
+### "Type is instantiated reflectively but was never registered"
+
+If you see this error:
+
+```
+Type com.example.MyClass is instantiated reflectively but was never registered
+```
+
+**Solution**: Register the class with Fory (don't add to reflect-config.json):
+
+```java
+fory.register(MyClass.class);
+fory.ensureSerializersCompiled();
+```
+
+If the class has a private constructor, either:
+
+1. Make sure `fory-graalvm-feature` is already on the native-image classpath, 
or
+2. Create a `reflect-config.json` for that specific class
+
+## Framework Integration
+
+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
+
+Performance comparison between Fory and GraalVM JDK Serialization:
+
+| 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.
+
+### Struct Benchmark
+
+#### Class Fields
+
+```java
+public class Struct implements Serializable {
+  public int f1;
+  public long f2;
+  public float f3;
+  public double f4;
+  public int f5;
+  public long f6;
+  public float f7;
+  public double f8;
+  public int f9;
+  public long f10;
+  public float f11;
+  public double f12;
+}
+```
+
+#### Benchmark Results
+
+No compression:
+
+```
+Benchmark repeat number: 400000
+Object type: class org.apache.fory.graalvm.Struct
+Compress number: false
+Fory size: 76.0
+JDK size: 178.0
+Fory serialization took mills: 49
+JDK serialization took mills: 2254
+Compare speed: Fory is 45.70x speed of JDK
+Compare size: Fory is 0.43x size of JDK
+```
+
+Compress number:
+
+```
+Benchmark repeat number: 400000
+Object type: class org.apache.fory.graalvm.Struct
+Compress number: true
+Fory size: 55.0
+JDK size: 178.0
+Fory serialization took mills: 130
+JDK serialization took mills: 3161
+Compare speed: Fory is 24.16x speed of JDK
+Compare size: Fory is 0.31x size of JDK
+```
+
+### Pojo Benchmark
+
+#### Class Fields
+
+```java
+public class Foo implements Serializable {
+  int f1;
+  String f2;
+  List<String> f3;
+  Map<String, Long> f4;
+}
+```
+
+#### Benchmark Results
+
+No compression:
+
+```
+Benchmark repeat number: 400000
+Object type: class org.apache.fory.graalvm.Foo
+Compress number: false
+Fory size: 541.0
+JDK size: 964.0
+Fory serialization took mills: 1663
+JDK serialization took mills: 16266
+Compare speed: Fory is 12.19x speed of JDK
+Compare size: Fory is 0.56x size of JDK
+```
+
+Compress number:
+
+```
+Benchmark repeat number: 400000
+Object type: class org.apache.fory.graalvm.Foo
+Compress number: true
+Fory size: 459.0
+JDK size: 964.0
+Fory serialization took mills: 1289
+JDK serialization took mills: 15069
+Compare speed: Fory is 12.11x speed of JDK
+Compare size: Fory is 0.48x size of JDK
+```
diff --git a/docs/guide/java/index.md b/docs/guide/java/index.md
index e4b7d05ac..95eccf6e2 100644
--- a/docs/guide/java/index.md
+++ b/docs/guide/java/index.md
@@ -203,8 +203,10 @@ ThreadSafeFory threadLocalFory = Fory.builder()
 - [Field Configuration](field-configuration.md) - `@ForyField`, `@Ignore`, and 
integer encoding annotations
 - [Enum Configuration](enum-configuration.md) - `serializeEnumByName` and 
`@ForyEnumId`
 - [Basic Serialization](basic-serialization.md) - Detailed serialization 
patterns
+- [Object Copy](object-copy.md) - Deep-copy Java object graphs in memory
 - [Compression](compression.md) - Integer, long, and array compression options
 - [Virtual Threads](virtual-threads.md) - Virtual-thread usage and pool sizing 
guidance
 - [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
+- [GraalVM Support](graalvm_support.md) - Build-time serializer compilation 
for native images
diff --git a/docs/guide/java/migration.md b/docs/guide/java/migration.md
index 9c77b3564..e17152936 100644
--- a/docs/guide/java/migration.md
+++ b/docs/guide/java/migration.md
@@ -1,6 +1,6 @@
 ---
 title: Migration Guide
-sidebar_position: 13
+sidebar_position: 15
 id: migration
 license: |
   Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/docs/guide/java/object-copy.md b/docs/guide/java/object-copy.md
new file mode 100644
index 000000000..c0fd4f51e
--- /dev/null
+++ b/docs/guide/java/object-copy.md
@@ -0,0 +1,375 @@
+---
+title: Object Copy
+sidebar_position: 9
+id: object_copy
+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.
+---
+
+This page covers in-memory Java object graph copying with `Fory#copy(Object)`.
+
+`Fory.copy` is a deep-copy operation for Java object graphs. It does not 
serialize to bytes first.
+Instead, it uses the same runtime type system and serializers to create a 
copied object graph in
+memory.
+
+## When to Use Object Copy
+
+Use object copy when you want a detached in-memory clone of an existing Java 
object graph.
+
+Typical use cases:
+
+- Clone request or response models before mutation
+- Duplicate cached state for optimistic updates
+- Copy graphs that contain collections, maps, arrays, or nested beans
+- Preserve shared references and circular references during cloning
+
+Use serialization instead when you need bytes for transport, storage, or 
cross-process exchange.
+
+| Operation                | `Fory.copy`         | `serialize` / `deserialize` 
              |
+| ------------------------ | ------------------- | 
----------------------------------------- |
+| Result                   | Java object graph   | Binary payload plus 
reconstructed objects |
+| Main use                 | In-memory deep copy | Transport, persistence, 
interoperability  |
+| Copy ref option          | `withRefCopy(...)`  | `withRefTracking(...)`      
              |
+| Cross-language payload   | No                  | Yes, in xlang mode          
              |
+| Intermediate byte buffer | No                  | Yes                         
              |
+
+## Quick Start
+
+For general-purpose object graphs, enable `withRefCopy(true)` so shared 
references and cycles are
+handled correctly:
+
+```java
+import org.apache.fory.Fory;
+import org.apache.fory.config.Language;
+
+public class Example {
+  public static void main(String[] args) {
+    Fory fory = Fory.builder()
+      .withLanguage(Language.JAVA)
+      .withRefCopy(true)
+      .build();
+
+    Order original = new Order();
+    Order copied = fory.copy(original);
+  }
+}
+```
+
+`copy(null)` returns `null`.
+
+## Reference Semantics
+
+The most important copy option is `ForyBuilder#withRefCopy(boolean)`.
+
+### `withRefCopy(true)`
+
+This is the safe default for general object graphs. Shared references remain 
shared in the copied
+graph, and circular references can be copied correctly.
+
+```java
+import org.apache.fory.Fory;
+import org.apache.fory.config.Language;
+
+public class Example {
+  static final class Address {
+    String city;
+  }
+
+  static final class Pair {
+    Address left;
+    Address right;
+  }
+
+  public static void main(String[] args) {
+    Fory fory = Fory.builder()
+      .withLanguage(Language.JAVA)
+      .withRefCopy(true)
+      .build();
+
+    Address address = new Address();
+    address.city = "Shanghai";
+
+    Pair pair = new Pair();
+    pair.left = address;
+    pair.right = address;
+
+    Pair copied = fory.copy(pair);
+    System.out.println(copied.left == copied.right); // true
+  }
+}
+```
+
+### `withRefCopy(false)`
+
+Disable copy ref tracking only when you know the graph is tree-like and does 
not rely on shared or
+cyclic references. This can be faster, but repeated references are copied into 
different objects.
+
+```java
+import org.apache.fory.Fory;
+import org.apache.fory.config.Language;
+
+public class Example {
+  static final class Address {
+    String city;
+  }
+
+  static final class Pair {
+    Address left;
+    Address right;
+  }
+
+  public static void main(String[] args) {
+    Fory fory = Fory.builder()
+      .withLanguage(Language.JAVA)
+      .withRefCopy(false)
+      .build();
+
+    Address address = new Address();
+    Pair pair = new Pair();
+    pair.left = address;
+    pair.right = address;
+
+    Pair copied = fory.copy(pair);
+    System.out.println(copied.left == copied.right); // false
+  }
+}
+```
+
+If you disable `withRefCopy` and the graph contains a cycle, copy can fail 
with stack overflow.
+
+## `withRefCopy` vs `withRefTracking`
+
+These two options control different operations:
+
+- `withRefCopy(true)` affects `Fory.copy(...)`
+- `withRefTracking(true)` affects serialization and deserialization
+
+Enabling one does not automatically enable the other. If your application both 
serializes and
+copies graphs with shared or circular references, configure both options 
explicitly.
+
+```java
+Fory fory = Fory.builder()
+  .withRefTracking(true)
+  .withRefCopy(true)
+  .build();
+```
+
+## Immutable vs Mutable Values
+
+Fory may reuse the original instance for immutable values. For mutable values, 
it creates a new
+object graph.
+
+In practice, this means:
+
+- `String`, boxed primitives, enums, and many immutable JDK value types may be 
returned as-is
+- Primitive arrays, string arrays, collections, maps, beans, dates, and other 
mutable structures
+  are copied into distinct objects
+
+Do not use object identity alone to decide whether copy succeeded. Use the 
mutability contract of
+the value you are copying.
+
+## Class Registration
+
+If class registration is required, register copied classes before calling 
`copy`.
+
+```java
+import org.apache.fory.Fory;
+
+public class Example {
+  public static void main(String[] args) {
+    Fory fory = Fory.builder()
+      .requireClassRegistration(true)
+      .withRefCopy(true)
+      .build();
+
+    fory.register(Order.class);
+    Order copied = fory.copy(new Order());
+  }
+}
+```
+
+This follows the same registration rules as the rest of the runtime: if the 
runtime requires class
+registration, copied runtime types must be registered first.
+
+## Thread-Safe Copy
+
+`ThreadSafeFory` also supports `copy(...)`.
+
+For general multi-threaded usage:
+
+```java
+import org.apache.fory.Fory;
+import org.apache.fory.ThreadSafeFory;
+import org.apache.fory.config.Language;
+
+public class Example {
+  public static void main(String[] args) {
+    ThreadSafeFory fory = Fory.builder()
+      .withLanguage(Language.JAVA)
+      .withRefCopy(true)
+      .buildThreadSafeFory();
+
+    Order copied = fory.copy(new Order());
+  }
+}
+```
+
+The same API also works for `buildThreadLocalFory()` and 
`buildThreadSafeForyPool(poolSize)`.
+
+## Built-In Coverage
+
+Fory already provides copy support for many common Java runtime types, 
including:
+
+- Primitive values and boxed primitives
+- Strings and primitive arrays
+- Common JDK collections and maps
+- Java time and date/time values
+- Beans, records, and nested object graphs
+
+If the runtime already knows how to serialize a mutable type, it may still 
need an explicit copy
+implementation in that serializer. For mutable serializers, the default 
`Serializer.copy(...)`
+throws `UnsupportedOperationException` unless the serializer overrides it.
+
+## Custom Copy with `ForyCopyable`
+
+If a type needs custom copy logic, implement `ForyCopyable<T>`.
+
+This is the simplest approach when the class itself should control how nested 
fields are copied:
+
+```java
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.fory.ForyCopyable;
+import org.apache.fory.context.CopyContext;
+
+public final class Node implements ForyCopyable<Node> {
+  private String name;
+  private final List<Node> neighbors = new ArrayList<>();
+
+  @Override
+  public Node copy(CopyContext copyContext) {
+    Node copied = new Node();
+    copyContext.reference(this, copied);
+    copied.name = name;
+    for (Node neighbor : neighbors) {
+      copied.neighbors.add(copyContext.copyObject(neighbor));
+    }
+    return copied;
+  }
+}
+```
+
+Guidelines:
+
+- Call `copyContext.reference(origin, copy)` immediately after creating a 
composite mutable object
+  if the type can participate in cycles or shared-reference graphs
+- Use `copyContext.copyObject(...)` for nested values instead of manually 
duplicating nested copy
+  logic
+- Keep copy logic consistent with the normal runtime semantics of the type
+
+## Custom Copy in a Serializer
+
+When a type already uses a custom serializer, override `Serializer.copy(...)` 
for mutable values.
+
+```java
+import org.apache.fory.config.Config;
+import org.apache.fory.context.CopyContext;
+import org.apache.fory.serializer.Serializer;
+
+public final class EnvelopeSerializer extends Serializer<Envelope> {
+  public EnvelopeSerializer(Config config) {
+    super(config, Envelope.class);
+  }
+
+  @Override
+  public Envelope copy(CopyContext copyContext, Envelope value) {
+    Envelope copied = new Envelope();
+    copyContext.reference(value, copied);
+    copied.header = copyContext.copyObject(value.header);
+    copied.payload = copyContext.copyObject(value.payload);
+    return copied;
+  }
+
+  @Override
+  public void write(org.apache.fory.context.WriteContext writeContext, 
Envelope value) {
+    throw new UnsupportedOperationException("omitted");
+  }
+
+  @Override
+  public Envelope read(org.apache.fory.context.ReadContext readContext) {
+    throw new UnsupportedOperationException("omitted");
+  }
+}
+```
+
+Use this approach when copy behavior belongs with a serializer rather than the 
domain class.
+
+## Best Practices
+
+- Reuse `Fory` or `ThreadSafeFory` instances instead of rebuilding them for 
each copy
+- Enable `withRefCopy(true)` unless you are certain the graph is acyclic and 
does not rely on
+  shared references
+- Treat `withRefCopy(false)` as a performance optimization for tree-like data, 
not as a default
+- Test custom copy implementations with both shared-reference and cyclic graphs
+- Keep mutable custom serializer copy paths explicit and do not rely on 
fallback behavior
+
+## Troubleshooting
+
+### Stack Overflow or Copy Failure on Cyclic Graphs
+
+If copy fails on a cyclic object graph, enable `withRefCopy(true)`:
+
+```java
+Fory fory = Fory.builder()
+  .withRefCopy(true)
+  .build();
+```
+
+Disabling copy ref tracking is only safe for acyclic graphs.
+
+### Shared References Are Not Preserved
+
+If the same source object is copied into multiple distinct target objects, 
`withRefCopy` is
+disabled. Turn it on:
+
+```java
+Fory fory = Fory.builder()
+  .withRefCopy(true)
+  .build();
+```
+
+`withRefTracking(true)` alone does not change `Fory.copy(...)` behavior.
+
+### `Copy for ... is not supported`
+
+This means the mutable serializer for that type does not implement `copy(...)`.
+
+Fix it by either:
+
+- Implementing `ForyCopyable<T>` on the class, or
+- Overriding `Serializer.copy(CopyContext, T)` in the registered serializer
+
+### Registration Errors
+
+If your runtime uses `requireClassRegistration(true)`, make sure the copied 
runtime types are
+registered before calling `copy(...)`.
+
+## Related Topics
+
+- [Basic Serialization](basic-serialization.md) - Runtime creation and core 
APIs
+- [Configuration](configuration.md) - Builder options including `withRefCopy`
+- [Custom Serializers](custom-serializers.md) - Serializer design and 
registration
+- [Virtual Threads](virtual-threads.md) - Thread-safe runtime guidance
diff --git a/docs/guide/java/row-format.md b/docs/guide/java/row-format.md
index 14bb55ed4..5b3425bc8 100644
--- a/docs/guide/java/row-format.md
+++ b/docs/guide/java/row-format.md
@@ -1,6 +1,6 @@
 ---
 title: Row Format
-sidebar_position: 12
+sidebar_position: 14
 id: row_format
 license: |
   Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/docs/guide/java/schema-evolution.md 
b/docs/guide/java/schema-evolution.md
index 5b754171a..acd870f55 100644
--- a/docs/guide/java/schema-evolution.md
+++ b/docs/guide/java/schema-evolution.md
@@ -1,6 +1,6 @@
 ---
 title: Schema Evolution
-sidebar_position: 9
+sidebar_position: 8
 id: schema_evolution
 license: |
   Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/docs/guide/java/troubleshooting.md 
b/docs/guide/java/troubleshooting.md
index b693d51bc..c03c19a1a 100644
--- a/docs/guide/java/troubleshooting.md
+++ b/docs/guide/java/troubleshooting.md
@@ -1,6 +1,6 @@
 ---
 title: Troubleshooting
-sidebar_position: 14
+sidebar_position: 16
 id: troubleshooting
 license: |
   Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/docs/guide/java/virtual-threads.md 
b/docs/guide/java/virtual-threads.md
index cc57166b3..764cd5243 100644
--- a/docs/guide/java/virtual-threads.md
+++ b/docs/guide/java/virtual-threads.md
@@ -1,6 +1,6 @@
 ---
 title: Virtual Threads
-sidebar_position: 8
+sidebar_position: 10
 id: java_virtual_threads
 license: |
   Licensed to the Apache Software Foundation (ASF) under one or more


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

Reply via email to