This is an automated email from the ASF dual-hosted git repository. amashenkov pushed a commit to branch ignite-13618 in repository https://gitbox.apache.org/repos/asf/ignite.git
commit 4fdc019a2dc2ecd4ab406260dc8b0ee2e015d631 Author: Andrew Mashenkov <[email protected]> AuthorDate: Mon Nov 23 13:38:16 2020 +0300 Create key/value objects using default constructor. --- .../generator/JaninoSerializerGenerator.java | 30 +++++++++++++--------- .../generator/MarshallerExprGenerator.java | 25 ++++++++++++------ .../ignite/internal/util/IgniteUnsafeUtils.java | 11 -------- .../apache/ignite/internal/util/ObjectFactory.java | 29 ++++++++++++++++----- .../benchmarks/SerializerBenchmarkTest.java | 20 +++------------ .../schema/marshaller/JavaSerializerTest.java | 16 +++--------- 6 files changed, 66 insertions(+), 65 deletions(-) diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java index def510a..654bf97 100644 --- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java +++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java @@ -121,28 +121,34 @@ public class JaninoSerializerGenerator implements SerializerFactory { "org.apache.ignite.internal.schema.SchemaDescriptor", "org.apache.ignite.internal.schema.Tuple", "org.apache.ignite.internal.schema.TupleAssembler", - "org.apache.ignite.internal.util.IgniteUnsafeUtils" + "org.apache.ignite.internal.util.IgniteUnsafeUtils", + "org.apache.ignite.internal.util.ObjectFactory" ); + // Build field accessor generators. + final MarshallerExprGenerator keyMarsh = createObjectMarshaller(keyClass, "keyFactory", schema.keyColumns(), 0); + final MarshallerExprGenerator valMarsh = createObjectMarshaller(valClass, "valFactory", schema.valueColumns(), schema.keyColumns().length()); + // Create buffer. final StringBuilder sb = new StringBuilder(INITIAL_BUFFER_SIZE); // Append class fields desctiption. sb.append("private final SchemaDescriptor schema;" + LF); - sb.append("private final Class kClass;" + LF); - sb.append("private final Class vClass;" + LF); + + if (!keyMarsh.isSimpleTypeMarshaller()) + sb.append("private final ObjectFactory keyFactory;" + LF); + if (!valMarsh.isSimpleTypeMarshaller()) + sb.append("private final ObjectFactory valFactory;" + LF); // Append constructor code. sb.append(LF + "public ").append(className).append("(SchemaDescriptor schema, Class kClass, Class vClass) {" + LF); - sb.append(TAB + "this.kClass = kClass;" + LF); - sb.append(TAB + "this.vClass = vClass;" + LF); sb.append(TAB + "this.schema = schema; " + LF); + if (!keyMarsh.isSimpleTypeMarshaller()) + sb.append(TAB + "keyFactory = new ObjectFactory(kClass);" + LF); + if (!valMarsh.isSimpleTypeMarshaller()) + sb.append(TAB + "valFactory = new ObjectFactory(vClass);" + LF); sb.append("}" + LF); - // Build field accessor generators. - final MarshallerExprGenerator keyMarsh = createObjectMarshaller(keyClass, "kClass", schema.keyColumns(), 0); - final MarshallerExprGenerator valMarsh = createObjectMarshaller(valClass, "vClass", schema.valueColumns(), schema.keyColumns().length()); - // Generate and append helper-methods. generateTupleFactoryMethod(sb, schema, keyMarsh, valMarsh); @@ -158,14 +164,14 @@ public class JaninoSerializerGenerator implements SerializerFactory { * Creates marshal/unmarshall expressions generator for object. * * @param aClass Object class. - * @param classExpr Instance class expression or {@code null} if not aplicable. + * @param factoryRefExpr Factory reference expression. * @param columns Columns that aClass mapped to. * @param firstColIdx First column absolute index in schema. * @return Marshal/unmarshall expression generator. */ private MarshallerExprGenerator createObjectMarshaller( Class<?> aClass, - @Nullable String classExpr, + @Nullable String factoryRefExpr, Columns columns, int firstColIdx ) { @@ -189,7 +195,7 @@ public class JaninoSerializerGenerator implements SerializerFactory { throw new IllegalStateException(ex); } - return new MarshallerExprGenerator(classExpr, accessors); + return new MarshallerExprGenerator(factoryRefExpr, accessors); } /** diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerExprGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerExprGenerator.java index cc2a7e1..433b567 100644 --- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerExprGenerator.java +++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerExprGenerator.java @@ -23,8 +23,8 @@ import org.apache.ignite.internal.schema.marshaller.Serializer; * Generate {@link Serializer} method's bodies. */ class MarshallerExprGenerator { - /** Instance class expression. */ - private final String classExpr; + /** Object factory regerence expression. */ + private final String factoryRefExpr; /** Object field access expression generators. */ protected FieldAccessExprGenerator[] accessors; @@ -32,12 +32,19 @@ class MarshallerExprGenerator { /** * Constructor. * - * @param classExpr Instance class expression. + * @param factoryRefExpr Object factory regerence expression. * @param accessors Object field access expression generators. */ - public MarshallerExprGenerator(String classExpr, FieldAccessExprGenerator[] accessors) { + public MarshallerExprGenerator(String factoryRefExpr, FieldAccessExprGenerator[] accessors) { this.accessors = accessors; - this.classExpr = classExpr; + this.factoryRefExpr = factoryRefExpr; + } + + /** + * @return {@code true} if it is simple object marshaller, {@code false} otherwise. + */ + boolean isSimpleTypeMarshaller() { + return factoryRefExpr == null; } /** @@ -47,19 +54,21 @@ class MarshallerExprGenerator { * @param indent Line indentation. */ public void appendUnmarshallObjectExpr(StringBuilder sb, String indent) { + assert factoryRefExpr != null; + sb.append(indent).append("Object obj;" + JaninoSerializerGenerator.LF); // Try. sb.append(indent).append("try {" + JaninoSerializerGenerator.LF); - sb.append(indent).append(JaninoSerializerGenerator.TAB + "obj = IgniteUnsafeUtils.allocateInstance(").append(classExpr).append(");" + JaninoSerializerGenerator.LF); + sb.append(indent).append(JaninoSerializerGenerator.TAB + "obj = ").append(factoryRefExpr).append(".create();" + JaninoSerializerGenerator.LF); // Read column from tuple to object field. for (int i = 0; i < accessors.length; i++) accessors[i].appendPutFieldExpr(sb, accessors[i].readColumnExpr(), indent + JaninoSerializerGenerator.TAB); // Catch and rethrow wrapped exeption. - sb.append(indent).append("} catch (InstantiationException ex) {" + JaninoSerializerGenerator.LF); + sb.append(indent).append("} catch (Exception ex) {" + JaninoSerializerGenerator.LF); sb.append(indent).append(JaninoSerializerGenerator.TAB + "throw new SerializationException(\"Failed to instantiate object: \" + ") - .append(classExpr).append(".getSimpleName(), ex);").append(JaninoSerializerGenerator.LF); + .append(factoryRefExpr).append(".getClazz().getName(), ex);").append(JaninoSerializerGenerator.LF); sb.append(indent).append("}" + JaninoSerializerGenerator.LF); } diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/util/IgniteUnsafeUtils.java b/modules/commons/src/main/java/org/apache/ignite/internal/util/IgniteUnsafeUtils.java index f9b78d4..74ea3a3 100644 --- a/modules/commons/src/main/java/org/apache/ignite/internal/util/IgniteUnsafeUtils.java +++ b/modules/commons/src/main/java/org/apache/ignite/internal/util/IgniteUnsafeUtils.java @@ -266,17 +266,6 @@ public final class IgniteUnsafeUtils { } /** - * Allocates instance of given class. - * - * @param cls Class. - * @return Allocated instance. - */ - @SuppressWarnings("rawtypes") - public static Object allocateInstance(Class cls) throws InstantiationException { - return UNSAFE.allocateInstance(cls); - } - - /** * Stub. */ private IgniteUnsafeUtils() { diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/util/ObjectFactory.java b/modules/commons/src/main/java/org/apache/ignite/internal/util/ObjectFactory.java index 1b0fb4f..f31965f 100644 --- a/modules/commons/src/main/java/org/apache/ignite/internal/util/ObjectFactory.java +++ b/modules/commons/src/main/java/org/apache/ignite/internal/util/ObjectFactory.java @@ -17,12 +17,15 @@ package org.apache.ignite.internal.util; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + /** * Object factory. */ public class ObjectFactory<T> implements Factory<T> { - /** Class. */ - private final Class<T> tClass; + /** Class default constructor. */ + private final Constructor<T> cnstr; /** * Constructor. @@ -30,16 +33,30 @@ public class ObjectFactory<T> implements Factory<T> { * @param tClass Class. */ public ObjectFactory(Class<T> tClass) { - this.tClass = tClass; + try { + cnstr = tClass.getDeclaredConstructor(); + + cnstr.setAccessible(true); + } + catch (NoSuchMethodException e) { + throw new IllegalStateException("Class has no default constructor: class=" + tClass.getName(), e); + } } /** {@inheritDoc} */ @Override public T create() throws IllegalStateException { try { - return (T)IgniteUnsafeUtils.allocateInstance(tClass); + return cnstr.newInstance(); } - catch (InstantiationException e) { - throw new IllegalStateException("Failed to instantiate class: " + tClass.getSimpleName(), e); + catch (IllegalAccessException | InvocationTargetException | InstantiationException e) { + throw new IllegalStateException("Failed to instantiate class: " + cnstr.getDeclaringClass().getName(), e); } } + + /** + * @return Class of object created by the factory. + */ + public Class<T> getClazz() { + return cnstr.getDeclaringClass(); + } } diff --git a/modules/commons/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java b/modules/commons/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java index b29def3..23193ba 100644 --- a/modules/commons/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java +++ b/modules/commons/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java @@ -17,9 +17,7 @@ package org.apache.ignite.internal.benchmarks; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.util.Random; import java.util.concurrent.TimeUnit; import org.apache.ignite.internal.schema.Column; @@ -28,6 +26,7 @@ import org.apache.ignite.internal.schema.SchemaDescriptor; import org.apache.ignite.internal.schema.marshaller.Serializer; import org.apache.ignite.internal.schema.marshaller.SerializerFactory; import org.apache.ignite.internal.util.Factory; +import org.apache.ignite.internal.util.ObjectFactory; import org.codehaus.commons.compiler.CompilerFactoryFactory; import org.codehaus.commons.compiler.IClassBodyEvaluator; import org.openjdk.jmh.annotations.Benchmark; @@ -69,11 +68,11 @@ public class SerializerBenchmarkTest { private Factory<?> objectFactory; /** Object fields count. */ - @Param({ "10", "100"}) + @Param({"10", "100"}) public int fieldsCount; /** Serializer. */ - @Param({"Janino","Java"}) + @Param({"Janino", "Java"}) public String serializerName; /** @@ -97,18 +96,7 @@ public class SerializerBenchmarkTest { rnd = new Random(seed); final Class<?> valClass = createGeneratedObjectClass(fieldsCount, Long.TYPE); -// objectFactory = new ObjectFactory<>(valClass); - final Constructor<?> constr = valClass.getDeclaredConstructor(); - objectFactory = new Factory<Object>() { - @Override public Object create() { - try { - return constr.newInstance(); - } - catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new IllegalStateException("Failed to instantiate class: " + valClass.getSimpleName(), e); - } - } - }; + objectFactory = new ObjectFactory<>(valClass); Columns keyCols = new Columns(new Column("key", LONG, true)); Columns valCols = mapFieldsToColumns(valClass); diff --git a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java index 27a156d..49ef554 100644 --- a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java +++ b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java @@ -255,18 +255,10 @@ public class JavaSerializerTest { final Object key = WrongTestObject.randomObject(rnd); final Object val = WrongTestObject.randomObject(rnd); - Serializer serializer = factory.create(schema, key.getClass(), val.getClass()); - - byte[] bytes = serializer.serialize(key, val); - - Object key1 = serializer.deserializeKey(bytes); - Object val1 = serializer.deserializeValue(bytes); - - assertTrue(key.getClass().isInstance(key1)); - assertTrue(val.getClass().isInstance(val1)); - - assertEquals(key, key); - assertEquals(val, val1); + assertThrows(IllegalStateException.class, + () -> factory.create(schema, key.getClass(), val.getClass()), + "Class has no default constructor: class=org.apache.ignite.internal.schema.marshaller.JavaSerializerTest$WrongTestObject" + ); } /**
