Skip to content

Commit 8beeb64

Browse files
authored
Merge pull request #2220, leave jdk standard classes to kryo, use the default registered serializer by kryo.
Fixes #2178, support java8 time types.
1 parent e350840 commit 8beeb64

File tree

7 files changed

+56
-25
lines changed

7 files changed

+56
-25
lines changed

dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/support/SerializableClassRegistry.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,34 @@
1616
*/
1717
package org.apache.dubbo.common.serialize.support;
1818

19-
import java.util.LinkedHashSet;
20-
import java.util.Set;
19+
import com.esotericsoftware.kryo.Serializer;
20+
21+
import java.util.LinkedHashMap;
22+
import java.util.Map;
2123

2224
public abstract class SerializableClassRegistry {
2325

24-
private static final Set<Class> registrations = new LinkedHashSet<Class>();
26+
27+
private static final Map<Class, Object> registrations = new LinkedHashMap<>();
2528

2629
/**
2730
* only supposed to be called at startup time
2831
*/
2932
public static void registerClass(Class clazz) {
30-
registrations.add(clazz);
33+
registerClass(clazz, null);
34+
}
35+
36+
/**
37+
* only supposed to be called at startup time
38+
*/
39+
public static void registerClass(Class clazz, Serializer serializer) {
40+
if (clazz == null) {
41+
throw new IllegalArgumentException("Class registered to kryo cannot be null!");
42+
}
43+
registrations.put(clazz, serializer);
3144
}
3245

33-
public static Set<Class> getRegisteredClasses() {
46+
public static Map<Class, Object> getRegisteredClasses() {
3447
return registrations;
3548
}
3649
}

dubbo-serialization/dubbo-serialization-api/src/test/java/org/apache/dubbo/common/serialize/support/SerializableClassRegistryTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818

1919
import org.junit.Test;
2020

21-
import java.util.Set;
21+
import java.util.Map;
2222

23-
import static org.hamcrest.Matchers.hasSize;
23+
import static org.hamcrest.Matchers.equalTo;
2424
import static org.junit.Assert.assertThat;
2525

2626
public class SerializableClassRegistryTest {
@@ -29,8 +29,8 @@ public void testAddClasses() {
2929
SerializableClassRegistry.registerClass(A.class);
3030
SerializableClassRegistry.registerClass(B.class);
3131

32-
Set<Class> registeredClasses = SerializableClassRegistry.getRegisteredClasses();
33-
assertThat(registeredClasses, hasSize(2));
32+
Map<Class, Object> registeredClasses = SerializableClassRegistry.getRegisteredClasses();
33+
assertThat(registeredClasses.size(), equalTo(2));
3434
}
3535

3636
private class A {

dubbo-serialization/dubbo-serialization-fst/src/main/java/org/apache/dubbo/common/serialize/fst/FstFactory.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.dubbo.common.serialize.fst;
1818

1919
import org.apache.dubbo.common.serialize.support.SerializableClassRegistry;
20-
2120
import org.nustaq.serialization.FSTConfiguration;
2221
import org.nustaq.serialization.FSTObjectInput;
2322
import org.nustaq.serialization.FSTObjectOutput;
@@ -37,9 +36,7 @@ public static FstFactory getDefaultFactory() {
3736
}
3837

3938
public FstFactory() {
40-
for (Class clazz : SerializableClassRegistry.getRegisteredClasses()) {
41-
conf.registerClass(clazz);
42-
}
39+
SerializableClassRegistry.getRegisteredClasses().keySet().forEach(conf::registerClass);
4340
}
4441

4542
public FSTObjectOutput getObjectOutput(OutputStream outputStream) {

dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryo.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,12 @@
1616
*/
1717
package org.apache.dubbo.common.serialize.kryo;
1818

19-
import org.apache.dubbo.common.logger.Logger;
20-
import org.apache.dubbo.common.logger.LoggerFactory;
21-
import org.apache.dubbo.common.serialize.kryo.utils.ReflectionUtils;
22-
2319
import com.esotericsoftware.kryo.Kryo;
2420
import com.esotericsoftware.kryo.Serializer;
2521
import com.esotericsoftware.kryo.serializers.JavaSerializer;
22+
import org.apache.dubbo.common.logger.Logger;
23+
import org.apache.dubbo.common.logger.LoggerFactory;
24+
import org.apache.dubbo.common.serialize.kryo.utils.ReflectionUtils;
2625

2726
public class CompatibleKryo extends Kryo {
2827

@@ -34,7 +33,16 @@ public Serializer getDefaultSerializer(Class type) {
3433
throw new IllegalArgumentException("type cannot be null.");
3534
}
3635

37-
if (!type.isArray() && !type.isEnum() && !ReflectionUtils.checkZeroArgConstructor(type)) {
36+
/**
37+
* Kryo requires every class to provide a zero argument constructor. For any class does not match this condition, kryo have two ways:
38+
* 1. Use JavaSerializer,
39+
* 2. Set 'kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));', StdInstantiatorStrategy can generate an instance bypassing the constructor.
40+
*
41+
* 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
42+
* default to the default serializer.
43+
* It is the responsibility of kryo to handle with every standard jdk classes, so we will just escape these classes.
44+
*/
45+
if (!ReflectionUtils.isJdk(type) && !type.isArray() && !type.isEnum() && !ReflectionUtils.checkZeroArgConstructor(type)) {
3846
if (logger.isWarnEnabled()) {
3947
logger.warn(type + " has no zero-arg constructor and this will affect the serialization performance");
4048
}

dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616
*/
1717
package org.apache.dubbo.common.serialize.kryo.utils;
1818

19-
import org.apache.dubbo.common.serialize.kryo.CompatibleKryo;
20-
import org.apache.dubbo.common.serialize.support.SerializableClassRegistry;
21-
2219
import com.esotericsoftware.kryo.Kryo;
20+
import com.esotericsoftware.kryo.Serializer;
2321
import com.esotericsoftware.kryo.pool.KryoFactory;
2422
import com.esotericsoftware.kryo.serializers.DefaultSerializers;
2523
import de.javakaffee.kryoserializers.ArraysAsListSerializer;
@@ -31,6 +29,8 @@
3129
import de.javakaffee.kryoserializers.URISerializer;
3230
import de.javakaffee.kryoserializers.UUIDSerializer;
3331
import de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer;
32+
import org.apache.dubbo.common.serialize.kryo.CompatibleKryo;
33+
import org.apache.dubbo.common.serialize.support.SerializableClassRegistry;
3434

3535
import java.lang.reflect.InvocationHandler;
3636
import java.math.BigDecimal;
@@ -134,9 +134,13 @@ public Kryo create() {
134134
kryo.register(clazz);
135135
}
136136

137-
for (Class clazz : SerializableClassRegistry.getRegisteredClasses()) {
138-
kryo.register(clazz);
139-
}
137+
SerializableClassRegistry.getRegisteredClasses().forEach((clazz, ser) -> {
138+
if (ser == null) {
139+
kryo.register(clazz);
140+
} else {
141+
kryo.register(clazz, (Serializer) ser);
142+
}
143+
});
140144

141145
return kryo;
142146
}

dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/utils/ReflectionUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@ public static boolean checkZeroArgConstructor(Class clazz) {
2626
return false;
2727
}
2828
}
29+
30+
public static boolean isJdk(Class clazz) {
31+
return clazz.getName().startsWith("java.") || clazz.getName().startsWith("javax.");
32+
}
2933
}

dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/serialization/AbstractSerializationTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import org.apache.dubbo.common.serialize.ObjectInput;
3535
import org.apache.dubbo.common.serialize.ObjectOutput;
3636
import org.apache.dubbo.common.serialize.Serialization;
37-
3837
import org.junit.Test;
3938

4039
import java.io.ByteArrayInputStream;
@@ -43,6 +42,7 @@
4342
import java.math.BigDecimal;
4443
import java.math.BigInteger;
4544
import java.sql.Time;
45+
import java.time.LocalDateTime;
4646
import java.util.ArrayList;
4747
import java.util.Arrays;
4848
import java.util.Date;
@@ -858,6 +858,11 @@ public void test_BizExceptionNoDefaultConstructor_WithType() throws Exception {
858858
assertEquals("Hello", ((BizExceptionNoDefaultConstructor) read).getMessage());
859859
}
860860

861+
@Test
862+
public void test_LocalDateTime() throws Exception {
863+
assertObject(LocalDateTime.now());
864+
}
865+
861866
@Test
862867
public void test_enum() throws Exception {
863868
assertObject(AnimalEnum.dog);

0 commit comments

Comments
 (0)