From 06f9fb9aeb24c751d75721ff776e579d2c0b084e Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 2 Jul 2018 22:32:29 +0200 Subject: [PATCH] Refine Class serializability check for actual Graal compatibility Issue: SPR-16992 --- .../core/SerializableTypeWrapper.java | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java b/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java index e680ea38a4..1fee0a5773 100644 --- a/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java +++ b/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java @@ -31,7 +31,6 @@ import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import org.springframework.lang.Nullable; -import org.springframework.util.Assert; import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; @@ -61,14 +60,6 @@ final class SerializableTypeWrapper { private static final Class[] SUPPORTED_SERIALIZABLE_TYPES = { GenericArrayType.class, ParameterizedType.class, TypeVariable.class, WildcardType.class}; - /** - * Let's test whether java.lang.Class itself is serializable... - * Otherwise we can skip our serializable type wrapping to begin with. - * This will be {@code true} on regular JVMs but {@code false} on GraalVM. - * @since 5.1 - */ - private static final boolean javaLangClassSerializable = Serializable.class.isAssignableFrom(Class.class); - static final ConcurrentReferenceHashMap cache = new ConcurrentReferenceHashMap<>(256); @@ -81,7 +72,6 @@ final class SerializableTypeWrapper { */ @Nullable public static Type forField(Field field) { - Assert.notNull(field, "Field must not be null"); return forTypeProvider(new FieldTypeProvider(field)); } @@ -149,21 +139,25 @@ final class SerializableTypeWrapper { * environment, this delegate will simply return the original {@code Type} as-is. */ @Nullable - static Type forTypeProvider(final TypeProvider provider) { - Assert.notNull(provider, "TypeProvider must not be null"); + static Type forTypeProvider(TypeProvider provider) { Type providedType = provider.getType(); - if (providedType == null) { - return null; + if (providedType == null || providedType instanceof Serializable) { + // No serializable type wrapping necessary (e.g. for java.lang.Class) + return providedType; } - if (!javaLangClassSerializable || providedType instanceof Serializable) { + if (!Serializable.class.isAssignableFrom(Class.class)) { + // Let's skip any wrapping attempts if types are generally not serializable in + // the current runtime environment (even java.lang.Class itself, e.g. on Graal) return providedType; } + + // Obtain a serializable type proxy for the given provider... Type cached = cache.get(providedType); if (cached != null) { return cached; } for (Class type : SUPPORTED_SERIALIZABLE_TYPES) { - if (type.isAssignableFrom(providedType.getClass())) { + if (type.isInstance(providedType)) { ClassLoader classLoader = provider.getClass().getClassLoader(); Class[] interfaces = new Class[] {type, SerializableTypeProxy.class, Serializable.class}; InvocationHandler handler = new TypeProxyInvocationHandler(provider);