From 00173375f21a9fd4d64480c4420c0e9fc337dbd2 Mon Sep 17 00:00:00 2001 From: lwen Date: Mon, 6 Aug 2018 19:54:35 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=8B=93=E5=B1=95kryo=E8=AE=A9=E5=85=B6?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=B8=8D=E5=90=AB=E9=BB=98=E8=AE=A4=E6=9E=84?= =?UTF-8?q?=E9=80=A0=E6=96=B9=E6=B3=95=E7=B1=BB=E5=9E=8B=E7=9A=84=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/serialize/kryo/CompatibleKryo.java | 48 +++++++++++++++++-- .../kryo/serializer/CommonJavaSerializer.java | 21 ++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/serializer/CommonJavaSerializer.java diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryo.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryo.java index dcd000767b0..929b1867f3e 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryo.java +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryo.java @@ -16,30 +16,70 @@ */ package org.apache.dubbo.common.serialize.kryo; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Serializer; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.serialize.kryo.serializer.CommonJavaSerializer; import org.apache.dubbo.common.serialize.kryo.utils.ReflectionUtils; +import sun.reflect.ReflectionFactory; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.serializers.JavaSerializer; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.ConcurrentHashMap; public class CompatibleKryo extends Kryo { + private static ReflectionFactory reflectionFactory = ReflectionFactory + .getReflectionFactory(); + private static final Logger logger = LoggerFactory.getLogger(CompatibleKryo.class); + private static ConcurrentHashMap, Constructor> constructorCache = new ConcurrentHashMap<>(); + @Override public Serializer getDefaultSerializer(Class type) { if (type == null) { throw new IllegalArgumentException("type cannot be null."); } + // 对于这些类型的 :array 、enum、没有默认构造器的类 if (!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 new CommonJavaSerializer(); } return super.getDefaultSerializer(type); } + + @Override + public T newInstance(Class type) { + try { + return super.newInstance(type); + } catch (Exception e) { + return newInstanceByReflection(type); + } + } + + @SuppressWarnings("all") + private T newInstanceByReflection(Class type) { + Object instance = null; + try { + Constructor constructor = constructorCache.get(type); + if (constructor == null) { + constructor = reflectionFactory.newConstructorForSerialization(type, + Object.class.getDeclaredConstructor()); + constructorCache.putIfAbsent(type, constructor); + // in order to improve reflection performance + constructor.setAccessible(true); + } + instance = constructor.newInstance(); + return (T) instance; + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { + logger.error(type.getName() + "unable to be serialized", e); + e.printStackTrace(); + } + return (T) instance; + } } diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/serializer/CommonJavaSerializer.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/serializer/CommonJavaSerializer.java new file mode 100644 index 00000000000..4351ea2d597 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/serializer/CommonJavaSerializer.java @@ -0,0 +1,21 @@ +package org.apache.dubbo.common.serialize.kryo.serializer; + +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; +import com.esotericsoftware.kryo.serializers.JavaSerializer; +import org.apache.dubbo.common.serialize.kryo.CompatibleKryo; + +public class CommonJavaSerializer extends JavaSerializer { + private Kryo kryo = new CompatibleKryo(); + + @Override + public void write(Kryo kryo, Output output, Object object) { + super.write(this.kryo, output, object); + } + + @Override + public Object read(Kryo kryo, Input input, Class type) { + return super.read(this.kryo, input, type); + } +} From 6a0511e5e0785aff893afd38a8bfa8550e644517 Mon Sep 17 00:00:00 2001 From: lwen Date: Mon, 6 Aug 2018 20:31:00 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../serialize/kryo/CompatibleKryoTest.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryoTest.java diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryoTest.java b/dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryoTest.java new file mode 100644 index 00000000000..007f112f049 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryoTest.java @@ -0,0 +1,42 @@ +package org.apache.dubbo.common.serialize.kryo; + +import com.esotericsoftware.kryo.Serializer; +import com.esotericsoftware.kryo.serializers.DefaultSerializers; +import org.apache.dubbo.common.serialize.kryo.serializer.CommonJavaSerializer; +import org.junit.Test; + +import java.time.LocalDateTime; +import java.util.Date; + +import static org.junit.Assert.*; + +public class CompatibleKryoTest { + + CompatibleKryo compatibleKryo = new CompatibleKryo(); + + @Test + public void getDefaultSerializer(){ + Serializer longSerializer = compatibleKryo.getDefaultSerializer(Long.class); + assertEquals(CommonJavaSerializer.class, longSerializer.getClass()); + + Serializer localDateTimeSerializer = compatibleKryo.getDefaultSerializer(LocalDateTime.class); + assertEquals(CommonJavaSerializer.class, localDateTimeSerializer.getClass()); + + Serializer dateSerializer = compatibleKryo.getDefaultSerializer(Date.class); + assertEquals(DefaultSerializers.DateSerializer.class, dateSerializer.getClass()); + + Serializer byteSerializer = compatibleKryo.getDefaultSerializer(Byte.class); + assertEquals(CommonJavaSerializer.class, byteSerializer.getClass()); + + } + + @Test + public void newInstance() { + Long longInstance = compatibleKryo.newInstance(Long.class); + LocalDateTime localTimeInstance = compatibleKryo.newInstance(LocalDateTime.class); + Date dateInstance = compatibleKryo.newInstance(Date.class); + assertNotNull(localTimeInstance); + assertNotNull(dateInstance); + assertNotNull(longInstance); + } +} \ No newline at end of file From f472b5b98ba9112dc12146843e953cea81f212b5 Mon Sep 17 00:00:00 2001 From: lwen Date: Tue, 7 Aug 2018 09:31:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E6=8B=93=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/serialize/kryo/ExtensionKryo.java | 81 +++++++++++++++++++ .../kryo/serializer/CommonJavaSerializer.java | 4 +- .../kryo/utils/AbstractKryoFactory.java | 33 ++------ ...leKryoTest.java => ExtensionKryoTest.java} | 22 ++--- 4 files changed, 100 insertions(+), 40 deletions(-) create mode 100644 dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/ExtensionKryo.java rename dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/{CompatibleKryoTest.java => ExtensionKryoTest.java} (52%) diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/ExtensionKryo.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/ExtensionKryo.java new file mode 100644 index 00000000000..99c3ccf934e --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/ExtensionKryo.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.common.serialize.kryo; + +import com.esotericsoftware.kryo.Serializer; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.serialize.kryo.serializer.CommonJavaSerializer; +import org.apache.dubbo.common.serialize.kryo.utils.ReflectionUtils; +import sun.reflect.ReflectionFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.ConcurrentHashMap; + +public class ExtensionKryo extends CompatibleKryo { + + private static ReflectionFactory reflectionFactory = ReflectionFactory + .getReflectionFactory(); + + private static final Logger logger = LoggerFactory.getLogger(ExtensionKryo.class); + + private static ConcurrentHashMap, Constructor> constructorCache = new ConcurrentHashMap<>(); + + @Override + public Serializer getDefaultSerializer(Class type) { + if (type == null) { + throw new IllegalArgumentException("type cannot be null."); + } + + // 对于这些类型的 :array 、enum、没有默认构造器的类 + if (!type.isArray() && !type.isEnum() && !ReflectionUtils.checkZeroArgConstructor(type)) { + return new CommonJavaSerializer(); + } + return super.getDefaultSerializer(type); + } + + @Override + public T newInstance(Class type) { + try { + return super.newInstance(type); + } catch (Exception e) { + return newInstanceByReflection(type); + } + } + + @SuppressWarnings("all") + private T newInstanceByReflection(Class type) { + Object instance = null; + try { + Constructor constructor = constructorCache.get(type); + if (constructor == null) { + constructor = reflectionFactory.newConstructorForSerialization(type, + Object.class.getDeclaredConstructor()); + constructorCache.putIfAbsent(type, constructor); + // in order to improve reflection performance + constructor.setAccessible(true); + } + instance = constructor.newInstance(); + return (T) instance; + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { + logger.error(type.getName() + "unable to be serialized", e); + e.printStackTrace(); + } + return (T) instance; + } +} diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/serializer/CommonJavaSerializer.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/serializer/CommonJavaSerializer.java index 4351ea2d597..362dc5d6fbe 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/serializer/CommonJavaSerializer.java +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/serializer/CommonJavaSerializer.java @@ -4,10 +4,10 @@ import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.serializers.JavaSerializer; -import org.apache.dubbo.common.serialize.kryo.CompatibleKryo; +import org.apache.dubbo.common.serialize.kryo.ExtensionKryo; public class CommonJavaSerializer extends JavaSerializer { - private Kryo kryo = new CompatibleKryo(); + private Kryo kryo = new ExtensionKryo(); @Override public void write(Kryo kryo, Output output, Object object) { diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java index ca0abad42fa..f1e947cdc5c 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/utils/AbstractKryoFactory.java @@ -16,42 +16,19 @@ */ package org.apache.dubbo.common.serialize.kryo.utils; -import org.apache.dubbo.common.serialize.kryo.CompatibleKryo; -import org.apache.dubbo.common.serialize.support.SerializableClassRegistry; - import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.pool.KryoFactory; import com.esotericsoftware.kryo.serializers.DefaultSerializers; -import de.javakaffee.kryoserializers.ArraysAsListSerializer; -import de.javakaffee.kryoserializers.BitSetSerializer; -import de.javakaffee.kryoserializers.GregorianCalendarSerializer; -import de.javakaffee.kryoserializers.JdkProxySerializer; -import de.javakaffee.kryoserializers.RegexSerializer; -import de.javakaffee.kryoserializers.SynchronizedCollectionsSerializer; -import de.javakaffee.kryoserializers.URISerializer; -import de.javakaffee.kryoserializers.UUIDSerializer; -import de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer; +import de.javakaffee.kryoserializers.*; +import org.apache.dubbo.common.serialize.kryo.ExtensionKryo; +import org.apache.dubbo.common.serialize.support.SerializableClassRegistry; import java.lang.reflect.InvocationHandler; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; -import java.util.Vector; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; @@ -86,7 +63,7 @@ public Kryo create() { kryoCreated = true; } - Kryo kryo = new CompatibleKryo(); + Kryo kryo = new ExtensionKryo(); // TODO // kryo.setReferences(false); diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryoTest.java b/dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/ExtensionKryoTest.java similarity index 52% rename from dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryoTest.java rename to dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/ExtensionKryoTest.java index 007f112f049..1db32c412fb 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/CompatibleKryoTest.java +++ b/dubbo-serialization/dubbo-serialization-kryo/src/test/java/org/apache/dubbo/common/serialize/kryo/ExtensionKryoTest.java @@ -1,5 +1,6 @@ package org.apache.dubbo.common.serialize.kryo; +import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.serializers.DefaultSerializers; import org.apache.dubbo.common.serialize.kryo.serializer.CommonJavaSerializer; @@ -8,33 +9,34 @@ import java.time.LocalDateTime; import java.util.Date; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; -public class CompatibleKryoTest { +public class ExtensionKryoTest { - CompatibleKryo compatibleKryo = new CompatibleKryo(); + private Kryo extensionKryo = new ExtensionKryo(); @Test public void getDefaultSerializer(){ - Serializer longSerializer = compatibleKryo.getDefaultSerializer(Long.class); + Serializer longSerializer = extensionKryo.getDefaultSerializer(Long.class); assertEquals(CommonJavaSerializer.class, longSerializer.getClass()); - Serializer localDateTimeSerializer = compatibleKryo.getDefaultSerializer(LocalDateTime.class); + Serializer localDateTimeSerializer = extensionKryo.getDefaultSerializer(LocalDateTime.class); assertEquals(CommonJavaSerializer.class, localDateTimeSerializer.getClass()); - Serializer dateSerializer = compatibleKryo.getDefaultSerializer(Date.class); + Serializer dateSerializer = extensionKryo.getDefaultSerializer(Date.class); assertEquals(DefaultSerializers.DateSerializer.class, dateSerializer.getClass()); - Serializer byteSerializer = compatibleKryo.getDefaultSerializer(Byte.class); + Serializer byteSerializer = extensionKryo.getDefaultSerializer(Byte.class); assertEquals(CommonJavaSerializer.class, byteSerializer.getClass()); } @Test public void newInstance() { - Long longInstance = compatibleKryo.newInstance(Long.class); - LocalDateTime localTimeInstance = compatibleKryo.newInstance(LocalDateTime.class); - Date dateInstance = compatibleKryo.newInstance(Date.class); + Long longInstance = extensionKryo.newInstance(Long.class); + LocalDateTime localTimeInstance = extensionKryo.newInstance(LocalDateTime.class); + Date dateInstance = extensionKryo.newInstance(Date.class); assertNotNull(localTimeInstance); assertNotNull(dateInstance); assertNotNull(longInstance);