引用跟踪
本页说明 Fory 在跨语言序列化中如 何处理共享引用与循环引用的引用跟踪。
概述
Reference tracking enables:
- Shared references: Same object referenced multiple times is serialized once
- Circular references: Objects that reference themselves or form cycles
- Memory efficiency: No duplicate data for repeated objects
启用引用跟踪
Java
Fory fory = Fory.builder()
.withLanguage(Language.XLANG)
.withRefTracking(true)
.build();
Python
fory = pyfory.Fory(xlang=True, ref_tracking=True)
Go
fory := forygo.NewFory(true) // true enables ref tracking
C++
auto fory = fory::Fory::create(fory::Config{
.ref_tracking = true
});
Rust
let fory = Fory::builder()
.with_ref_tracking(true)
.build();
线格式
When reference tracking is enabled, nullable fields write a ref flag byte before the value:
[ref_flag] [value data if not null/ref]
Where ref_flag is:
| Value | Meaning |
|---|---|
-1 (NULL_FLAG) | Value is null |
-2 (NOT_NULL_VALUE_FLAG) | Value is present, first occurrence |
≥0 | Reference ID pointing to previously serialized object |
引用跟踪与可空性
These are independent concepts:
| Concept | Purpose | Controlled By |
|---|---|---|
| Nullability | Whether a field can hold null values | Field type (Optional<T>) or annotation |
| Reference Tracking | Whether duplicate objects are deduplicated | Global refTracking option |
Key behavior:
- Ref flag bytes are only written for nullable fields
- Non-nullable fields skip ref flags entirely, even with
refTracking=true - Reference deduplication only applies to objects that appear multiple times
// Reference tracking enabled, but non-nullable fields still skip ref flags
Fory fory = Fory.builder()
.withLanguage(Language.XLANG)
.withRefTracking(true)
.build();
Per-Field Reference Tracking
By default, most fields do not track references even when global refTracking=true. Only specific pointer/smart pointer types track references by default.
默认行为 by Language
| Language | Default Ref Tracking | Types That Track Refs by Default |
|---|---|---|
| Java | No | None (use annotation to enable) |
| Python | No | None (use annotation to enable) |
| Go | No | None (use fory:"ref" to enable) |
| C++ | No | std::shared_ptr<T> |
| Rust | No | Rc<T>, Arc<T>, Weak<T> |
Customizing Per-Field Ref Tracking
Java: @ForyField Annotation
public class Document {
// Default: no ref tracking
String title;
// Enable ref tracking for this field
@ForyField(trackingRef = true)
Author author;
// Shared across documents, track refs to avoid duplicates
@ForyField(trackingRef = true)
List<Tag> tags;
}