diff --git a/codec/codec-sofa-hessian/src/main/java/com/alipay/sofa/rpc/codec/sofahessian/SingleClassLoaderSofaSerializerFactory.java b/codec/codec-sofa-hessian/src/main/java/com/alipay/sofa/rpc/codec/sofahessian/SingleClassLoaderSofaSerializerFactory.java index d79ddf610..8e0a8489c 100644 --- a/codec/codec-sofa-hessian/src/main/java/com/alipay/sofa/rpc/codec/sofahessian/SingleClassLoaderSofaSerializerFactory.java +++ b/codec/codec-sofa-hessian/src/main/java/com/alipay/sofa/rpc/codec/sofahessian/SingleClassLoaderSofaSerializerFactory.java @@ -27,6 +27,9 @@ import com.caucho.hessian.io.Serializer; import com.caucho.hessian.io.SerializerFactory; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import static com.alipay.hessian.generic.io.GenericDeserializer.ARRAY_PREFIX; import static com.alipay.sofa.rpc.codec.sofahessian.serialize.GenericCustomThrowableDeterminer.isGenericThrowException; @@ -40,8 +43,14 @@ public class SingleClassLoaderSofaSerializerFactory extends SerializerFactory { /** * logger for this class */ - private static final Logger LOGGER = LoggerFactory - .getLogger(SingleClassLoaderSofaSerializerFactory.class); + private static final Logger LOGGER = LoggerFactory + .getLogger(SingleClassLoaderSofaSerializerFactory.class); + + private final Map> _typeNotFoundMap = new ConcurrentHashMap<>(8); + private static final Object NOT_FOUND = new Object(); + private final boolean dynamicLoadEnable = Boolean.parseBoolean(System.getProperty( + DYNAMIC_LOAD_ENABLE_KEY, + Boolean.FALSE.toString())); @Override protected Serializer getDefaultSerializer(Class cl) { @@ -73,14 +82,24 @@ public Deserializer getDeserializer(String type) throws HessianProtocolException Deserializer subDeserializer = getDeserializer(type.substring(1)); deserializer = new ArrayDeserializer(subDeserializer); } else { + ClassLoader appClassLoader = Thread.currentThread().getContextClassLoader(); try { - ClassLoader appClassLoader = Thread.currentThread().getContextClassLoader(); + if (!dynamicLoadEnable) { + Map typeMap = _typeNotFoundMap.get(appClassLoader); + if (typeMap != null) { + if (typeMap.containsKey(type)) { + return null; + } + } + } Class cl = Class.forName(type, true, appClassLoader); deserializer = getDeserializer(cl); } catch (Exception e) { if (e instanceof ClassNotFoundException) { - LOGGER.errorWithApp(null, LogCodes.getLog(LogCodes.ERROR_DECODE_CLASS_NOT_FOUND, - getClass().getName(), type, Thread.currentThread().getContextClassLoader())); + if (!dynamicLoadEnable) { + _typeNotFoundMap.computeIfAbsent(appClassLoader, k -> new ConcurrentHashMap<>(8)).put(type, NOT_FOUND); + } + LOGGER.errorWithApp(null, LogCodes.getLog(LogCodes.ERROR_DECODE_CLASS_NOT_FOUND, getClass().getName(), type, appClassLoader)); } else { LOGGER.errorWithApp(null, e.toString(), e); } diff --git a/codec/codec-sofa-hessian/src/test/java/com/alipay/sofa/rpc/codec/sofahessian/SingleClassLoaderSofaSerializerFactoryTest.java b/codec/codec-sofa-hessian/src/test/java/com/alipay/sofa/rpc/codec/sofahessian/SingleClassLoaderSofaSerializerFactoryTest.java index 727f1ff0b..26bef4434 100644 --- a/codec/codec-sofa-hessian/src/test/java/com/alipay/sofa/rpc/codec/sofahessian/SingleClassLoaderSofaSerializerFactoryTest.java +++ b/codec/codec-sofa-hessian/src/test/java/com/alipay/sofa/rpc/codec/sofahessian/SingleClassLoaderSofaSerializerFactoryTest.java @@ -16,13 +16,17 @@ */ package com.alipay.sofa.rpc.codec.sofahessian; +import com.caucho.hessian.io.Deserializer; import com.caucho.hessian.io.Hessian2Input; import com.caucho.hessian.io.Hessian2Output; +import com.caucho.hessian.io.SerializerFactory; +import org.junit.Assert; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; @@ -63,4 +67,35 @@ public void testAll() throws IOException { assertEquals(a1[i], a2[i]); } + @Test + public void testDynamicLoadDisabled() throws Exception { + SingleClassLoaderSofaSerializerFactory factory = new SingleClassLoaderSofaSerializerFactory(); + Field field = SingleClassLoaderSofaSerializerFactory.class.getDeclaredField("_typeNotFoundMap"); + field.setAccessible(true); + Map> _typeNotFoundMap = (Map>) field + .get(factory); + Assert.assertEquals(0, _typeNotFoundMap.size()); + Deserializer deserializer = factory.getDeserializer("mock.xxx.MockObject"); + Assert.assertNull(deserializer); + Assert.assertEquals(1, _typeNotFoundMap.size()); + } + + @Test + public void testDynamicLoadEnabled() throws Exception { + try { + System.setProperty(SerializerFactory.DYNAMIC_LOAD_ENABLE_KEY, "true"); + SingleClassLoaderSofaSerializerFactory factory = new SingleClassLoaderSofaSerializerFactory(); + Field field = SingleClassLoaderSofaSerializerFactory.class.getDeclaredField("_typeNotFoundMap"); + field.setAccessible(true); + Map> _typeNotFoundMap = (Map>) field + .get(factory); + Assert.assertEquals(0, _typeNotFoundMap.size()); + Deserializer deserializer = factory.getDeserializer("mock.xxx.MockObject"); + Assert.assertNull(deserializer); + Assert.assertEquals(0, _typeNotFoundMap.size()); + } finally { + System.clearProperty(SerializerFactory.DYNAMIC_LOAD_ENABLE_KEY); + } + } + } \ No newline at end of file