This is an automated email from the ASF dual-hosted git repository.
pandalee pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fury.git
The following commit(s) were added to refs/heads/main by this push:
new fcdf7787 fix(java): use registered id to sort fields (#2115)
fcdf7787 is described below
commit fcdf77875395dad17b5328c7f721e4adf1384e99
Author: Shawn Yang <[email protected]>
AuthorDate: Sun Mar 23 19:58:19 2025 +0800
fix(java): use registered id to sort fields (#2115)
## What does this PR do?
<!-- Describe the purpose of this PR. -->
## Related issues
Closes #2093
## Does this PR introduce any user-facing change?
<!--
If any user-facing interface changes, please [open an
issue](https://github.com/apache/fury/issues/new/choose) describing the
need to do so and update the document if necessary.
-->
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
<!--
When the PR has an impact on performance (if you don't know whether the
PR will have an impact on performance, you can submit the PR first, and
if it will have impact on performance, the code reviewer will explain
it), be sure to attach a benchmark data here.
-->
---
.../main/java/org/apache/fury/meta/ClassDef.java | 8 ++-
.../org/apache/fury/resolver/ClassResolver.java | 17 +++++
.../fury/serializer/MetaSharedCompatibleTest.java | 82 ++++++++++++++++++++++
3 files changed, 106 insertions(+), 1 deletion(-)
diff --git a/java/fury-core/src/main/java/org/apache/fury/meta/ClassDef.java
b/java/fury-core/src/main/java/org/apache/fury/meta/ClassDef.java
index 6f213436..212ddc29 100644
--- a/java/fury-core/src/main/java/org/apache/fury/meta/ClassDef.java
+++ b/java/fury-core/src/main/java/org/apache/fury/meta/ClassDef.java
@@ -237,10 +237,16 @@ public class ClassDef implements Serializable {
Descriptor descriptor =
descriptorsMap.get(fieldInfo.getDefinedClass() + "." +
fieldInfo.getFieldName());
Descriptor newDesc = fieldInfo.toDescriptor(resolver);
+ Class<?> rawType = newDesc.getRawType();
+ if (resolver.isRegistered(rawType)) {
+ String typeAlias = resolver.getTypeAlias(rawType);
+ if (!typeAlias.equals(newDesc.getTypeName())) {
+ newDesc = newDesc.copyWithTypeName(typeAlias);
+ }
+ }
if (descriptor != null) {
// Make DescriptorGrouper have consistent order whether field exist
or not
// fury builtin types skip
- Class<?> rawType = newDesc.getRawType();
if (rawType.isEnum()
|| rawType.isAssignableFrom(descriptor.getRawType())
|| NonexistentClass.isNonexistent(rawType)
diff --git
a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java
b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java
index 28ed27d6..522bf310 100644
--- a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java
+++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java
@@ -536,6 +536,11 @@ public class ClassResolver {
}
}
+ public boolean isRegistered(Class<?> cls) {
+ return extRegistry.registeredClassIdMap.containsKey(cls)
+ || extRegistry.registeredClasses.inverse().containsKey(cls);
+ }
+
public boolean isRegisteredById(Class<?> cls) {
return extRegistry.registeredClassIdMap.get(cls) != null;
}
@@ -561,6 +566,18 @@ public class ClassResolver {
.collect(Collectors.toList());
}
+ public String getTypeAlias(Class<?> cls) {
+ Short id = extRegistry.registeredClassIdMap.get(cls);
+ if (id != null) {
+ return String.valueOf(id);
+ }
+ String name = extRegistry.registeredClasses.inverse().get(cls);
+ if (name != null) {
+ return name;
+ }
+ return cls.getName();
+ }
+
/**
* Mark non-inner registered final types as non-final to write class def for
those types. Note if
* a class is registered but not an inner class with inner serializer, it
will still be taken as
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/MetaSharedCompatibleTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/MetaSharedCompatibleTest.java
index 8a4eb683..60e15e8b 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/MetaSharedCompatibleTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/MetaSharedCompatibleTest.java
@@ -31,6 +31,8 @@ import java.util.stream.Collectors;
import org.apache.fury.Fury;
import org.apache.fury.FuryTestBase;
import org.apache.fury.builder.MetaSharedCodecBuilder;
+import org.apache.fury.codegen.CompileUnit;
+import org.apache.fury.codegen.JaninoUtils;
import org.apache.fury.config.CompatibleMode;
import org.apache.fury.config.FuryBuilder;
import org.apache.fury.config.Language;
@@ -673,4 +675,84 @@ public class MetaSharedCompatibleTest extends FuryTestBase
{
.InnerClassTestLengthInnerClassTestLengthInnerClassTestLength();
serDeCheck(fury, o);
}
+
+ @Test
+ public void testRegisterToSameIdForRenamedClass() throws Exception {
+ CompileUnit unit1 =
+ new CompileUnit(
+ "demo.pkg1",
+ "A",
+ (""
+ + "package demo.pkg1;\n"
+ + "import demo.test.*;\n"
+ + "import demo.report.*;\n"
+ + "public class A {\n"
+ + " int f1;\n"
+ + " B f2;\n"
+ + " C f3;\n"
+ + " public String toString() {return \"A\" + \",\" + f1 +
\",\" + f2 + \",\" + f3;}\n"
+ + " public static A create() { A a = new A(); a.f1 = 10; a.f2
= new B(); a.f3 = new C(); return a;}\n"
+ + "}"));
+ CompileUnit unit2 =
+ new CompileUnit(
+ "demo.test", "B", ("" + "package demo.test;\n" + "public class B
{\n" + "}"));
+ CompileUnit unit3 =
+ new CompileUnit(
+ "demo.report", "C", ("" + "package demo.report;\n" + "public class
C {\n" + "}"));
+ ClassLoader classLoader =
+ JaninoUtils.compile(Thread.currentThread().getContextClassLoader(),
unit1, unit2, unit3);
+ byte[] serialized;
+ {
+ Class<?> A = classLoader.loadClass("demo.pkg1.A");
+ Class<?> B = classLoader.loadClass("demo.test.B");
+ Class<?> C = classLoader.loadClass("demo.report.C");
+ Fury fury =
builder().withCompatibleMode(CompatibleMode.COMPATIBLE).build();
+ fury.register(A);
+ fury.register(B);
+ fury.register(C);
+ Object a = A.getMethod("create").invoke(null);
+ System.out.println(a);
+ serialized = fury.serialize(a);
+ }
+ {
+ unit1 =
+ new CompileUnit(
+ "example.pkg1",
+ "A",
+ (""
+ + "package example.pkg1;\n"
+ + "import example.test.*;\n"
+ + "import example.report.*;\n"
+ + "public class A {\n"
+ + " int f1;\n"
+ + " B f2;\n"
+ + " C f3;\n"
+ + " public String toString() {return \"A\" + \",\" + f1 +
\",\" + f2 + \",\" + f3;}\n"
+ + " public static A create() { A a = new A(); a.f1 = 10;
a.f2 = new B(); a.f3 = new C(); return a;}\n"
+ + "}"));
+ unit2 =
+ new CompileUnit(
+ "example.report",
+ "B",
+ ("" + "package example.report;\n" + "public class B {\n" + "}"));
+ unit3 =
+ new CompileUnit(
+ "example.test", "C", ("" + "package example.test;\n" + "public
class C {\n" + "}"));
+ classLoader =
+ JaninoUtils.compile(Thread.currentThread().getContextClassLoader(),
unit1, unit2, unit3);
+ Class<?> A = classLoader.loadClass("example.pkg1.A");
+ Class<?> B = classLoader.loadClass("example.report.B");
+ Class<?> C = classLoader.loadClass("example.test.C");
+ Fury fury =
+ builder()
+ .withCompatibleMode(CompatibleMode.COMPATIBLE)
+ .withClassLoader(classLoader)
+ .build();
+ fury.register(A);
+ fury.register(B);
+ fury.register(C);
+ Object newObj = fury.deserialize(serialized);
+ System.out.println(newObj);
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]