diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistry.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistry.java index 132f27ac2da..467d1be2571 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistry.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistry.java @@ -16,21 +16,33 @@ */ package com.alibaba.dubbo.common.serialize.support; -import java.util.LinkedHashSet; -import java.util.Set; +import com.esotericsoftware.kryo.Serializer; + +import java.util.LinkedHashMap; +import java.util.Map; public abstract class SerializableClassRegistry { - private static final Set registrations = new LinkedHashSet(); + private static final Map registrations = new LinkedHashMap(); /** * only supposed to be called at startup time */ public static void registerClass(Class clazz) { - registrations.add(clazz); + registerClass(clazz, null); + } + + /** + * only supposed to be called at startup time + */ + public static void registerClass(Class clazz, Serializer serializer) { + if (clazz == null) { + throw new IllegalArgumentException("Class registered to kryo cannot be null!"); + } + registrations.put(clazz, serializer); } - public static Set getRegisteredClasses() { + public static Map getRegisteredClasses() { return registrations; } } diff --git a/dubbo-serialization/dubbo-serialization-api/src/test/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistryTest.java b/dubbo-serialization/dubbo-serialization-api/src/test/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistryTest.java index 156e52fa8d6..35f78cce635 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/test/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistryTest.java +++ b/dubbo-serialization/dubbo-serialization-api/src/test/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistryTest.java @@ -18,9 +18,9 @@ import org.junit.Test; -import java.util.Set; +import java.util.Map; -import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; public class SerializableClassRegistryTest { @@ -29,8 +29,8 @@ public void testAddClasses() { SerializableClassRegistry.registerClass(A.class); SerializableClassRegistry.registerClass(B.class); - Set registeredClasses = SerializableClassRegistry.getRegisteredClasses(); - assertThat(registeredClasses, hasSize(2)); + Map registeredClasses = SerializableClassRegistry.getRegisteredClasses(); + assertThat(registeredClasses.size(), equalTo(2)); } private class A { @@ -38,4 +38,4 @@ private class A { private class B { } -} \ No newline at end of file +} diff --git a/dubbo-serialization/dubbo-serialization-fst/src/main/java/com/alibaba/dubbo/common/serialize/fst/FstFactory.java b/dubbo-serialization/dubbo-serialization-fst/src/main/java/com/alibaba/dubbo/common/serialize/fst/FstFactory.java index 028cfd76402..4377f885664 100644 --- a/dubbo-serialization/dubbo-serialization-fst/src/main/java/com/alibaba/dubbo/common/serialize/fst/FstFactory.java +++ b/dubbo-serialization/dubbo-serialization-fst/src/main/java/com/alibaba/dubbo/common/serialize/fst/FstFactory.java @@ -37,7 +37,7 @@ public static FstFactory getDefaultFactory() { } public FstFactory() { - for (Class clazz : SerializableClassRegistry.getRegisteredClasses()) { + for (Class clazz : SerializableClassRegistry.getRegisteredClasses().keySet()) { conf.registerClass(clazz); } } diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/CompatibleKryo.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/CompatibleKryo.java index 302906064a8..2b440109977 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/CompatibleKryo.java +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/CompatibleKryo.java @@ -34,12 +34,22 @@ public Serializer getDefaultSerializer(Class type) { throw new IllegalArgumentException("type cannot be null."); } - if (!type.isArray() && !type.isEnum() && !ReflectionUtils.checkZeroArgConstructor(type)) { + /** + * Kryo requires every class to provide a zero argument constructor. For any class does not match this condition, kryo have two ways: + * 1. Use JavaSerializer, + * 2. Set 'kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));', StdInstantiatorStrategy can generate an instance bypassing the constructor. + * + * In practice, it's not possible for Dubbo users to register kryo Serializer for every customized class. So in most cases, customized classes with/without zero argument constructor will + * default to the default serializer. + * It is the responsibility of kryo to handle with every standard jdk classes, so we will just escape these classes. + */ + if (!ReflectionUtils.isJdk(type) && !type.isArray() && !type.isEnum() && !ReflectionUtils.checkZeroArgConstructor(type)) { if (logger.isWarnEnabled()) { logger.warn(type + " has no zero-arg constructor and this will affect the serialization performance"); } return new JavaSerializer(); } + return super.getDefaultSerializer(type); } } diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java index bcde92aae6a..7ca5c6c131c 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java @@ -20,6 +20,7 @@ import com.alibaba.dubbo.common.serialize.support.SerializableClassRegistry; import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.pool.KryoFactory; import com.esotericsoftware.kryo.serializers.DefaultSerializers; import de.javakaffee.kryoserializers.ArraysAsListSerializer; @@ -48,6 +49,7 @@ import java.util.Hashtable; import java.util.LinkedHashSet; import java.util.LinkedList; +import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.UUID; @@ -134,8 +136,12 @@ public Kryo create() { kryo.register(clazz); } - for (Class clazz : SerializableClassRegistry.getRegisteredClasses()) { - kryo.register(clazz); + for (Map.Entry entry : SerializableClassRegistry.getRegisteredClasses().entrySet()) { + if (entry.getValue() == null) { + kryo.register(entry.getKey()); + } else { + kryo.register(entry.getKey(), (Serializer) entry.getValue()); + } } return kryo; diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/utils/ReflectionUtils.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/utils/ReflectionUtils.java index b35fcc6ef97..469ec610dac 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/utils/ReflectionUtils.java +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/com/alibaba/dubbo/common/serialize/kryo/utils/ReflectionUtils.java @@ -26,4 +26,8 @@ public static boolean checkZeroArgConstructor(Class clazz) { return false; } } + + public static boolean isJdk(Class clazz) { + return clazz.getName().startsWith("java.") || clazz.getName().startsWith("javax."); + } } diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/test/java/com/alibaba/dubbo/common/serialize/serialization/AbstractSerializationTest.java b/dubbo-serialization/dubbo-serialization-kryo/src/test/java/com/alibaba/dubbo/common/serialize/serialization/AbstractSerializationTest.java index 61c642595f4..0a645a9efad 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/test/java/com/alibaba/dubbo/common/serialize/serialization/AbstractSerializationTest.java +++ b/dubbo-serialization/dubbo-serialization-kryo/src/test/java/com/alibaba/dubbo/common/serialize/serialization/AbstractSerializationTest.java @@ -67,7 +67,7 @@ public abstract class AbstractSerializationTest { URL url = new URL("protocol", "1.1.1.1", 1234); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - // ================ Primitive Type ================ + // ================ Primitive Type ================ BigPerson bigPerson; MediaContent mediaContent; @@ -383,7 +383,7 @@ public void test_BytesRange() throws Exception { } } - // ================ Array Type ================ + // ================ Array Type ================ void assertObjectArray(T[] data, Class clazz) throws Exception { ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); @@ -762,7 +762,7 @@ public void test_StringArray_withType() throws Exception { assertObjectArrayWithType(new String[]{"1", "b"}, String[].class); } - // ================ Simple Type ================ + // ================ Simple Type ================ @Test public void test_IntegerArray() throws Exception { @@ -979,7 +979,7 @@ public void test_LinkedHashMap() throws Exception { } } - // ================ Complex Collection Type ================ + // ================ Complex Collection Type ================ @Test public void test_SPersonList() throws Exception { @@ -1111,7 +1111,7 @@ public void test_MultiObject_WithType() throws Exception { } - // abnormal case + // abnormal case @Test public void test_MediaContent_badStream() throws Exception { @@ -1207,4 +1207,4 @@ public void test_URL_mutable_withType() throws Exception { } catch (IOException expected) { } } -} \ No newline at end of file +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/redis/redis-consumer.xml b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/redis/redis-consumer.xml index ccd63bb876d..c173000baeb 100644 --- a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/redis/redis-consumer.xml +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/redis/redis-consumer.xml @@ -21,7 +21,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> - +