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.git
The following commit(s) were added to refs/heads/main by this push:
new e62e18e6e fix(java): optimize type resolver calls for xlang mode on
graalvm (#3129)
e62e18e6e is described below
commit e62e18e6e106e9ead7169356afb00d2ded17767e
Author: Shawn Yang <[email protected]>
AuthorDate: Mon Jan 12 16:30:04 2026 +0800
fix(java): optimize type resolver calls for xlang mode on graalvm (#3129)
## Why?
## What does this PR do?
## Related issues
#3126
## Does this PR introduce any user-facing change?
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
---
.../fory/builder/BaseObjectCodecBuilder.java | 22 ++++++++++++----------
.../java/org/apache/fory/builder/CodecUtils.java | 6 +++---
.../org/apache/fory/resolver/XtypeResolver.java | 20 ++++++++------------
.../fory/serializer/DeferedLazySerializer.java | 4 ++--
.../fory-core/native-image.properties | 2 +-
java/fory-simd/pom.xml | 2 +-
java/pom.xml | 2 +-
kotlin/pom.xml | 2 +-
8 files changed, 29 insertions(+), 31 deletions(-)
diff --git
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
index c359d2ea7..53a338ec3 100644
---
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
+++
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
@@ -185,9 +185,6 @@ public abstract class BaseObjectCodecBuilder extends
CodecBuilder {
super(new CodegenContext(), beanType);
this.fory = fory;
typeResolver = fory._getTypeResolver();
- // Use TypeResolver interface instead of concrete class to support both
xlang and non-xlang
- // modes
- TypeRef<?> typeResolverType = TypeRef.of(TypeResolver.class);
this.parentSerializerClass = parentSerializerClass;
if (fory.isCrossLanguage()) {
writeMethodName = "xwrite";
@@ -199,7 +196,7 @@ public abstract class BaseObjectCodecBuilder extends
CodecBuilder {
addCommonImports();
ctx.reserveName(REF_RESOLVER_NAME);
ctx.reserveName(TYPE_RESOLVER_NAME);
- typeResolverRef = fieldRef(TYPE_RESOLVER_NAME, typeResolverType);
+ // use concrete type to avoid virtual methods call in generated code
TypeRef<?> refResolverTypeRef =
TypeRef.of(fory.getRefResolver().getClass());
refResolverRef = fieldRef(REF_RESOLVER_NAME, refResolverTypeRef);
Expression refResolverExpr =
@@ -208,8 +205,13 @@ public abstract class BaseObjectCodecBuilder extends
CodecBuilder {
ctx.type(refResolverTypeRef),
REF_RESOLVER_NAME,
new Cast(refResolverExpr, refResolverTypeRef));
+ // use concrete type to avoid virtual methods call in generated code
+ TypeRef<?> typeResolverType = TypeRef.of(typeResolver.getClass());
+ typeResolverRef = fieldRef(TYPE_RESOLVER_NAME, typeResolverType);
Expression typeResolverExpr =
- inlineInvoke(foryRef, "_getTypeResolver",
TypeRef.of(TypeResolver.class));
+ cast(
+ inlineInvoke(foryRef, "_getTypeResolver",
TypeRef.of(TypeResolver.class)),
+ typeResolverType);
ctx.addField(ctx.type(typeResolverType), TYPE_RESOLVER_NAME,
typeResolverExpr);
ctx.reserveName(STRING_SERIALIZER_NAME);
stringSerializerRef = fieldRef(STRING_SERIALIZER_NAME,
STRING_SERIALIZER_TYPE_TOKEN);
@@ -227,6 +229,11 @@ public abstract class BaseObjectCodecBuilder extends
CodecBuilder {
public String codecClassName(Class<?> beanClass) {
String name =
ReflectionUtils.getClassNameWithoutPackage(beanClass).replace("$", "_");
StringBuilder nameBuilder = new StringBuilder(name);
+ if (fory.isCrossLanguage()) {
+ // Generated classes are different when xlang mode is enabled.
+ // So we need to use a different name to generate xwrite/xread methods.
+ nameBuilder.append("Xlang");
+ }
if (fory.trackingRef()) {
// Generated classes are different when referenceTracking is switched.
// So we need to use a different name.
@@ -234,11 +241,6 @@ public abstract class BaseObjectCodecBuilder extends
CodecBuilder {
} else {
nameBuilder.append("Fory");
}
- if (fory.isCrossLanguage()) {
- // Generated classes are different when xlang mode is enabled.
- // So we need to use a different name to generate xwrite/xread methods.
- nameBuilder.append("Xlang");
- }
nameBuilder.append("Codec").append(codecSuffix());
Map<String, Integer> subGenerator =
idGenerator.computeIfAbsent(nameBuilder.toString(), k -> new
ConcurrentHashMap<>());
diff --git
a/java/fory-core/src/main/java/org/apache/fory/builder/CodecUtils.java
b/java/fory-core/src/main/java/org/apache/fory/builder/CodecUtils.java
index 6f58545aa..3f940e529 100644
--- a/java/fory-core/src/main/java/org/apache/fory/builder/CodecUtils.java
+++ b/java/fory-core/src/main/java/org/apache/fory/builder/CodecUtils.java
@@ -35,11 +35,11 @@ import org.apache.fory.util.GraalvmSupport;
import org.apache.fory.util.Preconditions;
/** Codec util to create and load jit serializer class. */
-@SuppressWarnings("rawtypes")
+@SuppressWarnings({"rawtypes", "unchecked"})
public class CodecUtils {
// Cache key includes configHash to distinguish between xlang and non-xlang
modes
- private static ConcurrentHashMap<Tuple3<String, Class<?>, Integer>, Class>
graalvmSerializers =
- new ConcurrentHashMap<>();
+ private static final ConcurrentHashMap<Tuple3<String, Class<?>, Integer>,
Class>
+ graalvmSerializers = new ConcurrentHashMap<>();
// TODO(chaokunyang) how to uninstall org.apache.fory.codegen/builder
classes for graalvm build
// time
diff --git
a/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
b/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
index 06fc666c6..a4a4eab4b 100644
--- a/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
+++ b/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
@@ -72,7 +72,8 @@ import org.apache.fory.meta.MetaString;
import org.apache.fory.reflect.ReflectionUtils;
import org.apache.fory.reflect.TypeRef;
import org.apache.fory.serializer.ArraySerializers;
-import
org.apache.fory.serializer.DeferedLazySerializer.DeferedLazyObjectSerializer;
+import org.apache.fory.serializer.DeferedLazySerializer;
+import
org.apache.fory.serializer.DeferedLazySerializer.DeferredLazyObjectSerializer;
import org.apache.fory.serializer.EnumSerializer;
import org.apache.fory.serializer.NonexistentClass;
import org.apache.fory.serializer.NonexistentClass.NonexistentMetaShared;
@@ -265,18 +266,11 @@ public class XtypeResolver extends TypeResolver {
if (serializer == null) {
if (type.isEnum()) {
classInfo.serializer = new EnumSerializer(fory, (Class<Enum>) type);
- } else if (GraalvmSupport.isGraalBuildtime()) {
- // For GraalVM build time, directly create the serializer to avoid
- // issues with DeferedLazySerializer persistence in native image
- Class<? extends Serializer> c =
- classResolver.getObjectSerializerClass(
- type, shareMeta, fory.getConfig().isCodeGenEnabled(), null);
- classInfo.serializer = Serializers.newSerializer(fory, type, c);
} else {
AtomicBoolean updated = new AtomicBoolean(false);
AtomicReference<Serializer> ref = new AtomicReference(null);
classInfo.serializer =
- new DeferedLazyObjectSerializer(
+ new DeferedLazySerializer.DeferredLazyObjectSerializer(
fory,
type,
() -> {
@@ -327,7 +321,7 @@ public class XtypeResolver extends TypeResolver {
if (serializer instanceof ObjectSerializer || serializer instanceof
GeneratedSerializer) {
return true;
}
- return serializer instanceof DeferedLazyObjectSerializer;
+ return serializer instanceof DeferredLazyObjectSerializer;
}
private ClassInfo newClassInfo(Class<?> type, Serializer<?> serializer, int
xtypeId) {
@@ -1047,8 +1041,10 @@ public class XtypeResolver extends TypeResolver {
GraalvmSupport.registerClass(cls, fory.getConfig().getConfigHash());
if (classInfo.serializer != null) {
// Trigger serializer initialization and resolution for deferred
serializers
- if (classInfo.serializer instanceof DeferedLazyObjectSerializer) {
- ((DeferedLazyObjectSerializer)
classInfo.serializer).resolveSerializer();
+ if (classInfo.serializer
+ instanceof DeferedLazySerializer.DeferredLazyObjectSerializer)
{
+ ((DeferedLazySerializer.DeferredLazyObjectSerializer)
classInfo.serializer)
+ .resolveSerializer();
} else {
classInfo.serializer.getClass();
}
diff --git
a/java/fory-core/src/main/java/org/apache/fory/serializer/DeferedLazySerializer.java
b/java/fory-core/src/main/java/org/apache/fory/serializer/DeferedLazySerializer.java
index aa75223c6..636a00ba6 100644
---
a/java/fory-core/src/main/java/org/apache/fory/serializer/DeferedLazySerializer.java
+++
b/java/fory-core/src/main/java/org/apache/fory/serializer/DeferedLazySerializer.java
@@ -83,8 +83,8 @@ public class DeferedLazySerializer extends Serializer {
return getSerializer().copy(value);
}
- public static class DeferedLazyObjectSerializer extends
DeferedLazySerializer {
- public DeferedLazyObjectSerializer(
+ public static class DeferredLazyObjectSerializer extends
DeferedLazySerializer {
+ public DeferredLazyObjectSerializer(
Fory fory, Class type, Supplier<Tuple2<Boolean, Serializer>>
serializerSupplier) {
super(fory, type, serializerSupplier);
}
diff --git
a/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/native-image.properties
b/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/native-image.properties
index a669aae69..4d4dbc324 100644
---
a/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/native-image.properties
+++
b/java/fory-core/src/main/resources/META-INF/native-image/org.apache.fory/fory-core/native-image.properties
@@ -464,7 +464,7 @@
Args=--initialize-at-build-time=org.apache.fory.memory.MemoryBuffer,\
org.apache.fory.serializer.LazySerializer,\
org.apache.fory.serializer.LazySerializer$LazyObjectSerializer,\
org.apache.fory.serializer.DeferedLazySerializer,\
-
org.apache.fory.serializer.DeferedLazySerializer$DeferedLazyObjectSerializer,\
+
org.apache.fory.serializer.DeferedLazySerializer$DeferredLazyObjectSerializer,\
org.apache.fory.serializer.shim.ShimDispatcher,\
org.apache.fory.serializer.shim.ProtobufDispatcher,\
org.apache.fory.serializer.converter.FieldConverter,\
diff --git a/java/fory-simd/pom.xml b/java/fory-simd/pom.xml
index 152693120..e63a2e93e 100644
--- a/java/fory-simd/pom.xml
+++ b/java/fory-simd/pom.xml
@@ -73,7 +73,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <version>3.2.5</version>
+ <version>3.5.4</version>
<configuration>
<argLine>--add-modules=jdk.incubator.vector</argLine>
</configuration>
diff --git a/java/pom.xml b/java/pom.xml
index cd449cb7d..9104c3294 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -217,7 +217,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <version>3.2.5</version>
+ <version>3.5.4</version>
</plugin>
<plugin>
diff --git a/kotlin/pom.xml b/kotlin/pom.xml
index e27a33ad4..b0e8dacff 100644
--- a/kotlin/pom.xml
+++ b/kotlin/pom.xml
@@ -165,7 +165,7 @@
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
- <version>3.2.5</version>
+ <version>3.5.4</version>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]