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]