Skip to content

Commit

Permalink
refactor(java): replace Guava's TypeToken with self-made (#1553)
Browse files Browse the repository at this point in the history

## What does this PR do?

Removes Guava's `TypeToken` usages and replaces it with a hand-made
`TypeToken` implementation.
To be honest, this is mostly a copy-paste of Guava's TypeToken with
removing some unnecessary stuff. This implementation can be improved and
optimized.

## Related issues

#1113
#1273

---------

Co-authored-by: Nandakumar Vadivelu <nanda@apache.org>
  • Loading branch information
Munoon and nandakumar131 committed Apr 26, 2024
1 parent c6bc996 commit a003624
Show file tree
Hide file tree
Showing 48 changed files with 2,214 additions and 891 deletions.
3 changes: 3 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ The text of each license is the standard Apache 2.0 license.
* guava (https://github.com/google/guava)
Files:
java/fury-core/src/main/java/org/apache/fury/util/Preconditions.java
java/fury-core/src/main/java/org/apache/fury/reflect/TypeParameter.java
java/fury-core/src/main/java/org/apache/fury/reflect/Types.java
java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java

* spark (https://github.com/apache/spark)
Files:
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import static org.apache.fury.type.TypeUtils.PRIMITIVE_VOID_TYPE;
import static org.apache.fury.type.TypeUtils.getRawType;

import com.google.common.reflect.TypeToken;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
Expand All @@ -56,6 +55,7 @@
import org.apache.fury.collection.Tuple2;
import org.apache.fury.memory.MemoryBuffer;
import org.apache.fury.memory.Platform;
import org.apache.fury.reflect.TypeRef;
import org.apache.fury.resolver.ClassInfo;
import org.apache.fury.resolver.ClassInfoHolder;
import org.apache.fury.type.Descriptor;
Expand Down Expand Up @@ -84,23 +84,23 @@ public abstract class CodecBuilder {
protected static final String ROOT_OBJECT_NAME = "obj";
// avoid user class has field with name fury.
protected static final String FURY_NAME = "fury";
static TypeToken<Object[]> objectArrayTypeToken = TypeToken.of(Object[].class);
static TypeToken<MemoryBuffer> bufferTypeToken = TypeToken.of(MemoryBuffer.class);
static TypeToken<ClassInfo> classInfoTypeToken = TypeToken.of(ClassInfo.class);
static TypeToken<ClassInfoHolder> classInfoHolderTypeToken = TypeToken.of(ClassInfoHolder.class);
static TypeRef<Object[]> objectArrayTypeRef = TypeRef.of(Object[].class);
static TypeRef<MemoryBuffer> bufferTypeRef = TypeRef.of(MemoryBuffer.class);
static TypeRef<ClassInfo> classInfoTypeRef = TypeRef.of(ClassInfo.class);
static TypeRef<ClassInfoHolder> classInfoHolderTypeRef = TypeRef.of(ClassInfoHolder.class);

protected final CodegenContext ctx;
protected final TypeToken<?> beanType;
protected final TypeRef<?> beanType;
protected final Class<?> beanClass;
protected final boolean isRecord;
private final Set<String> duplicatedFields;
protected Reference furyRef = new Reference(FURY_NAME, TypeToken.of(Fury.class));
protected Reference furyRef = new Reference(FURY_NAME, TypeRef.of(Fury.class));
public static final Reference recordComponentDefaultValues =
new Reference("recordComponentDefaultValues", OBJECT_ARRAY_TYPE);
protected final Map<String, Reference> fieldMap = new HashMap<>();
protected boolean recordCtrAccessible;

public CodecBuilder(CodegenContext ctx, TypeToken<?> beanType) {
public CodecBuilder(CodegenContext ctx, TypeRef<?> beanType) {
this.ctx = ctx;
this.beanType = beanType;
this.beanClass = getRawType(beanType);
Expand All @@ -126,16 +126,16 @@ protected boolean sourcePublicAccessible(Class<?> cls) {
return ctx.sourcePublicAccessible(cls);
}

protected Expression tryInlineCast(Expression expression, TypeToken<?> targetType) {
protected Expression tryInlineCast(Expression expression, TypeRef<?> targetType) {
return tryCastIfPublic(expression, targetType, true);
}

protected Expression tryCastIfPublic(Expression expression, TypeToken<?> targetType) {
protected Expression tryCastIfPublic(Expression expression, TypeRef<?> targetType) {
return tryCastIfPublic(expression, targetType, false);
}

protected Expression tryCastIfPublic(
Expression expression, TypeToken<?> targetType, boolean inline) {
Expression expression, TypeRef<?> targetType, boolean inline) {
Class<?> rawType = getRawType(targetType);
if (rawType == FinalObjectTypeStub.class) {
// final field doesn't exist in this class, skip cast.
Expand All @@ -145,14 +145,14 @@ protected Expression tryCastIfPublic(
if (sourcePublicAccessible(rawType)) {
return new Cast(expression, targetType);
} else {
return new Cast(expression, ReflectionUtils.getPublicSuperType(TypeToken.of(rawType)));
return new Cast(expression, ReflectionUtils.getPublicSuperType(TypeRef.of(rawType)));
}
}
return tryCastIfPublic(expression, targetType, "castedValue");
}

protected Expression tryCastIfPublic(
Expression expression, TypeToken<?> targetType, String valuePrefix) {
Expression expression, TypeRef<?> targetType, String valuePrefix) {
Class<?> rawType = getRawType(targetType);
if (sourcePublicAccessible(rawType)
&& !expression.type().wrap().isSubtypeOf(targetType.wrap())) {
Expand All @@ -172,10 +172,10 @@ protected Reference getRecordCtrHandle() {
new StaticInvoke(
RecordUtils.class,
"getRecordCtrHandle",
TypeToken.of(MethodHandle.class),
TypeRef.of(MethodHandle.class),
beanClassExpr());
ctx.addField(ctx.type(MethodHandle.class), fieldName, getRecordCtrHandle);
fieldRef = new Reference(fieldName, TypeToken.of(MethodHandle.class));
fieldRef = new Reference(fieldName, TypeRef.of(MethodHandle.class));
fieldMap.put(fieldName, fieldRef);
}
return fieldRef;
Expand All @@ -188,7 +188,7 @@ protected Expression buildDefaultComponentsArray() {

/** Returns an expression that get field value from <code>bean</code>. */
protected Expression getFieldValue(Expression inputBeanExpr, Descriptor descriptor) {
TypeToken<?> fieldType = descriptor.getTypeToken();
TypeRef<?> fieldType = descriptor.getTypeRef();
Class<?> rawType = descriptor.getRawType();
String fieldName = descriptor.getName();
if (isRecord) {
Expand Down Expand Up @@ -234,7 +234,7 @@ protected Expression getFieldValue(Expression inputBeanExpr, Descriptor descript
}

private Expression getRecordFieldValue(Expression inputBeanExpr, Descriptor descriptor) {
TypeToken<?> fieldType = descriptor.getTypeToken();
TypeRef<?> fieldType = descriptor.getTypeRef();
if (!sourcePublicAccessible(descriptor.getRawType())) {
fieldType = OBJECT_TYPE;
}
Expand All @@ -249,7 +249,7 @@ private Expression getRecordFieldValue(Expression inputBeanExpr, Descriptor desc
Tuple2<Class<?>, String> methodInfo = Functions.getterMethodInfo(descriptor.getRawType());
if (ref == null) {
Class<?> funcInterface = methodInfo.f0;
TypeToken<?> getterType = TypeToken.of(funcInterface);
TypeRef<?> getterType = TypeRef.of(funcInterface);
Expression getter =
new StaticInvoke(
Functions.class,
Expand All @@ -264,7 +264,7 @@ private Expression getRecordFieldValue(Expression inputBeanExpr, Descriptor desc
}
if (!fieldType.isPrimitive()) {
Expression v = inlineInvoke(ref, methodInfo.f1, OBJECT_TYPE, fieldNullable, inputBeanExpr);
return tryCastIfPublic(v, descriptor.getTypeToken(), fieldName);
return tryCastIfPublic(v, descriptor.getTypeRef(), fieldName);
} else {
return new Invoke(ref, methodInfo.f1, fieldType, fieldNullable, inputBeanExpr);
}
Expand All @@ -277,18 +277,18 @@ private Expression reflectAccessField(
Reference fieldRef = getReflectField(cls, descriptor.getField());
// boolean fieldNullable = !descriptor.getTypeToken().isPrimitive();
Invoke getObj = new Invoke(fieldRef, "get", OBJECT_TYPE, fieldNullable, inputObject);
return new Cast(getObj, descriptor.getTypeToken(), descriptor.getName());
return new Cast(getObj, descriptor.getTypeRef(), descriptor.getName());
}

/** Returns an expression that get field value> from <code>bean</code> using {@link Unsafe}. */
private Expression unsafeAccessField(
Expression inputObject, Class<?> cls, Descriptor descriptor) {
String fieldName = descriptor.getName();
Expression fieldOffsetExpr = getFieldOffset(cls, descriptor);
if (descriptor.getTypeToken().isPrimitive()) {
if (descriptor.getTypeRef().isPrimitive()) {
// ex: Platform.UNSAFE.getFloat(obj, fieldOffset)
Preconditions.checkArgument(!fieldNullable);
TypeToken<?> returnType = descriptor.getTypeToken();
TypeRef<?> returnType = descriptor.getTypeRef();
String funcName = "get" + StringUtils.capitalize(descriptor.getRawType().toString());
return new StaticInvoke(
Platform.class, funcName, returnType, false, inputObject, fieldOffsetExpr);
Expand All @@ -302,7 +302,7 @@ private Expression unsafeAccessField(
fieldNullable,
inputObject,
fieldOffsetExpr);
return tryCastIfPublic(getObj, descriptor.getTypeToken(), fieldName);
return tryCastIfPublic(getObj, descriptor.getTypeRef(), fieldName);
}
}

Expand All @@ -317,7 +317,7 @@ private Expression getFieldOffset(Class<?> cls, Descriptor descriptor) {
fieldName + "_offset_",
() -> {
Expression classExpr = beanClassExpr(field.getDeclaringClass());
new Invoke(classExpr, "getDeclaredField", TypeToken.of(Field.class));
new Invoke(classExpr, "getDeclaredField", TypeRef.of(Field.class));
Expression reflectFieldRef = getReflectField(cls, field, false);
return new StaticInvoke(
Platform.class, "objectFieldOffset", PRIMITIVE_LONG_TYPE, reflectFieldRef)
Expand Down Expand Up @@ -355,8 +355,8 @@ protected Expression setFieldValue(Expression bean, Descriptor d, Expression val
if (!d.isFinalField() && !Modifier.isPrivate(d.getModifiers())) {
if (AccessorHelper.defineSetter(d.getField())) {
Class<?> accessorClass = AccessorHelper.getAccessorClass(d.getField());
if (!value.type().equals(d.getTypeToken())) {
value = new Cast(value, d.getTypeToken());
if (!value.type().equals(d.getTypeRef())) {
value = new Cast(value, d.getTypeRef());
}
return new StaticInvoke(
accessorClass, d.getName(), PRIMITIVE_VOID_TYPE, false, bean, value);
Expand All @@ -365,8 +365,8 @@ protected Expression setFieldValue(Expression bean, Descriptor d, Expression val
if (d.getWriteMethod() != null && !Modifier.isPrivate(d.getWriteMethod().getModifiers())) {
if (AccessorHelper.defineSetter(d.getWriteMethod())) {
Class<?> accessorClass = AccessorHelper.getAccessorClass(d.getWriteMethod());
if (!value.type().equals(d.getTypeToken())) {
value = new Cast(value, d.getTypeToken());
if (!value.type().equals(d.getTypeRef())) {
value = new Cast(value, d.getTypeRef());
}
return new StaticInvoke(
accessorClass, d.getWriteMethod().getName(), PRIMITIVE_VOID_TYPE, false, bean, value);
Expand All @@ -392,10 +392,10 @@ private Expression reflectSetField(Expression bean, Field field, Expression valu
* Unsafe}.
*/
private Expression unsafeSetField(Expression bean, Descriptor descriptor, Expression value) {
TypeToken<?> fieldType = descriptor.getTypeToken();
TypeRef<?> fieldType = descriptor.getTypeRef();
// Use Field in case the class has duplicate field name as `fieldName`.
Expression fieldOffsetExpr = getFieldOffset(beanClass, descriptor);
if (descriptor.getTypeToken().isPrimitive()) {
if (descriptor.getTypeRef().isPrimitive()) {
Preconditions.checkArgument(value.type().equals(fieldType));
String funcName = "put" + StringUtils.capitalize(getRawType(fieldType).toString());
return new StaticInvoke(Platform.class, funcName, bean, fieldOffsetExpr, value);
Expand All @@ -421,19 +421,19 @@ private Reference getReflectField(Class<?> cls, Field field, boolean setAccessib
Field.class,
fieldRefName,
() -> {
TypeToken<Field> fieldTypeToken = TypeToken.of(Field.class);
TypeRef<Field> fieldTypeRef = TypeRef.of(Field.class);
Expression classExpr = beanClassExpr(field.getDeclaringClass());
Expression fieldExpr;
if (GraalvmSupport.isGraalBuildtime()) {
fieldExpr =
inlineInvoke(
classExpr, "getDeclaredField", fieldTypeToken, Literal.ofString(fieldName));
classExpr, "getDeclaredField", fieldTypeRef, Literal.ofString(fieldName));
} else {
fieldExpr =
new StaticInvoke(
ReflectionUtils.class,
"getField",
fieldTypeToken,
fieldTypeRef,
classExpr,
Literal.ofString(fieldName));
}
Expand All @@ -450,7 +450,7 @@ private Reference getOrCreateField(
Reference fieldRef = fieldMap.get(fieldName);
if (fieldRef == null) {
ctx.addField(isStatic, true, ctx.type(type), fieldName, value.get());
fieldRef = new Reference(fieldName, TypeToken.of(type));
fieldRef = new Reference(fieldName, TypeRef.of(type));
fieldMap.put(fieldName, fieldRef);
}
return fieldRef;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

package org.apache.fury.builder;

import com.google.common.reflect.TypeToken;
import java.util.Collections;
import org.apache.fury.Fury;
import org.apache.fury.codegen.CodeGenerator;
import org.apache.fury.codegen.CompileUnit;
import org.apache.fury.meta.ClassDef;
import org.apache.fury.reflect.TypeRef;
import org.apache.fury.resolver.ClassResolver;
import org.apache.fury.resolver.FieldResolver;
import org.apache.fury.serializer.Serializer;
Expand All @@ -47,7 +47,7 @@ public static <T> Class<? extends Serializer<T>> loadOrGenMetaSharedCodecClass(
Fury fury, Class<T> cls, ClassDef classDef) {
Preconditions.checkNotNull(fury);
MetaSharedCodecBuilder codecBuilder =
new MetaSharedCodecBuilder(TypeToken.of(cls), fury, classDef);
new MetaSharedCodecBuilder(TypeRef.of(cls), fury, classDef);
return loadOrGenCodecClass(cls, fury, codecBuilder);
}

Expand All @@ -61,7 +61,7 @@ public static <T> Class<? extends Serializer<T>> loadOrGenCompatibleCodecClass(
Class<T> cls, Fury fury, FieldResolver fieldResolver, Class<?> parentSerializerClass) {
Preconditions.checkNotNull(fury);
BaseObjectCodecBuilder codecBuilder =
new CompatibleCodecBuilder(TypeToken.of(cls), fury, fieldResolver, parentSerializerClass);
new CompatibleCodecBuilder(TypeRef.of(cls), fury, fieldResolver, parentSerializerClass);
return loadOrGenCodecClass(cls, fury, codecBuilder);
}

Expand Down

0 comments on commit a003624

Please sign in to comment.