diff --git a/java/fury-core/src/main/java/org/apache/fury/Fury.java b/java/fury-core/src/main/java/org/apache/fury/Fury.java index 3dc1c16b3d..954ba87887 100644 --- a/java/fury-core/src/main/java/org/apache/fury/Fury.java +++ b/java/fury-core/src/main/java/org/apache/fury/Fury.java @@ -39,6 +39,7 @@ import org.apache.fury.config.LongEncoding; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.MemoryUtils; +import org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassInfoHolder; import org.apache.fury.resolver.ClassResolver; @@ -514,35 +515,35 @@ public void xwriteNonRef(MemoryBuffer buffer, T obj, Serializer serialize /** Write not null data to buffer. */ private void writeData(MemoryBuffer buffer, ClassInfo classInfo, Object obj) { switch (classInfo.getClassId()) { - case ClassResolver.BOOLEAN_CLASS_ID: + case BuiltinClassId.BOOLEAN_CLASS_ID: buffer.writeBoolean((Boolean) obj); break; - case ClassResolver.BYTE_CLASS_ID: + case BuiltinClassId.BYTE_CLASS_ID: buffer.writeByte((Byte) obj); break; - case ClassResolver.CHAR_CLASS_ID: + case BuiltinClassId.CHAR_CLASS_ID: buffer.writeChar((Character) obj); break; - case ClassResolver.SHORT_CLASS_ID: + case BuiltinClassId.SHORT_CLASS_ID: buffer.writeShort((Short) obj); break; - case ClassResolver.INTEGER_CLASS_ID: + case BuiltinClassId.INTEGER_CLASS_ID: if (compressInt) { buffer.writeVarInt((Integer) obj); } else { buffer.writeInt((Integer) obj); } break; - case ClassResolver.FLOAT_CLASS_ID: + case BuiltinClassId.FLOAT_CLASS_ID: buffer.writeFloat((Float) obj); break; - case ClassResolver.LONG_CLASS_ID: + case BuiltinClassId.LONG_CLASS_ID: LongSerializer.writeLong(buffer, (Long) obj, longEncoding); break; - case ClassResolver.DOUBLE_CLASS_ID: + case BuiltinClassId.DOUBLE_CLASS_ID: buffer.writeDouble((Double) obj); break; - case ClassResolver.STRING_CLASS_ID: + case BuiltinClassId.STRING_CLASS_ID: stringSerializer.writeJavaString(buffer, (String) obj); break; // TODO(add fastpath for other types) @@ -870,27 +871,27 @@ public Object readData(MemoryBuffer buffer, ClassInfo classInfo) { private Object readDataInternal(MemoryBuffer buffer, ClassInfo classInfo) { switch (classInfo.getClassId()) { - case ClassResolver.BOOLEAN_CLASS_ID: + case BuiltinClassId.BOOLEAN_CLASS_ID: return buffer.readBoolean(); - case ClassResolver.BYTE_CLASS_ID: + case BuiltinClassId.BYTE_CLASS_ID: return buffer.readByte(); - case ClassResolver.CHAR_CLASS_ID: + case BuiltinClassId.CHAR_CLASS_ID: return buffer.readChar(); - case ClassResolver.SHORT_CLASS_ID: + case BuiltinClassId.SHORT_CLASS_ID: return buffer.readShort(); - case ClassResolver.INTEGER_CLASS_ID: + case BuiltinClassId.INTEGER_CLASS_ID: if (compressInt) { return buffer.readVarInt(); } else { return buffer.readInt(); } - case ClassResolver.FLOAT_CLASS_ID: + case BuiltinClassId.FLOAT_CLASS_ID: return buffer.readFloat(); - case ClassResolver.LONG_CLASS_ID: + case BuiltinClassId.LONG_CLASS_ID: return LongSerializer.readLong(buffer, longEncoding); - case ClassResolver.DOUBLE_CLASS_ID: + case BuiltinClassId.DOUBLE_CLASS_ID: return buffer.readDouble(); - case ClassResolver.STRING_CLASS_ID: + case BuiltinClassId.STRING_CLASS_ID: return stringSerializer.readJavaString(buffer); // TODO(add fastpath for other types) default: diff --git a/java/fury-core/src/main/java/org/apache/fury/builder/CompatibleCodecBuilder.java b/java/fury-core/src/main/java/org/apache/fury/builder/CompatibleCodecBuilder.java index 50117db0a3..f13a325f4d 100644 --- a/java/fury-core/src/main/java/org/apache/fury/builder/CompatibleCodecBuilder.java +++ b/java/fury-core/src/main/java/org/apache/fury/builder/CompatibleCodecBuilder.java @@ -65,8 +65,8 @@ import org.apache.fury.codegen.ExpressionOptimizer; import org.apache.fury.codegen.ExpressionUtils; import org.apache.fury.collection.Tuple2; +import org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import org.apache.fury.resolver.ClassInfo; -import org.apache.fury.resolver.ClassResolver; import org.apache.fury.resolver.FieldResolver; import org.apache.fury.resolver.FieldResolver.CollectionFieldInfo; import org.apache.fury.resolver.FieldResolver.FieldInfo; @@ -879,7 +879,7 @@ protected Expression getFinalClassInfo(Class cls) { protected Expression writeFinalClassInfo(Expression buffer, Class cls) { Preconditions.checkArgument(ReflectionUtils.isMonomorphic(cls)); ClassInfo classInfo = visitFury(f -> f.getClassResolver().getClassInfo(cls, false)); - if (classInfo != null && classInfo.getClassId() != ClassResolver.NO_CLASS_ID) { + if (classInfo != null && classInfo.getClassId() != BuiltinClassId.NO_CLASS_ID) { return fury.getClassResolver().writeClassExpr(buffer, classInfo.getClassId()); } Expression classInfoExpr = getFinalClassInfo(cls); @@ -889,7 +889,7 @@ protected Expression writeFinalClassInfo(Expression buffer, Class cls) { protected Expression skipFinalClassInfo(Class cls, Expression buffer) { Preconditions.checkArgument(ReflectionUtils.isMonomorphic(cls)); ClassInfo classInfo = visitFury(f -> f.getClassResolver().getClassInfo(cls, false)); - if (classInfo != null && classInfo.getClassId() != ClassResolver.NO_CLASS_ID) { + if (classInfo != null && classInfo.getClassId() != BuiltinClassId.NO_CLASS_ID) { return fury.getClassResolver().skipRegisteredClassExpr(buffer); } // read `ClassInfo` is not used, set `inlineReadClassInfo` false, diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassIdAllocator.java b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassIdAllocator.java new file mode 100644 index 0000000000..c5a7ceaa2c --- /dev/null +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassIdAllocator.java @@ -0,0 +1,115 @@ +/* + * 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. + */ + +package org.apache.fury.resolver; + +import java.util.function.Function; +import org.apache.fury.util.Preconditions; + +/** Responsible for allocating ClassId and maintaining built-in ClassId. */ +public class ClassIdAllocator { + public static class BuiltinClassId { + // preserve 0 as flag for class id not set in ClassInfo` + public static final short NO_CLASS_ID = (short) 0; + public static final short LAMBDA_STUB_ID = 1; + public static final short JDK_PROXY_STUB_ID = 2; + public static final short REPLACE_STUB_ID = 3; + // Note: following pre-defined class id should be continuous, since they may be used based + // range. + public static final short PRIMITIVE_VOID_CLASS_ID = (short) (REPLACE_STUB_ID + 1); + public static final short PRIMITIVE_BOOLEAN_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 1); + public static final short PRIMITIVE_BYTE_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 2); + public static final short PRIMITIVE_CHAR_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 3); + public static final short PRIMITIVE_SHORT_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 4); + public static final short PRIMITIVE_INT_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 5); + public static final short PRIMITIVE_FLOAT_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 6); + public static final short PRIMITIVE_LONG_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 7); + public static final short PRIMITIVE_DOUBLE_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 8); + public static final short VOID_CLASS_ID = (short) (PRIMITIVE_DOUBLE_CLASS_ID + 1); + public static final short BOOLEAN_CLASS_ID = (short) (VOID_CLASS_ID + 1); + public static final short BYTE_CLASS_ID = (short) (VOID_CLASS_ID + 2); + public static final short CHAR_CLASS_ID = (short) (VOID_CLASS_ID + 3); + public static final short SHORT_CLASS_ID = (short) (VOID_CLASS_ID + 4); + public static final short INTEGER_CLASS_ID = (short) (VOID_CLASS_ID + 5); + public static final short FLOAT_CLASS_ID = (short) (VOID_CLASS_ID + 6); + public static final short LONG_CLASS_ID = (short) (VOID_CLASS_ID + 7); + public static final short DOUBLE_CLASS_ID = (short) (VOID_CLASS_ID + 8); + public static final short STRING_CLASS_ID = (short) (VOID_CLASS_ID + 9); + public static final short PRIMITIVE_BOOLEAN_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 1); + public static final short PRIMITIVE_BYTE_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 2); + public static final short PRIMITIVE_CHAR_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 3); + public static final short PRIMITIVE_SHORT_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 4); + public static final short PRIMITIVE_INT_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 5); + public static final short PRIMITIVE_FLOAT_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 6); + public static final short PRIMITIVE_LONG_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 7); + public static final short PRIMITIVE_DOUBLE_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 8); + public static final short STRING_ARRAY_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 1); + public static final short OBJECT_ARRAY_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 2); + public static final short ARRAYLIST_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 3); + public static final short HASHMAP_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 4); + public static final short HASHSET_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 5); + public static final short CLASS_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 6); + public static final short EMPTY_OBJECT_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 7); + } + + // class id of last default registered class. + private short innerEndClassId; + // Here we set it to 1 because `NO_CLASS_ID` is 0 to avoid calculating it again in + // `register(Class cls)`. + private short classIdGenerator = 1; + + private final Function, Boolean> classRegisteredFactory; + + private final Function classIdRegisteredFactory; + + public ClassIdAllocator( + Function, Boolean> classRegisteredFactory, + Function classIdRegisteredFactory) { + Preconditions.checkNotNull(classRegisteredFactory); + Preconditions.checkNotNull(classIdRegisteredFactory); + this.classRegisteredFactory = classRegisteredFactory; + this.classIdRegisteredFactory = classIdRegisteredFactory; + } + + public short allocateClassId(Class cls) { + if (!classRegisteredFactory.apply(cls)) { + while (classIdRegisteredFactory.apply(classIdGenerator)) { + classIdGenerator++; + } + } + return classIdGenerator; + } + + public void notifyRegistrationEnd() { + classIdGenerator++; + } + + public void markInternalRegistrationEnd() { + innerEndClassId = classIdGenerator; + } + + public boolean isInnerClass(Short classId) { + return classId != null && classId != BuiltinClassId.NO_CLASS_ID && classId < innerEndClassId; + } + + public boolean isPrimitive(short classId) { + return classId >= BuiltinClassId.PRIMITIVE_VOID_CLASS_ID + && classId <= BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID; + } +} diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassInfo.java b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassInfo.java index 712c456a5a..75676ecf0d 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassInfo.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassInfo.java @@ -58,7 +58,7 @@ public class ClassInfo { this.typeTagBytes = typeTagBytes; this.serializer = serializer; this.classId = classId; - if (cls != null && classId == ClassResolver.NO_CLASS_ID) { + if (cls != null && classId == ClassIdAllocator.BuiltinClassId.NO_CLASS_ID) { Preconditions.checkArgument(classNameBytes != null); } } @@ -78,7 +78,8 @@ public class ClassInfo { this.fullClassNameBytes = null; } if (cls != null - && (classId == ClassResolver.NO_CLASS_ID || classId == ClassResolver.REPLACE_STUB_ID)) { + && (classId == ClassIdAllocator.BuiltinClassId.NO_CLASS_ID + || classId == ClassIdAllocator.BuiltinClassId.REPLACE_STUB_ID)) { // REPLACE_STUB_ID for write replace class in `ClassSerializer`. String packageName = ReflectionUtils.getPackage(cls); this.packageNameBytes = enumStringResolver.getOrCreateEnumStringBytes(packageName); @@ -100,10 +101,10 @@ public class ClassInfo { boolean isProxy = ReflectionUtils.isJdkProxy(cls); this.isDynamicGeneratedClass = isLambda || isProxy; if (isLambda) { - this.classId = ClassResolver.LAMBDA_STUB_ID; + this.classId = ClassIdAllocator.BuiltinClassId.LAMBDA_STUB_ID; } if (isProxy) { - this.classId = ClassResolver.JDK_PROXY_STUB_ID; + this.classId = ClassIdAllocator.BuiltinClassId.JDK_PROXY_STUB_ID; } } else { this.isDynamicGeneratedClass = false; 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 4f04f3bb63..2efa8471da 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 @@ -21,6 +21,7 @@ import static org.apache.fury.codegen.Expression.Invoke.inlineInvoke; import static org.apache.fury.codegen.ExpressionUtils.eq; +import static org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import static org.apache.fury.serializer.CodegenSerializer.loadCodegenSerializer; import static org.apache.fury.serializer.CodegenSerializer.loadCompatibleCodegenSerializer; import static org.apache.fury.serializer.CodegenSerializer.supportCodegenForJavaSerialization; @@ -156,55 +157,14 @@ public class ClassResolver { // bit 0 unset indicates class is written as an id. public static final byte USE_CLASS_VALUE_FLAG = 0b1; // preserve 0 as flag for class id not set in ClassInfo` - public static final short NO_CLASS_ID = (short) 0; - public static final short LAMBDA_STUB_ID = 1; - public static final short JDK_PROXY_STUB_ID = 2; - public static final short REPLACE_STUB_ID = 3; - // Note: following pre-defined class id should be continuous, since they may be used based range. - public static final short PRIMITIVE_VOID_CLASS_ID = (short) (REPLACE_STUB_ID + 1); - public static final short PRIMITIVE_BOOLEAN_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 1); - public static final short PRIMITIVE_BYTE_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 2); - public static final short PRIMITIVE_CHAR_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 3); - public static final short PRIMITIVE_SHORT_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 4); - public static final short PRIMITIVE_INT_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 5); - public static final short PRIMITIVE_FLOAT_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 6); - public static final short PRIMITIVE_LONG_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 7); - public static final short PRIMITIVE_DOUBLE_CLASS_ID = (short) (PRIMITIVE_VOID_CLASS_ID + 8); - public static final short VOID_CLASS_ID = (short) (PRIMITIVE_DOUBLE_CLASS_ID + 1); - public static final short BOOLEAN_CLASS_ID = (short) (VOID_CLASS_ID + 1); - public static final short BYTE_CLASS_ID = (short) (VOID_CLASS_ID + 2); - public static final short CHAR_CLASS_ID = (short) (VOID_CLASS_ID + 3); - public static final short SHORT_CLASS_ID = (short) (VOID_CLASS_ID + 4); - public static final short INTEGER_CLASS_ID = (short) (VOID_CLASS_ID + 5); - public static final short FLOAT_CLASS_ID = (short) (VOID_CLASS_ID + 6); - public static final short LONG_CLASS_ID = (short) (VOID_CLASS_ID + 7); - public static final short DOUBLE_CLASS_ID = (short) (VOID_CLASS_ID + 8); - public static final short STRING_CLASS_ID = (short) (VOID_CLASS_ID + 9); - public static final short PRIMITIVE_BOOLEAN_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 1); - public static final short PRIMITIVE_BYTE_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 2); - public static final short PRIMITIVE_CHAR_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 3); - public static final short PRIMITIVE_SHORT_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 4); - public static final short PRIMITIVE_INT_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 5); - public static final short PRIMITIVE_FLOAT_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 6); - public static final short PRIMITIVE_LONG_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 7); - public static final short PRIMITIVE_DOUBLE_ARRAY_CLASS_ID = (short) (STRING_CLASS_ID + 8); - public static final short STRING_ARRAY_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 1); - public static final short OBJECT_ARRAY_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 2); - public static final short ARRAYLIST_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 3); - public static final short HASHMAP_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 4); - public static final short HASHSET_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 5); - public static final short CLASS_CLASS_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 6); - public static final short EMPTY_OBJECT_ID = (short) (PRIMITIVE_DOUBLE_ARRAY_CLASS_ID + 7); private static final int initialCapacity = 128; // use a lower load factor to minimize hash collision private static final float loadFactor = 0.25f; private static final float furyMapLoadFactor = 0.25f; private static final String META_SHARE_FIELDS_INFO_KEY = "shareFieldsInfo"; private static final ClassInfo NIL_CLASS_INFO = - new ClassInfo(null, null, null, null, false, null, null, ClassResolver.NO_CLASS_ID); - + new ClassInfo(null, null, null, null, false, null, null, BuiltinClassId.NO_CLASS_ID); private final Fury fury; - private ClassInfo[] registeredId2ClassInfo = new ClassInfo[] {}; // IdentityMap has better lookup performance, when loadFactor is 0.05f, performance is better private final IdentityMap, ClassInfo> classInfoMap = @@ -223,15 +183,11 @@ public class ClassResolver { private final boolean metaContextShareEnabled; private final Map, ClassDef> classDefMap = new HashMap<>(); private Class currentReadClass; - // class id of last default registered class. - private short innerEndClassId; private final ExtRegistry extRegistry; private final ShimDispatcher shimDispatcher; + private final ClassIdAllocator classIdAllocator; private static class ExtRegistry { - // Here we set it to 1 because `NO_CLASS_ID` is 0 to avoid calculating it again in - // `register(Class cls)`. - private short classIdGenerator = 1; private SerializerFactory serializerFactory; private final IdentityMap, Short> registeredClassIdMap = new IdentityMap<>(initialCapacity); @@ -247,6 +203,15 @@ private static class ExtRegistry { private ClassChecker classChecker = (classResolver, className) -> true; private GenericType objectGenericType; private Map, CodeGenerator> codeGeneratorMap = new HashMap<>(); + private ClassInfo[] registeredId2ClassInfo = new ClassInfo[] {}; + + private boolean classRegistered(Class cls) { + return registeredClassIdMap.containsKey(cls); + } + + private boolean classIdRegistered(short classId) { + return classId < registeredId2ClassInfo.length && registeredId2ClassInfo[classId] != null; + } } public ClassResolver(Fury fury) { @@ -257,46 +222,48 @@ public ClassResolver(Fury fury) { extRegistry = new ExtRegistry(); extRegistry.objectGenericType = buildGenericType(OBJECT_TYPE); shimDispatcher = new ShimDispatcher(fury); + classIdAllocator = + new ClassIdAllocator(extRegistry::classRegistered, extRegistry::classIdRegistered); } public void initialize() { - register(LambdaSerializer.ReplaceStub.class, LAMBDA_STUB_ID); - register(JdkProxySerializer.ReplaceStub.class, JDK_PROXY_STUB_ID); - register(ReplaceResolveSerializer.ReplaceStub.class, REPLACE_STUB_ID); - registerWithCheck(void.class, PRIMITIVE_VOID_CLASS_ID); - registerWithCheck(boolean.class, PRIMITIVE_BOOLEAN_CLASS_ID); - registerWithCheck(byte.class, PRIMITIVE_BYTE_CLASS_ID); - registerWithCheck(char.class, PRIMITIVE_CHAR_CLASS_ID); - registerWithCheck(short.class, PRIMITIVE_SHORT_CLASS_ID); - registerWithCheck(int.class, PRIMITIVE_INT_CLASS_ID); - registerWithCheck(float.class, PRIMITIVE_FLOAT_CLASS_ID); - registerWithCheck(long.class, PRIMITIVE_LONG_CLASS_ID); - registerWithCheck(double.class, PRIMITIVE_DOUBLE_CLASS_ID); - registerWithCheck(Void.class, VOID_CLASS_ID); - registerWithCheck(Boolean.class, BOOLEAN_CLASS_ID); - registerWithCheck(Byte.class, BYTE_CLASS_ID); - registerWithCheck(Character.class, CHAR_CLASS_ID); - registerWithCheck(Short.class, SHORT_CLASS_ID); - registerWithCheck(Integer.class, INTEGER_CLASS_ID); - registerWithCheck(Float.class, FLOAT_CLASS_ID); - registerWithCheck(Long.class, LONG_CLASS_ID); - registerWithCheck(Double.class, DOUBLE_CLASS_ID); - registerWithCheck(String.class, STRING_CLASS_ID); - registerWithCheck(boolean[].class, PRIMITIVE_BOOLEAN_ARRAY_CLASS_ID); - registerWithCheck(byte[].class, PRIMITIVE_BYTE_ARRAY_CLASS_ID); - registerWithCheck(char[].class, PRIMITIVE_CHAR_ARRAY_CLASS_ID); - registerWithCheck(short[].class, PRIMITIVE_SHORT_ARRAY_CLASS_ID); - registerWithCheck(int[].class, PRIMITIVE_INT_ARRAY_CLASS_ID); - registerWithCheck(float[].class, PRIMITIVE_FLOAT_ARRAY_CLASS_ID); - registerWithCheck(long[].class, PRIMITIVE_LONG_ARRAY_CLASS_ID); - registerWithCheck(double[].class, PRIMITIVE_DOUBLE_ARRAY_CLASS_ID); - registerWithCheck(String[].class, STRING_ARRAY_CLASS_ID); - registerWithCheck(Object[].class, OBJECT_ARRAY_CLASS_ID); - registerWithCheck(ArrayList.class, ARRAYLIST_CLASS_ID); - registerWithCheck(HashMap.class, HASHMAP_CLASS_ID); - registerWithCheck(HashSet.class, HASHSET_CLASS_ID); - registerWithCheck(Class.class, CLASS_CLASS_ID); - registerWithCheck(Object.class, EMPTY_OBJECT_ID); + register(LambdaSerializer.ReplaceStub.class, BuiltinClassId.LAMBDA_STUB_ID); + register(JdkProxySerializer.ReplaceStub.class, BuiltinClassId.JDK_PROXY_STUB_ID); + register(ReplaceResolveSerializer.ReplaceStub.class, BuiltinClassId.REPLACE_STUB_ID); + registerWithCheck(void.class, BuiltinClassId.PRIMITIVE_VOID_CLASS_ID); + registerWithCheck(boolean.class, BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID); + registerWithCheck(byte.class, BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID); + registerWithCheck(char.class, BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID); + registerWithCheck(short.class, BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID); + registerWithCheck(int.class, BuiltinClassId.PRIMITIVE_INT_CLASS_ID); + registerWithCheck(float.class, BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID); + registerWithCheck(long.class, BuiltinClassId.PRIMITIVE_LONG_CLASS_ID); + registerWithCheck(double.class, BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID); + registerWithCheck(Void.class, BuiltinClassId.VOID_CLASS_ID); + registerWithCheck(Boolean.class, BuiltinClassId.BOOLEAN_CLASS_ID); + registerWithCheck(Byte.class, BuiltinClassId.BYTE_CLASS_ID); + registerWithCheck(Character.class, BuiltinClassId.CHAR_CLASS_ID); + registerWithCheck(Short.class, BuiltinClassId.SHORT_CLASS_ID); + registerWithCheck(Integer.class, BuiltinClassId.INTEGER_CLASS_ID); + registerWithCheck(Float.class, BuiltinClassId.FLOAT_CLASS_ID); + registerWithCheck(Long.class, BuiltinClassId.LONG_CLASS_ID); + registerWithCheck(Double.class, BuiltinClassId.DOUBLE_CLASS_ID); + registerWithCheck(String.class, BuiltinClassId.STRING_CLASS_ID); + registerWithCheck(boolean[].class, BuiltinClassId.PRIMITIVE_BOOLEAN_ARRAY_CLASS_ID); + registerWithCheck(byte[].class, BuiltinClassId.PRIMITIVE_BYTE_ARRAY_CLASS_ID); + registerWithCheck(char[].class, BuiltinClassId.PRIMITIVE_CHAR_ARRAY_CLASS_ID); + registerWithCheck(short[].class, BuiltinClassId.PRIMITIVE_SHORT_ARRAY_CLASS_ID); + registerWithCheck(int[].class, BuiltinClassId.PRIMITIVE_INT_ARRAY_CLASS_ID); + registerWithCheck(float[].class, BuiltinClassId.PRIMITIVE_FLOAT_ARRAY_CLASS_ID); + registerWithCheck(long[].class, BuiltinClassId.PRIMITIVE_LONG_ARRAY_CLASS_ID); + registerWithCheck(double[].class, BuiltinClassId.PRIMITIVE_DOUBLE_ARRAY_CLASS_ID); + registerWithCheck(String[].class, BuiltinClassId.STRING_ARRAY_CLASS_ID); + registerWithCheck(Object[].class, BuiltinClassId.OBJECT_ARRAY_CLASS_ID); + registerWithCheck(ArrayList.class, BuiltinClassId.ARRAYLIST_CLASS_ID); + registerWithCheck(HashMap.class, BuiltinClassId.HASHMAP_CLASS_ID); + registerWithCheck(HashSet.class, BuiltinClassId.HASHSET_CLASS_ID); + registerWithCheck(Class.class, BuiltinClassId.CLASS_CLASS_ID); + registerWithCheck(Object.class, BuiltinClassId.EMPTY_OBJECT_ID); // Register common class ahead to get smaller class id for serialization. // TODO(Liangliang Sui): Clean up duplicately registered Classes and throw exceptions when // Classes are duplicately registered. @@ -304,7 +271,7 @@ public void initialize() { addDefaultSerializers(); registerDefaultClasses(); shimDispatcher.initialize(); - innerEndClassId = extRegistry.classIdGenerator; + classIdAllocator.markInternalRegistrationEnd(); } private void addDefaultSerializers() { @@ -395,13 +362,7 @@ private void registerDefaultClasses() { /** register class. */ public void register(Class cls) { - if (!extRegistry.registeredClassIdMap.containsKey(cls)) { - while (extRegistry.classIdGenerator < registeredId2ClassInfo.length - && registeredId2ClassInfo[extRegistry.classIdGenerator] != null) { - extRegistry.classIdGenerator++; - } - register(cls, extRegistry.classIdGenerator); - } + register(cls, classIdAllocator.allocateClassId(cls)); } public void register(Class... classes) { @@ -437,24 +398,29 @@ public void register(Class cls, int classId) { // class id must be less than Integer.MAX_VALUE/2 since we use bit 0 as class id flag. Preconditions.checkArgument(classId >= 0 && classId < Short.MAX_VALUE); short id = (short) classId; - if (!extRegistry.registeredClassIdMap.containsKey(cls)) { + if (!extRegistry.classRegistered(cls)) { if (extRegistry.registeredClasses.containsKey(cls.getName())) { throw new IllegalArgumentException( String.format( "Class %s with name %s has been registered, registering class with same name are not allowed.", extRegistry.registeredClasses.get(cls.getName()), cls.getName())); } - if (id < registeredId2ClassInfo.length && registeredId2ClassInfo[id] != null) { + if (extRegistry.classIdRegistered(id)) { throw new IllegalArgumentException( String.format( "Class %s with id %s has been registered, registering class %s with same id are not allowed.", - registeredId2ClassInfo[id].getCls(), id, cls.getName())); + extRegistry.registeredId2ClassInfo[id].getCls(), id, cls.getName())); } extRegistry.registeredClassIdMap.put(cls, id); - if (registeredId2ClassInfo.length <= id) { + if (extRegistry.registeredId2ClassInfo.length <= id) { ClassInfo[] tmp = new ClassInfo[(id + 1) * 2]; - System.arraycopy(registeredId2ClassInfo, 0, tmp, 0, registeredId2ClassInfo.length); - registeredId2ClassInfo = tmp; + System.arraycopy( + extRegistry.registeredId2ClassInfo, + 0, + tmp, + 0, + extRegistry.registeredId2ClassInfo.length); + extRegistry.registeredId2ClassInfo = tmp; } ClassInfo classInfo = classInfoMap.get(cls); if (classInfo != null) { @@ -466,9 +432,9 @@ public void register(Class cls, int classId) { classInfoMap.put(cls, classInfo); } // serializer will be set lazily in `addSerializer` method if it's null. - registeredId2ClassInfo[id] = classInfo; + extRegistry.registeredId2ClassInfo[id] = classInfo; extRegistry.registeredClasses.put(cls.getName(), cls); - extRegistry.classIdGenerator++; + classIdAllocator.notifyRegistrationEnd(); } } @@ -481,7 +447,7 @@ public void register(Class cls, Short id, boolean createSerializer) { /** register class with given id. */ public void registerWithCheck(Class cls, short id) { - if (extRegistry.registeredClassIdMap.containsKey(cls)) { + if (extRegistry.classRegistered(cls)) { throw new IllegalArgumentException( String.format( "Class %s already registered with id %s.", @@ -495,8 +461,8 @@ public Short getRegisteredClassId(Class cls) { } public Class getRegisteredClass(short id) { - if (id < registeredId2ClassInfo.length) { - ClassInfo classInfo = registeredId2ClassInfo[id]; + if (id < extRegistry.registeredId2ClassInfo.length) { + ClassInfo classInfo = extRegistry.registeredId2ClassInfo[id]; if (classInfo != null) { return classInfo.cls; } @@ -505,7 +471,7 @@ public Class getRegisteredClass(short id) { } public List> getRegisteredClasses() { - return Arrays.stream(registeredId2ClassInfo) + return Arrays.stream(extRegistry.registeredId2ClassInfo) .filter(Objects::nonNull) .map(info -> info.cls) .collect(Collectors.toList()); @@ -536,7 +502,7 @@ boolean isInnerClass(Class cls) { classId = classInfo.getClassId(); } } - return classId != null && classId != NO_CLASS_ID && classId < innerEndClassId; + return classIdAllocator.isInnerClass(classId); } /** @@ -607,8 +573,7 @@ public void registerSerializer(Class type, Class se * @param serializer serializer for object of {@code type} */ public void registerSerializer(Class type, Serializer serializer) { - if (!extRegistry.registeredClassIdMap.containsKey(type) - && fury.getLanguage() == Language.JAVA) { + if (!extRegistry.classRegistered(type) && fury.getLanguage() == Language.JAVA) { register(type); } addSerializer(type, serializer); @@ -725,12 +690,12 @@ private void addSerializer(Class type, Serializer serializer) { boolean registered = classId != null; // set serializer for class if it's registered by now. if (registered) { - classInfo = registeredId2ClassInfo[classId]; + classInfo = extRegistry.registeredId2ClassInfo[classId]; } else { if (serializer instanceof ReplaceResolveSerializer) { - classId = REPLACE_STUB_ID; + classId = BuiltinClassId.REPLACE_STUB_ID; } else { - classId = NO_CLASS_ID; + classId = BuiltinClassId.NO_CLASS_ID; } classInfo = classInfoMap.get(type); } @@ -739,7 +704,7 @@ private void addSerializer(Class type, Serializer serializer) { classInfo = new ClassInfo(this, type, typeTag, null, classId); classInfoMap.put(type, classInfo); if (registered) { - registeredId2ClassInfo[classId] = classInfo; + extRegistry.registeredId2ClassInfo[classId] = classInfo; } } @@ -1059,7 +1024,7 @@ public boolean needToWriteRef(Class cls) { } public ClassInfo getClassInfo(short classId) { - ClassInfo classInfo = registeredId2ClassInfo[classId]; + ClassInfo classInfo = extRegistry.registeredId2ClassInfo[classId]; if (classInfo.serializer == null) { addSerializer(classInfo.cls, createSerializer(classInfo.cls)); classInfo = classInfoMap.get(classInfo.cls); @@ -1127,7 +1092,7 @@ public ClassInfo getOrUpdateClassInfo(Class cls) { private ClassInfo getOrUpdateClassInfo(short classId) { ClassInfo classInfo = classInfoCache; if (classInfo.classId != classId) { - classInfo = registeredId2ClassInfo[classId]; + classInfo = extRegistry.registeredId2ClassInfo[classId]; if (classInfo.serializer == null) { addSerializer(classInfo.cls, createSerializer(classInfo.cls)); classInfo = classInfoMap.get(classInfo.cls); @@ -1167,7 +1132,7 @@ private Serializer createSerializer(Class cls) { if (!fury.getConfig().suppressClassRegistrationWarnings() && !Functions.isLambda(cls) && !ReflectionUtils.isJdkProxy(cls) - && !extRegistry.registeredClassIdMap.containsKey(cls) + && !extRegistry.classRegistered(cls) && !shimDispatcher.contains(cls)) { LOG.warn(msg); } @@ -1190,7 +1155,7 @@ private Serializer createSerializer(Class cls) { } private boolean isSecure(Class cls) { - if (extRegistry.registeredClassIdMap.containsKey(cls) || shimDispatcher.contains(cls)) { + if (extRegistry.classRegistered(cls) || shimDispatcher.contains(cls)) { return true; } if (cls.isArray()) { @@ -1199,7 +1164,7 @@ private boolean isSecure(Class cls) { if (fury.getConfig().requireClassRegistration()) { return Functions.isLambda(cls) || ReflectionUtils.isJdkProxy(cls) - || extRegistry.registeredClassIdMap.containsKey(cls) + || extRegistry.classRegistered(cls) || shimDispatcher.contains(cls); } else { return extRegistry.classChecker.checkClass(this, cls.getName()); @@ -1221,9 +1186,9 @@ private boolean isSecure(Class cls) { public void writeClassAndUpdateCache(MemoryBuffer buffer, Class cls) { // fast path for common type if (cls == Integer.class) { - buffer.writePositiveVarInt(INTEGER_CLASS_ID << 1); + buffer.writePositiveVarInt(BuiltinClassId.INTEGER_CLASS_ID << 1); } else if (cls == Long.class) { - buffer.writePositiveVarInt(LONG_CLASS_ID << 1); + buffer.writePositiveVarInt(BuiltinClassId.LONG_CLASS_ID << 1); } else { writeClass(buffer, getOrUpdateClassInfo(cls)); } @@ -1241,7 +1206,7 @@ public void writeClassAndUpdateCache(MemoryBuffer buffer, Class cls) { /** Write classname for java serialization. */ public void writeClass(MemoryBuffer buffer, ClassInfo classInfo) { - if (classInfo.classId == NO_CLASS_ID) { // no class id provided. + if (classInfo.classId == BuiltinClassId.NO_CLASS_ID) { // no class id provided. // use classname buffer.writeByte(USE_CLASS_VALUE_FLAG); if (metaContextShareEnabled) { @@ -1317,7 +1282,9 @@ private Class readClassWithMetaShare(MemoryBuffer buffer) { classInfo = getClassInfo(cls, false); if (classInfo == null) { Short classId = extRegistry.registeredClassIdMap.get(cls); - classInfo = new ClassInfo(this, cls, null, null, classId == null ? NO_CLASS_ID : classId); + classInfo = + new ClassInfo( + this, cls, null, null, classId == null ? BuiltinClassId.NO_CLASS_ID : classId); classInfoMap.put(cls, classInfo); } readClassInfos.set(id, classInfo); @@ -1368,7 +1335,8 @@ private ClassInfo getMetaSharedClassInfo(ClassDef classDef, Class clz) { Class cls = clz; Short classId = extRegistry.registeredClassIdMap.get(cls); ClassInfo classInfo = - new ClassInfo(this, cls, null, null, classId == null ? NO_CLASS_ID : classId); + new ClassInfo( + this, cls, null, null, classId == null ? BuiltinClassId.NO_CLASS_ID : classId); if (cls == UnexistedMetaSharedClass.class) { classInfo.serializer = new UnexistedClassSerializer(fury, classDef); // ensure `UnexistedMetaSharedClass` registered to write fixed-length class def, @@ -1460,14 +1428,14 @@ public Expression writeClassExpr( inlineInvoke(classInfo, "getClassNameBytes", TypeToken.of(EnumStringBytes.class)))); } return new Expression.If( - eq(classId, Literal.ofShort(NO_CLASS_ID)), + eq(classId, Literal.ofShort(BuiltinClassId.NO_CLASS_ID)), writeUnregistered, writeClassExpr(buffer, classId)); } // Note: Thread safe fot jit thread to call. public Expression writeClassExpr(Expression buffer, short classId) { - Preconditions.checkArgument(classId != NO_CLASS_ID); + Preconditions.checkArgument(classId != BuiltinClassId.NO_CLASS_ID); return writeClassExpr(buffer, Literal.ofShort(classId)); } @@ -1497,14 +1465,16 @@ public void writeClassInternal(MemoryBuffer buffer, Class cls) { Short classId = extRegistry.registeredClassIdMap.get(cls); // Don't create serializer in case the object for class is non-serializable, // Or class is abstract or interface. - classInfo = new ClassInfo(this, cls, null, null, classId == null ? NO_CLASS_ID : classId); + classInfo = + new ClassInfo( + this, cls, null, null, classId == null ? BuiltinClassId.NO_CLASS_ID : classId); classInfoMap.put(cls, classInfo); } short classId = classInfo.classId; - if (classId == REPLACE_STUB_ID) { + if (classId == BuiltinClassId.REPLACE_STUB_ID) { // clear class id to avoid replaced class written as // ReplaceResolveSerializer.ReplaceStub - classInfo.classId = NO_CLASS_ID; + classInfo.classId = BuiltinClassId.NO_CLASS_ID; } writeClass(buffer, classInfo); classInfo.classId = classId; @@ -1528,7 +1498,7 @@ public Class readClassInternal(MemoryBuffer buffer) { return cls; } else { short classId = readClassId(buffer, flag); - ClassInfo classInfo = registeredId2ClassInfo[classId]; + ClassInfo classInfo = extRegistry.registeredId2ClassInfo[classId]; final Class cls = classInfo.cls; currentReadClass = cls; return cls; @@ -1784,7 +1754,7 @@ public ClassInfo newClassInfo(Class cls, Serializer serializer, short clas // Invoked by fury JIT. public ClassInfo nilClassInfo() { - return new ClassInfo(this, null, null, null, NO_CLASS_ID); + return new ClassInfo(this, null, null, null, BuiltinClassId.NO_CLASS_ID); } public ClassInfoHolder nilClassInfoHolder() { @@ -1792,7 +1762,7 @@ public ClassInfoHolder nilClassInfoHolder() { } public boolean isPrimitive(short classId) { - return classId >= PRIMITIVE_VOID_CLASS_ID && classId <= PRIMITIVE_DOUBLE_CLASS_ID; + return classIdAllocator.isPrimitive(classId); } public EnumStringResolver getEnumStringResolver() { diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java index cf9128c69e..d0493f88b5 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java @@ -19,8 +19,7 @@ package org.apache.fury.resolver; -import static org.apache.fury.resolver.ClassResolver.NO_CLASS_ID; -import static org.apache.fury.resolver.ClassResolver.PRIMITIVE_LONG_CLASS_ID; +import static org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import static org.apache.fury.resolver.FieldResolver.FieldInfoEncodingType.EMBED_TYPES_4; import static org.apache.fury.resolver.FieldResolver.FieldInfoEncodingType.EMBED_TYPES_9; import static org.apache.fury.resolver.FieldResolver.FieldInfoEncodingType.EMBED_TYPES_HASH; @@ -478,9 +477,9 @@ public long skipDataBy8(MemoryBuffer buffer, long partFieldInfo) { } ClassInfo classInfo = classResolver.getClassInfo(classId); if (classId >= minPrimitiveClassId && classId <= maxPrimitiveClassId) { - if (classId == ClassResolver.PRIMITIVE_INT_CLASS_ID) { + if (classId == BuiltinClassId.PRIMITIVE_INT_CLASS_ID) { intSerializer.read(buffer); - } else if (classId == PRIMITIVE_LONG_CLASS_ID) { + } else if (classId == BuiltinClassId.PRIMITIVE_LONG_CLASS_ID) { longSerializer.read(buffer); } else { fury.readData(buffer, classInfo); @@ -739,7 +738,7 @@ public static FieldInfo of( FieldTypes.OBJECT, fieldInfoEncodingType, encodedFieldInfo, - NO_CLASS_ID); + BuiltinClassId.NO_CLASS_ID); } if (Collection.class.isAssignableFrom(field.getType())) { TypeToken elementTypeToken = @@ -783,7 +782,7 @@ public static FieldInfo of( FieldTypes.OBJECT, fieldInfoEncodingType, encodedFieldInfo, - NO_CLASS_ID); + BuiltinClassId.NO_CLASS_ID); } } @@ -825,8 +824,8 @@ public ClassInfo getClassInfo(Class cls) { public ClassInfo getClassInfo(short classId) { ClassInfo classInfo = this.classInfoHolder.classInfo; - if (classInfo.classId == NO_CLASS_ID) { - Preconditions.checkArgument(classId != NO_CLASS_ID); + if (classInfo.classId == BuiltinClassId.NO_CLASS_ID) { + Preconditions.checkArgument(classId != BuiltinClassId.NO_CLASS_ID); this.classInfoHolder.classInfo = classInfo = classResolver.getClassInfo(classId); } return classInfo; @@ -875,7 +874,7 @@ public CollectionFieldInfo( fieldType, fieldInfoEncodingType, encodedFieldInfo, - NO_CLASS_ID); + BuiltinClassId.NO_CLASS_ID); Preconditions.checkArgument(field != STUB_FIELD); this.elementTypeToken = elementTypeToken; this.elementType = getRawType(elementTypeToken); @@ -926,7 +925,7 @@ public MapFieldInfo( fieldType, separateTypesHash, encodedFieldInfo, - NO_CLASS_ID); + BuiltinClassId.NO_CLASS_ID); Preconditions.checkArgument(field != STUB_FIELD); this.keyTypeToken = keyTypeToken; this.valueTypeToken = valueTypeToken; diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/CompatibleSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/CompatibleSerializer.java index b42a7b421f..b3118e4b2d 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/CompatibleSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/CompatibleSerializer.java @@ -27,6 +27,7 @@ import java.util.stream.Collectors; import org.apache.fury.Fury; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.resolver.FieldResolver; @@ -151,7 +152,7 @@ private void readAndWriteFieldValue( Object fieldValue; fieldValue = fieldAccessor.getObject(targetObject); if (ObjectSerializer.writeBasicObjectFieldValueFailed(fury, buffer, fieldValue, classId)) { - if (classId == ClassResolver.NO_CLASS_ID) { // SEPARATE_TYPES_HASH + if (classId == BuiltinClassId.NO_CLASS_ID) { // SEPARATE_TYPES_HASH writeSeparateFieldValue(fieldInfo, buffer, fieldValue); } else { ClassInfo classInfo = fieldInfo.getClassInfo(classId); @@ -167,38 +168,38 @@ private void writeFieldValue( short classId = fieldInfo.getEmbeddedClassId(); // PRIMITIVE fields, not need for null check. switch (classId) { - case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID: buffer.writeBoolean((Boolean) fieldValue); return; - case ClassResolver.PRIMITIVE_BYTE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID: buffer.writeByte((Byte) fieldValue); return; - case ClassResolver.PRIMITIVE_CHAR_CLASS_ID: + case BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID: buffer.writeChar((Character) fieldValue); return; - case ClassResolver.PRIMITIVE_SHORT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID: buffer.writeShort((Short) fieldValue); return; - case ClassResolver.PRIMITIVE_INT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_INT_CLASS_ID: if (fury.compressInt()) { buffer.writeVarInt((Integer) fieldValue); } else { buffer.writeInt((Integer) fieldValue); } return; - case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID: buffer.writeFloat((Float) fieldValue); return; - case ClassResolver.PRIMITIVE_LONG_CLASS_ID: + case BuiltinClassId.PRIMITIVE_LONG_CLASS_ID: fury.writeLong(buffer, (Long) fieldValue); return; - case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID: buffer.writeDouble((Double) fieldValue); return; - case ClassResolver.STRING_CLASS_ID: + case BuiltinClassId.STRING_CLASS_ID: fury.writeJavaStringRef(buffer, (String) fieldValue); break; - case ClassResolver.NO_CLASS_ID: // SEPARATE_TYPES_HASH + case BuiltinClassId.NO_CLASS_ID: // SEPARATE_TYPES_HASH writeSeparateFieldValue(fieldInfo, buffer, fieldValue); break; default: @@ -552,7 +553,7 @@ private void readAndSetFieldValue( fury, buffer, targetObject, fieldAccessor, classId) && ObjectSerializer.readBasicObjectFieldValueFailed( fury, buffer, targetObject, fieldAccessor, classId)) { - if (classId == ClassResolver.NO_CLASS_ID) { + if (classId == BuiltinClassId.NO_CLASS_ID) { // SEPARATE_TYPES_HASH Object fieldValue = fieldResolver.readObjectField(buffer, fieldInfo); fieldAccessor.putObject(targetObject, fieldValue); @@ -568,29 +569,29 @@ private Object readFieldValue(FieldResolver.FieldInfo fieldInfo, MemoryBuffer bu short classId = fieldInfo.getEmbeddedClassId(); // PRIMITIVE fields, not need for null check. switch (classId) { - case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID: return buffer.readBoolean(); - case ClassResolver.PRIMITIVE_BYTE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID: return buffer.readByte(); - case ClassResolver.PRIMITIVE_CHAR_CLASS_ID: + case BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID: return buffer.readChar(); - case ClassResolver.PRIMITIVE_SHORT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID: return buffer.readShort(); - case ClassResolver.PRIMITIVE_INT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_INT_CLASS_ID: if (fury.compressInt()) { return buffer.readVarInt(); } else { return buffer.readInt(); } - case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID: return buffer.readFloat(); - case ClassResolver.PRIMITIVE_LONG_CLASS_ID: + case BuiltinClassId.PRIMITIVE_LONG_CLASS_ID: return fury.readLong(buffer); - case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID: return buffer.readDouble(); - case ClassResolver.STRING_CLASS_ID: + case BuiltinClassId.STRING_CLASS_ID: return fury.readJavaStringRef(buffer); - case ClassResolver.NO_CLASS_ID: + case BuiltinClassId.NO_CLASS_ID: return fieldResolver.readObjectField(buffer, fieldInfo); default: { diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/MetaSharedSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/MetaSharedSerializer.java index 4d51af9d94..5b86f94bea 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/MetaSharedSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/MetaSharedSerializer.java @@ -36,6 +36,7 @@ import org.apache.fury.config.CompatibleMode; import org.apache.fury.config.FuryBuilder; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import org.apache.fury.resolver.ClassInfoHolder; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.resolver.RefResolver; @@ -216,8 +217,8 @@ private void readFields(MemoryBuffer buffer, Object[] fields) { assert fieldInfo.classInfo != null; short classId = fieldInfo.classId; // primitive field won't write null flag. - if (classId >= ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID - && classId <= ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID) { + if (classId >= BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID + && classId <= BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID) { fields[counter++] = Serializers.readPrimitiveValue(fury, buffer, classId); } else { Object fieldValue = @@ -253,32 +254,32 @@ private void readFields(MemoryBuffer buffer, Object[] fields) { /** Skip primitive primitive field value since it doesn't write null flag. */ static boolean skipPrimitiveFieldValueFailed(Fury fury, short classId, MemoryBuffer buffer) { switch (classId) { - case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID: buffer.increaseReaderIndex(1); return false; - case ClassResolver.PRIMITIVE_BYTE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID: buffer.increaseReaderIndex(1); return false; - case ClassResolver.PRIMITIVE_CHAR_CLASS_ID: + case BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID: buffer.increaseReaderIndex(2); return false; - case ClassResolver.PRIMITIVE_SHORT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID: buffer.increaseReaderIndex(2); return false; - case ClassResolver.PRIMITIVE_INT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_INT_CLASS_ID: if (fury.compressInt()) { buffer.readVarInt(); } else { buffer.increaseReaderIndex(4); } return false; - case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID: buffer.increaseReaderIndex(4); return false; - case ClassResolver.PRIMITIVE_LONG_CLASS_ID: + case BuiltinClassId.PRIMITIVE_LONG_CLASS_ID: fury.readLong(buffer); return false; - case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID: buffer.increaseReaderIndex(8); return false; default: diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java index d652878a63..a5b619d594 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java @@ -34,6 +34,7 @@ import org.apache.fury.collection.Tuple3; import org.apache.fury.exception.FuryException; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassInfoHolder; import org.apache.fury.resolver.ClassResolver; @@ -334,8 +335,8 @@ public Object[] readFields(MemoryBuffer buffer) { FinalTypeField fieldInfo = finalFields[i]; boolean isFinal = !metaContextShareEnabled || this.isFinal[i]; short classId = fieldInfo.classId; - if (classId >= ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID - && classId <= ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID) { + if (classId >= BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID + && classId <= BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID) { fieldValues[counter++] = Serializers.readPrimitiveValue(fury, buffer, classId); } else { Object fieldValue = @@ -478,19 +479,19 @@ static boolean writePrimitiveFieldValueFailed( return writePrimitiveFieldValueFailed(fury, buffer, targetObject, fieldOffset, classId); } switch (classId) { - case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID: buffer.writeBoolean((Boolean) fieldAccessor.get(targetObject)); return false; - case ClassResolver.PRIMITIVE_BYTE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID: buffer.writeByte((Byte) fieldAccessor.get(targetObject)); return false; - case ClassResolver.PRIMITIVE_CHAR_CLASS_ID: + case BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID: buffer.writeChar((Character) fieldAccessor.get(targetObject)); return false; - case ClassResolver.PRIMITIVE_SHORT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID: buffer.writeShort((Short) fieldAccessor.get(targetObject)); return false; - case ClassResolver.PRIMITIVE_INT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_INT_CLASS_ID: { int fieldValue = (Integer) fieldAccessor.get(targetObject); if (fury.compressInt()) { @@ -500,16 +501,16 @@ static boolean writePrimitiveFieldValueFailed( } return false; } - case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID: buffer.writeFloat((Float) fieldAccessor.get(targetObject)); return false; - case ClassResolver.PRIMITIVE_LONG_CLASS_ID: + case BuiltinClassId.PRIMITIVE_LONG_CLASS_ID: { long fieldValue = (long) fieldAccessor.get(targetObject); fury.writeLong(buffer, fieldValue); return false; } - case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID: buffer.writeDouble((Double) fieldAccessor.get(targetObject)); return false; default: @@ -520,19 +521,19 @@ static boolean writePrimitiveFieldValueFailed( static boolean writePrimitiveFieldValueFailed( Fury fury, MemoryBuffer buffer, Object targetObject, long fieldOffset, short classId) { switch (classId) { - case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID: buffer.writeBoolean(Platform.getBoolean(targetObject, fieldOffset)); return false; - case ClassResolver.PRIMITIVE_BYTE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID: buffer.writeByte(Platform.getByte(targetObject, fieldOffset)); return false; - case ClassResolver.PRIMITIVE_CHAR_CLASS_ID: + case BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID: buffer.writeChar(Platform.getChar(targetObject, fieldOffset)); return false; - case ClassResolver.PRIMITIVE_SHORT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID: buffer.writeShort(Platform.getShort(targetObject, fieldOffset)); return false; - case ClassResolver.PRIMITIVE_INT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_INT_CLASS_ID: { int fieldValue = Platform.getInt(targetObject, fieldOffset); if (fury.compressInt()) { @@ -542,16 +543,16 @@ static boolean writePrimitiveFieldValueFailed( } return false; } - case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID: buffer.writeFloat(Platform.getFloat(targetObject, fieldOffset)); return false; - case ClassResolver.PRIMITIVE_LONG_CLASS_ID: + case BuiltinClassId.PRIMITIVE_LONG_CLASS_ID: { long fieldValue = Platform.getLong(targetObject, fieldOffset); fury.writeLong(buffer, fieldValue); return false; } - case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID: buffer.writeDouble(Platform.getDouble(targetObject, fieldOffset)); return false; default: @@ -571,10 +572,10 @@ static boolean writeBasicObjectFieldValueFailed( } // add time types serialization here. switch (classId) { - case ClassResolver.STRING_CLASS_ID: // fastpath for string. + case BuiltinClassId.STRING_CLASS_ID: // fastpath for string. fury.writeJavaStringRef(buffer, (String) (fieldValue)); return false; - case ClassResolver.BOOLEAN_CLASS_ID: + case BuiltinClassId.BOOLEAN_CLASS_ID: { if (fieldValue == null) { buffer.writeByte(Fury.NULL_FLAG); @@ -584,7 +585,7 @@ static boolean writeBasicObjectFieldValueFailed( } return false; } - case ClassResolver.BYTE_CLASS_ID: + case BuiltinClassId.BYTE_CLASS_ID: { if (fieldValue == null) { buffer.writeByte(Fury.NULL_FLAG); @@ -594,7 +595,7 @@ static boolean writeBasicObjectFieldValueFailed( } return false; } - case ClassResolver.CHAR_CLASS_ID: + case BuiltinClassId.CHAR_CLASS_ID: { if (fieldValue == null) { buffer.writeByte(Fury.NULL_FLAG); @@ -604,7 +605,7 @@ static boolean writeBasicObjectFieldValueFailed( } return false; } - case ClassResolver.SHORT_CLASS_ID: + case BuiltinClassId.SHORT_CLASS_ID: { if (fieldValue == null) { buffer.writeByte(Fury.NULL_FLAG); @@ -614,7 +615,7 @@ static boolean writeBasicObjectFieldValueFailed( } return false; } - case ClassResolver.INTEGER_CLASS_ID: + case BuiltinClassId.INTEGER_CLASS_ID: { if (fieldValue == null) { buffer.writeByte(Fury.NULL_FLAG); @@ -628,7 +629,7 @@ static boolean writeBasicObjectFieldValueFailed( } return false; } - case ClassResolver.FLOAT_CLASS_ID: + case BuiltinClassId.FLOAT_CLASS_ID: { if (fieldValue == null) { buffer.writeByte(Fury.NULL_FLAG); @@ -638,7 +639,7 @@ static boolean writeBasicObjectFieldValueFailed( } return false; } - case ClassResolver.LONG_CLASS_ID: + case BuiltinClassId.LONG_CLASS_ID: { if (fieldValue == null) { buffer.writeByte(Fury.NULL_FLAG); @@ -648,7 +649,7 @@ static boolean writeBasicObjectFieldValueFailed( } return false; } - case ClassResolver.DOUBLE_CLASS_ID: + case BuiltinClassId.DOUBLE_CLASS_ID: { if (fieldValue == null) { buffer.writeByte(Fury.NULL_FLAG); @@ -680,35 +681,35 @@ static boolean readPrimitiveFieldValueFailed( return readPrimitiveFieldValueFailed(fury, buffer, targetObject, fieldOffset, classId); } switch (classId) { - case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID: fieldAccessor.set(targetObject, buffer.readBoolean()); return false; - case ClassResolver.PRIMITIVE_BYTE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID: fieldAccessor.set(targetObject, buffer.readByte()); return false; - case ClassResolver.PRIMITIVE_CHAR_CLASS_ID: + case BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID: fieldAccessor.set(targetObject, buffer.readChar()); return false; - case ClassResolver.PRIMITIVE_SHORT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID: fieldAccessor.set(targetObject, buffer.readShort()); return false; - case ClassResolver.PRIMITIVE_INT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_INT_CLASS_ID: if (fury.compressInt()) { fieldAccessor.set(targetObject, buffer.readVarInt()); } else { fieldAccessor.set(targetObject, buffer.readInt()); } return false; - case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID: fieldAccessor.set(targetObject, buffer.readFloat()); return false; - case ClassResolver.PRIMITIVE_LONG_CLASS_ID: + case BuiltinClassId.PRIMITIVE_LONG_CLASS_ID: fieldAccessor.set(targetObject, fury.readLong(buffer)); return false; - case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID: fieldAccessor.set(targetObject, buffer.readDouble()); return false; - case ClassResolver.STRING_CLASS_ID: + case BuiltinClassId.STRING_CLASS_ID: fieldAccessor.putObject(targetObject, fury.readJavaStringRef(buffer)); return false; default: @@ -721,35 +722,35 @@ static boolean readPrimitiveFieldValueFailed( private static boolean readPrimitiveFieldValueFailed( Fury fury, MemoryBuffer buffer, Object targetObject, long fieldOffset, short classId) { switch (classId) { - case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID: Platform.putBoolean(targetObject, fieldOffset, buffer.readBoolean()); return false; - case ClassResolver.PRIMITIVE_BYTE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID: Platform.putByte(targetObject, fieldOffset, buffer.readByte()); return false; - case ClassResolver.PRIMITIVE_CHAR_CLASS_ID: + case BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID: Platform.putChar(targetObject, fieldOffset, buffer.readChar()); return false; - case ClassResolver.PRIMITIVE_SHORT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID: Platform.putShort(targetObject, fieldOffset, buffer.readShort()); return false; - case ClassResolver.PRIMITIVE_INT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_INT_CLASS_ID: if (fury.compressInt()) { Platform.putInt(targetObject, fieldOffset, buffer.readVarInt()); } else { Platform.putInt(targetObject, fieldOffset, buffer.readInt()); } return false; - case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID: Platform.putFloat(targetObject, fieldOffset, buffer.readFloat()); return false; - case ClassResolver.PRIMITIVE_LONG_CLASS_ID: + case BuiltinClassId.PRIMITIVE_LONG_CLASS_ID: Platform.putLong(targetObject, fieldOffset, fury.readLong(buffer)); return false; - case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID: Platform.putDouble(targetObject, fieldOffset, buffer.readDouble()); return false; - case ClassResolver.STRING_CLASS_ID: + case BuiltinClassId.STRING_CLASS_ID: Platform.putObject(targetObject, fieldOffset, fury.readJavaStringRef(buffer)); return false; default: @@ -770,10 +771,10 @@ static boolean readBasicObjectFieldValueFailed( } // add time types serialization here. switch (classId) { - case ClassResolver.STRING_CLASS_ID: // fastpath for string. + case BuiltinClassId.STRING_CLASS_ID: // fastpath for string. fieldAccessor.putObject(targetObject, fury.readJavaStringRef(buffer)); return false; - case ClassResolver.BOOLEAN_CLASS_ID: + case BuiltinClassId.BOOLEAN_CLASS_ID: { if (buffer.readByte() == Fury.NULL_FLAG) { fieldAccessor.putObject(targetObject, null); @@ -782,7 +783,7 @@ static boolean readBasicObjectFieldValueFailed( } return false; } - case ClassResolver.BYTE_CLASS_ID: + case BuiltinClassId.BYTE_CLASS_ID: { if (buffer.readByte() == Fury.NULL_FLAG) { fieldAccessor.putObject(targetObject, null); @@ -791,7 +792,7 @@ static boolean readBasicObjectFieldValueFailed( } return false; } - case ClassResolver.CHAR_CLASS_ID: + case BuiltinClassId.CHAR_CLASS_ID: { if (buffer.readByte() == Fury.NULL_FLAG) { fieldAccessor.putObject(targetObject, null); @@ -800,7 +801,7 @@ static boolean readBasicObjectFieldValueFailed( } return false; } - case ClassResolver.SHORT_CLASS_ID: + case BuiltinClassId.SHORT_CLASS_ID: { if (buffer.readByte() == Fury.NULL_FLAG) { fieldAccessor.putObject(targetObject, null); @@ -809,7 +810,7 @@ static boolean readBasicObjectFieldValueFailed( } return false; } - case ClassResolver.INTEGER_CLASS_ID: + case BuiltinClassId.INTEGER_CLASS_ID: { if (buffer.readByte() == Fury.NULL_FLAG) { fieldAccessor.putObject(targetObject, null); @@ -822,7 +823,7 @@ static boolean readBasicObjectFieldValueFailed( } return false; } - case ClassResolver.FLOAT_CLASS_ID: + case BuiltinClassId.FLOAT_CLASS_ID: { if (buffer.readByte() == Fury.NULL_FLAG) { fieldAccessor.putObject(targetObject, null); @@ -831,7 +832,7 @@ static boolean readBasicObjectFieldValueFailed( } return false; } - case ClassResolver.LONG_CLASS_ID: + case BuiltinClassId.LONG_CLASS_ID: { if (buffer.readByte() == Fury.NULL_FLAG) { fieldAccessor.putObject(targetObject, null); @@ -840,7 +841,7 @@ static boolean readBasicObjectFieldValueFailed( } return false; } - case ClassResolver.DOUBLE_CLASS_ID: + case BuiltinClassId.DOUBLE_CLASS_ID: { if (buffer.readByte() == Fury.NULL_FLAG) { fieldAccessor.putObject(targetObject, null); @@ -946,7 +947,7 @@ public String toString() { private static short getRegisteredClassId(Fury fury, Class cls) { Short classId = fury.getClassResolver().getRegisteredClassId(cls); - return classId == null ? ClassResolver.NO_CLASS_ID : classId; + return classId == null ? BuiltinClassId.NO_CLASS_ID : classId; } public static int computeVersionHash(Collection descriptors) { diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectStreamSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectStreamSerializer.java index 02a942642a..dd618dac27 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectStreamSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectStreamSerializer.java @@ -51,6 +51,7 @@ import org.apache.fury.collection.ObjectArray; import org.apache.fury.collection.ObjectIntMap; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.resolver.FieldResolver; @@ -327,7 +328,7 @@ private static class SlotsInfo { public SlotsInfo(Fury fury, Class type) { this.cls = type; - classInfo = fury.getClassResolver().newClassInfo(type, null, ClassResolver.NO_CLASS_ID); + classInfo = fury.getClassResolver().newClassInfo(type, null, BuiltinClassId.NO_CLASS_ID); ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(type); streamClassInfo = STREAM_CLASS_INFO_CACHE.get(type); // `putFields/writeFields` will convert to fields value to be written by diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/ReplaceResolveSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/ReplaceResolveSerializer.java index da1c59fa2b..0ff3aea973 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/ReplaceResolveSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/ReplaceResolveSerializer.java @@ -29,6 +29,7 @@ import java.util.function.Function; import org.apache.fury.Fury; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.resolver.RefResolver; @@ -216,7 +217,7 @@ public ReplaceResolveSerializer(Fury fury, Class type) { jdkMethodInfoWriteCache = newJDKMethodInfoCache(type, fury); classClassInfoHolderMap.put(type, jdkMethodInfoWriteCache); // FIXME new classinfo may miss serializer update in async compilation mode. - writeClassInfo = classResolver.newClassInfo(type, this, ClassResolver.NO_CLASS_ID); + writeClassInfo = classResolver.newClassInfo(type, this, BuiltinClassId.NO_CLASS_ID); } else { jdkMethodInfoWriteCache = null; writeClassInfo = null; diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/Serializers.java b/java/fury-core/src/main/java/org/apache/fury/serializer/Serializers.java index 19829c97aa..baf01a229b 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/Serializers.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/Serializers.java @@ -44,7 +44,7 @@ import org.apache.fury.Fury; import org.apache.fury.collection.Tuple2; import org.apache.fury.memory.MemoryBuffer; -import org.apache.fury.resolver.ClassResolver; +import org.apache.fury.resolver.ClassIdAllocator.BuiltinClassId; import org.apache.fury.type.Type; import org.apache.fury.util.GraalvmSupport; import org.apache.fury.util.Platform; @@ -149,25 +149,25 @@ private static Serializer createSerializer( public static Object readPrimitiveValue(Fury fury, MemoryBuffer buffer, short classId) { switch (classId) { - case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BOOLEAN_CLASS_ID: return buffer.readBoolean(); - case ClassResolver.PRIMITIVE_BYTE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_BYTE_CLASS_ID: return buffer.readByte(); - case ClassResolver.PRIMITIVE_CHAR_CLASS_ID: + case BuiltinClassId.PRIMITIVE_CHAR_CLASS_ID: return buffer.readChar(); - case ClassResolver.PRIMITIVE_SHORT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_SHORT_CLASS_ID: return buffer.readShort(); - case ClassResolver.PRIMITIVE_INT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_INT_CLASS_ID: if (fury.compressInt()) { return buffer.readVarInt(); } else { return buffer.readInt(); } - case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID: + case BuiltinClassId.PRIMITIVE_FLOAT_CLASS_ID: return buffer.readFloat(); - case ClassResolver.PRIMITIVE_LONG_CLASS_ID: + case BuiltinClassId.PRIMITIVE_LONG_CLASS_ID: return fury.readLong(buffer); - case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID: + case BuiltinClassId.PRIMITIVE_DOUBLE_CLASS_ID: return buffer.readDouble(); default: { diff --git a/java/fury-core/src/main/java/org/apache/fury/type/ClassDef.java b/java/fury-core/src/main/java/org/apache/fury/type/ClassDef.java index fa22d0af25..4f86dd46a0 100644 --- a/java/fury-core/src/main/java/org/apache/fury/type/ClassDef.java +++ b/java/fury-core/src/main/java/org/apache/fury/type/ClassDef.java @@ -44,6 +44,7 @@ import org.apache.fury.config.FuryBuilder; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.MemoryUtils; +import org.apache.fury.resolver.ClassIdAllocator; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.serializer.CompatibleSerializer; import org.apache.fury.util.LoggerFactory; @@ -661,7 +662,7 @@ static FieldType buildFieldType(ClassResolver classResolver, Field field) { : genericType.getTypeParameter1())); } else { Short classId = classResolver.getRegisteredClassId(rawType); - if (classId != null && classId != ClassResolver.NO_CLASS_ID) { + if (classId != null && classId != ClassIdAllocator.BuiltinClassId.NO_CLASS_ID) { return new RegisteredFieldType(isFinal, classId); } else { return new ObjectFieldType(isFinal); @@ -696,7 +697,7 @@ private static FieldType buildFieldType(ClassResolver classResolver, GenericType : genericType.getTypeParameter1())); } else { Short classId = classResolver.getRegisteredClassId(genericType.cls); - if (classId != null && classId != ClassResolver.NO_CLASS_ID) { + if (classId != null && classId != ClassIdAllocator.BuiltinClassId.NO_CLASS_ID) { return new RegisteredFieldType(isFinal, classId); } else { return new ObjectFieldType(isFinal); diff --git a/java/fury-core/src/test/java/org/apache/fury/resolver/ClassIdAllocatorTest.java b/java/fury-core/src/test/java/org/apache/fury/resolver/ClassIdAllocatorTest.java new file mode 100644 index 0000000000..cb85882575 --- /dev/null +++ b/java/fury-core/src/test/java/org/apache/fury/resolver/ClassIdAllocatorTest.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package org.apache.fury.resolver; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class ClassIdAllocatorTest { + @Test + public void testInvalidConstructorArguments() { + Assert.assertThrows( + NullPointerException.class, + () -> { + new ClassIdAllocator(null, null); + }); + } + + @Test + public void testInnerClass() { + ClassIdAllocator allocator = new ClassIdAllocator((cls) -> true, (classId) -> true); + int innerRegisteredCount = 10; + for (int i = 0; i < innerRegisteredCount; i++) { + allocator.notifyRegistrationEnd(); + } + + allocator.markInternalRegistrationEnd(); + // Inner Class + Assert.assertTrue(allocator.isInnerClass((short) innerRegisteredCount)); + Assert.assertTrue(allocator.isInnerClass((short) (innerRegisteredCount - 1))); + Assert.assertTrue(allocator.isInnerClass((short) 1)); + + // Not Inner Class + Assert.assertFalse(allocator.isInnerClass(null)); + Assert.assertFalse(allocator.isInnerClass(ClassIdAllocator.BuiltinClassId.NO_CLASS_ID)); + Assert.assertFalse(allocator.isInnerClass((short) 12)); + } + + @Test + public void testAllocateClassId() { + final int registeredClassId = 3; + ClassIdAllocator allocator = + new ClassIdAllocator((cls) -> false, (classId) -> classId <= registeredClassId); + Assert.assertEquals(allocator.allocateClassId(this.getClass()), 4); + } +}