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 3a0646d3aafb30b8b281e22fcb29dd13f0f67e35
Author: Andrew Mashenkov <[email protected]>
AuthorDate: Thu Nov 19 13:51:27 2020 +0300

    WIP. Add serializer generator.
---
 .../ignite/internal/schema/TupleAssembler.java     |   4 -
 .../marshaller/FieldAccessExprGenerator.java       |  76 ++++
 .../marshaller/JaninoSerializerGenerator.java      | 382 +++++++++++++++++++++
 .../internal/schema/marshaller/JavaSerializer.java |  91 +----
 ...onException.java => JavaSerializerFactory.java} |  17 +-
 .../internal/schema/marshaller/Marshaller.java     |  44 ++-
 .../schema/marshaller/MarshallerFactory.java       |  74 ----
 .../internal/schema/marshaller/MarshallerUtil.java |  95 +++++
 .../marshaller/ObjectMarshallerExprGenerator.java  |  68 ++++
 .../schema/marshaller/SerializationException.java  |  10 +
 ...SerializationException.java => Serializer.java} |  25 +-
 ...zationException.java => SerializerFactory.java} |  24 +-
 ...FieldAccessor.java => UnsafeFieldAccessor.java} |  32 +-
 .../schema/marshaller/FieldAccessorTest.java       |   8 +-
 .../schema/marshaller/JavaSerializerTest.java      | 360 ++++++++++---------
 15 files changed, 925 insertions(+), 385 deletions(-)

diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/TupleAssembler.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/TupleAssembler.java
index 45d3982..71c3eda 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/TupleAssembler.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/TupleAssembler.java
@@ -17,12 +17,8 @@
 
 package org.apache.ignite.internal.schema;
 
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
 import java.nio.charset.StandardCharsets;
 import java.util.BitSet;
 import java.util.UUID;
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/FieldAccessExprGenerator.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/FieldAccessExprGenerator.java
new file mode 100644
index 0000000..1ef3484
--- /dev/null
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/FieldAccessExprGenerator.java
@@ -0,0 +1,76 @@
+/*
+ * 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.ignite.internal.schema.marshaller;
+
+class FieldAccessExprGenerator {
+    final long offset;
+    final int colIdx;
+
+    private final String castClass;
+    private final String putFieldMethod;
+    private final String getFieldMethod;
+    private final String writeColMethod;
+    private final String readColMethod;
+
+    public FieldAccessExprGenerator(int colIdx, String castClass, String 
writeColMethod,
+        String readColMethod, long offset) {
+        this(colIdx, castClass, readColMethod, writeColMethod, offset,
+            "IgniteUnsafeUtils.getObjectField", 
"IgniteUnsafeUtils.putObjectField");
+    }
+
+    public FieldAccessExprGenerator(int colIdx, String readColMethod, String 
writeColMethod, long offset,
+        String getFieldMethod, String putFieldMethod) {
+        this(colIdx, null, readColMethod, writeColMethod, offset, 
getFieldMethod, putFieldMethod);
+    }
+
+    private FieldAccessExprGenerator(int colIdx, String castClass, String 
readColMethod, String writeColMethod,
+        long offset, String getFieldMethod, String putFieldMethod) {
+        this.offset = offset;
+        this.colIdx = colIdx;
+        this.castClass = castClass;
+        this.putFieldMethod = putFieldMethod;
+        this.getFieldMethod = getFieldMethod;
+        this.writeColMethod = writeColMethod;
+        this.readColMethod = readColMethod;
+    }
+
+    public String getFieldExpr() {
+        if (offset == -1)
+            return "obj";
+
+        return getFieldMethod + "(obj, " + offset + ')';
+    }
+
+    public final void addPutFieldExpr(StringBuilder sb, String val, String 
indent) {
+        sb.append(indent).append(putFieldMethod).append("(obj, 
").append(offset).append(", ").append(val).append(')');
+        sb.append(";" + JaninoSerializerGenerator.LF);
+    }
+
+    public final void addWriteColumnExpr(StringBuilder sb, String expr, String 
indent) {
+        sb.append(indent).append(writeColMethod).append('(');
+
+        if (castClass != null)
+            sb.append("(").append(castClass).append(")");
+
+        sb.append(expr).append(");" + JaninoSerializerGenerator.LF);
+    }
+
+    public String readColumnExpr() {
+        return readColMethod + "(" + colIdx + ")";
+    }
+}
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JaninoSerializerGenerator.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JaninoSerializerGenerator.java
new file mode 100644
index 0000000..e96e5c2
--- /dev/null
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JaninoSerializerGenerator.java
@@ -0,0 +1,382 @@
+/*
+ * 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.ignite.internal.schema.marshaller;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import org.apache.ignite.internal.schema.Columns;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.apache.ignite.internal.util.IgniteUnsafeUtils;
+import org.codehaus.commons.compiler.CompilerFactoryFactory;
+import org.codehaus.commons.compiler.IClassBodyEvaluator;
+
+/**
+ *
+ */
+public class JaninoSerializerGenerator implements SerializerFactory {
+    /** Tabulate. */
+    static final String TAB = "    ";
+
+    /** Line feed. */
+    static final char LF = '\n';
+
+    /** Debug flag. */
+    private static final boolean enabledDebug = false;
+
+    @Override public Serializer create(
+        SchemaDescriptor schema,
+        Class<?> keyClass,
+        Class<?> valClass
+    ) {
+        try {
+            final String packageName = 
"org.apache.ignite.internal.schema.marshaller.";
+            final String className = "JaninoSerializerForSchema_" + 
schema.version();
+
+            final IClassBodyEvaluator ce = 
CompilerFactoryFactory.getDefaultCompilerFactory().newClassBodyEvaluator();
+
+            ce.setClassName(packageName + className);
+            ce.setImplementedInterfaces(new Class[] {Serializer.class});
+            ce.setDefaultImports(
+                "java.util.UUID",
+                "java.util.BitSet",
+
+                "org.apache.ignite.internal.schema.ByteBufferTuple",
+                "org.apache.ignite.internal.schema.Columns",
+                "org.apache.ignite.internal.schema.SchemaDescriptor",
+                "org.apache.ignite.internal.schema.Tuple",
+                "org.apache.ignite.internal.schema.TupleAssembler",
+                "org.apache.ignite.internal.util.IgniteUnsafeUtils"
+            );
+
+            final StringBuilder sb = new StringBuilder(8 * 1024);
+
+            // Create class fields and constructor.
+            sb.append("private final SchemaDescriptor schema;" + LF);
+            sb.append("private final Class kClass;" + LF);
+            sb.append("private final Class vClass;" + LF);
+            // Constructor.
+            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);
+            sb.append("}" + LF);
+
+            // Build field accessor generators.
+            final ObjectMarshallerExprGenerator keyMarsh = 
createObjectMarshaller(keyClass, "kClass", schema.keyColumns(), 0);
+            final ObjectMarshallerExprGenerator valMarsh = 
createObjectMarshaller(valClass, "vClass", schema.valueColumns(), 
schema.keyColumns().length());
+
+            generateTupleFactoryMethod(sb, schema, keyMarsh, valMarsh);
+
+            writeSerializeMethod(sb, keyMarsh, valMarsh);
+            writeDeserializeMethods(sb, keyMarsh, valMarsh);
+
+            final String code = sb.toString();
+
+            if (enabledDebug) {
+                ce.setDebuggingInformation(true, true, true);
+                //TODO: pass to logger.
+                System.out.println(code);
+            }
+
+            ce.setParentClassLoader(getClass().getClassLoader());
+            ce.cook(code);
+
+            try {
+                final Constructor<Serializer> ctor = 
(Constructor<Serializer>)ce.getClazz()
+                    .getDeclaredConstructor(schema.getClass(), Class.class, 
Class.class);
+
+                return ctor.newInstance(schema, keyClass, valClass);
+            }
+            catch (Exception ex) {
+                System.err.println(code);
+
+                throw ex;
+            }
+        }
+        catch (Exception ex) {
+            //TODO: fallback to java serializer?
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    private ObjectMarshallerExprGenerator createObjectMarshaller(Class<?> 
aClass, String classField, Columns columns,
+        int firstColIdx) {
+        BinaryMode mode = MarshallerUtil.mode(aClass);
+
+        if (mode != null)
+            return new 
ObjectMarshallerExprGenerator.IdentityObjectMarshaller(createAccessor(mode, 
firstColIdx, -1L));
+
+        FieldAccessExprGenerator[] accessors = new 
FieldAccessExprGenerator[columns.length()];
+        try {
+            for (int i = 0; i < columns.length(); i++) {
+                final Field field = 
aClass.getDeclaredField(columns.column(i).name());
+
+                accessors[i] = createAccessor(
+                    MarshallerUtil.mode(field.getType()),
+                    firstColIdx + i /* schma absolute index. */,
+                    IgniteUnsafeUtils.objectFieldOffset(field));
+            }
+        }
+        catch (NoSuchFieldException ex) {
+            throw new IllegalStateException(ex);
+        }
+
+        return new ObjectMarshallerExprGenerator(classField, accessors);
+    }
+
+    private FieldAccessExprGenerator createAccessor(BinaryMode mode, int 
colIdx, long offset) {
+        switch (mode) {
+            case BYTE:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Byte",
+                    "asm.appendByte",
+                    "tuple.byteValueBoxed",
+                    offset);
+
+            case P_BYTE:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.byteValue", "asm.appendByte",
+                    offset,
+                    "IgniteUnsafeUtils.getByteField",
+                    "IgniteUnsafeUtils.putByteField"
+                );
+
+            case SHORT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Short",
+                    "asm.appendShort",
+                    "tuple.shortValueBoxed",
+                    offset);
+
+            case P_SHORT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.shortValue", "asm.appendShort",
+                    offset,
+                    "IgniteUnsafeUtils.getShortField",
+                    "IgniteUnsafeUtils.putShortField"
+                );
+
+            case INT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Integer",
+                    "asm.appendInt",
+                    "tuple.intValueBoxed",
+                    offset);
+
+            case P_INT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.intValue", "asm.appendInt",
+                    offset,
+                    "IgniteUnsafeUtils.getIntField",
+                    "IgniteUnsafeUtils.putIntField"
+                );
+
+            case LONG:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Long",
+                    "asm.appendLong",
+                    "tuple.longValueBoxed",
+                    offset);
+
+            case P_LONG:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.longValue", "asm.appendLong",
+                    offset,
+                    "IgniteUnsafeUtils.getLongField",
+                    "IgniteUnsafeUtils.putLongField"
+                );
+
+            case FLOAT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Float",
+                    "asm.appendFloat",
+                    "tuple.floatValueBoxed",
+                    offset);
+
+            case P_FLOAT:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.floatValue", "asm.appendFloat",
+                    offset,
+                    "IgniteUnsafeUtils.getFloatField",
+                    "IgniteUnsafeUtils.putFloatField"
+                );
+
+            case DOUBLE:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "Double",
+                    "asm.appendDouble",
+                    "tuple.doubleValueBoxed",
+                    offset);
+
+            case P_DOUBLE:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "tuple.doubleValue", "asm.appendDouble",
+                    offset,
+                    "IgniteUnsafeUtils.getDoubleField",
+                    "IgniteUnsafeUtils.putDoubleField"
+                );
+
+            case UUID:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "UUID",
+                    "asm.appendUuid",
+                    "tuple.uuidValue",
+                    offset);
+
+            case BITSET:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "BitSet",
+                    "asm.appendBitmask",
+                    "tuple.bitmaskValue",
+                    offset);
+
+            case STRING:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "String",
+                    "asm.appendString",
+                    "tuple.stringValue",
+                    offset);
+
+            case BYTE_ARR:
+                return new FieldAccessExprGenerator(
+                    colIdx,
+                    "byte[]",
+                    "asm.appendBytes",
+                    "tuple.bytesValue",
+                    offset);
+            default:
+                throw new IllegalStateException("Unsupportd binary mode");
+        }
+    }
+
+    private void writeSerializeMethod(StringBuilder sb,
+        ObjectMarshallerExprGenerator keyMarsh,
+        ObjectMarshallerExprGenerator valMarsh
+    ) {
+        sb.append(LF + "@Override public byte[] serialize(Object key, Object 
val) throws SerializationException {" + LF);
+        sb.append(TAB + "TupleAssembler asm = createAssembler(key, val);" + 
LF);
+
+        sb.append(TAB + "{" + LF);
+        sb.append(TAB + TAB + "Object obj = key;" + LF);
+        keyMarsh.marshallObject(sb, TAB + TAB);
+        sb.append(TAB + "} {" + LF);
+        sb.append(TAB + TAB + "Object obj = val;" + LF);
+        valMarsh.marshallObject(sb, TAB + TAB);
+        sb.append(TAB + "}" + LF);
+
+        sb.append(TAB + "return asm.build();" + LF);
+        sb.append("}" + LF);
+    }
+
+    private void writeDeserializeMethods(StringBuilder sb,
+        ObjectMarshallerExprGenerator keyMarsh,
+        ObjectMarshallerExprGenerator valMarsh
+    ) {
+        sb.append(LF + "@Override public Object deserializeKey(byte[] data) 
throws SerializationException {" + LF);
+        sb.append(TAB + "Tuple tuple = new ByteBufferTuple(schema, data);" + 
LF);
+
+        keyMarsh.unmarshallObject(sb, TAB);
+
+        sb.append(TAB + "return obj;" + LF);
+        sb.append("}" + LF);
+
+        sb.append(LF + "@Override public Object deserializeValue(byte[] data) 
throws SerializationException {" + LF);
+        sb.append(TAB + "Tuple tuple = new ByteBufferTuple(schema, data);" + 
LF);
+
+        valMarsh.unmarshallObject(sb, TAB);
+
+        sb.append(TAB + "return obj;" + LF);
+        sb.append("}" + LF);
+    }
+
+    private void generateTupleFactoryMethod(
+        StringBuilder sb,
+        SchemaDescriptor schema,
+        ObjectMarshallerExprGenerator keyMarsh,
+        ObjectMarshallerExprGenerator valMarsh
+    ) {
+        sb.append(LF + "TupleAssembler createAssembler(Object key, Object val) 
{" + LF);
+        sb.append(TAB + "int nonNullVarlenKeys = 0; int nonNullVarlenValues = 
0;" + LF);
+        sb.append(TAB + "int nonNullVarlenKeysSize = 0; int 
nonNullVarlenValuesSize = 0;" + LF);
+        sb.append(LF);
+        sb.append(TAB + "Columns keyCols = schema.keyColumns();" + LF);
+        sb.append(TAB + "Columns valCols = schema.valueColumns();" + LF);
+        sb.append(LF);
+
+        Columns keyCols = schema.keyColumns();
+        if (keyCols.firstVarlengthColumn() >= 0) {
+            sb.append(TAB + "{" + LF);
+            sb.append(TAB + TAB + "Object fVal, obj = key;" + LF);
+
+            for (int i = keyCols.firstVarlengthColumn(); i < keyCols.length(); 
i++) {
+                assert !keyCols.column(i).type().spec().fixedLength();
+
+                sb.append(TAB + TAB + "assert 
!keyCols.column(").append(i).append(").type().spec().fixedLength();" + LF);
+                sb.append(TAB + TAB + "fVal = 
").append(keyMarsh.accessors[i].getFieldExpr()).append(";" + LF);
+                sb.append(TAB + TAB + "if (fVal != null) {" + LF);
+                sb.append(TAB + TAB + TAB + "nonNullVarlenKeysSize += 
MarshallerUtil.getValueSize(fVal, 
keyCols.column(").append(i).append(").type());").append(LF);
+                sb.append(TAB + TAB + TAB + "nonNullVarlenKeys++;" + LF);
+                sb.append(TAB + TAB + "}" + LF);
+            }
+
+            sb.append(TAB + "}" + LF);
+        }
+
+        Columns valCols = schema.valueColumns();
+        if (valCols.firstVarlengthColumn() >= 0) {
+            sb.append(TAB + "{" + LF);
+            sb.append(TAB + TAB + "Object fVal, obj = val;" + LF);
+
+            for (int i = valCols.firstVarlengthColumn(); i < valCols.length(); 
i++) {
+                assert !valCols.column(i).type().spec().fixedLength();
+
+                sb.append(TAB + TAB + "assert 
!valCols.column(").append(i).append(").type().spec().fixedLength();" + LF);
+                sb.append(TAB + TAB + "fVal = 
").append(valMarsh.accessors[i].getFieldExpr()).append(";" + LF);
+                sb.append(TAB + TAB + "if (fVal != null) {" + LF);
+                sb.append(TAB + TAB + TAB + "nonNullVarlenValuesSize += 
MarshallerUtil.getValueSize(fVal, 
valCols.column(").append(i).append(").type());" + LF);
+                sb.append(TAB + TAB + TAB + "nonNullVarlenValues++;" + LF);
+                sb.append(TAB + TAB + "}" + LF);
+            }
+            sb.append(TAB + "}" + LF);
+        }
+
+        sb.append(LF);
+        sb.append(TAB + "int size = TupleAssembler.tupleSize(" + LF);
+        sb.append(TAB + TAB + "keyCols, nonNullVarlenKeys, 
nonNullVarlenKeysSize, " + LF);
+        sb.append(TAB + TAB + "valCols, nonNullVarlenValues, 
nonNullVarlenValuesSize); " + LF);
+        sb.append(LF);
+
+        sb.append(TAB + "return new TupleAssembler(schema, size, 
nonNullVarlenKeys, nonNullVarlenValues);" + LF);
+        sb.append("}" + LF);
+    }
+}
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JavaSerializer.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JavaSerializer.java
index 9294ce9..1aae7b2 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JavaSerializer.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JavaSerializer.java
@@ -21,66 +21,16 @@ import java.util.BitSet;
 import java.util.UUID;
 import org.apache.ignite.internal.schema.ByteBufferTuple;
 import org.apache.ignite.internal.schema.Columns;
-import org.apache.ignite.internal.schema.NativeType;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.Tuple;
 import org.apache.ignite.internal.schema.TupleAssembler;
 
+import static 
org.apache.ignite.internal.schema.marshaller.MarshallerUtil.getValueSize;
+
 /**
- * Cache objects (de)serializer.
- * <p>
- * TODO: Extract interface.
+ * Reflection based (de)serializer.
  */
-public class JavaSerializer {
-    /**
-     * Gets binary read/write mode for given class.
-     *
-     * @param cls Type.
-     * @return Binary mode.
-     */
-    public static BinaryMode mode(Class<?> cls) {
-        assert cls != null;
-
-        // Primitives.
-        if (cls == byte.class)
-            return BinaryMode.P_BYTE;
-        else if (cls == short.class)
-            return BinaryMode.P_SHORT;
-        else if (cls == int.class)
-            return BinaryMode.P_INT;
-        else if (cls == long.class)
-            return BinaryMode.P_LONG;
-        else if (cls == float.class)
-            return BinaryMode.P_FLOAT;
-        else if (cls == double.class)
-            return BinaryMode.P_DOUBLE;
-
-            // Boxed primitives.
-        else if (cls == Byte.class)
-            return BinaryMode.BYTE;
-        else if (cls == Short.class)
-            return BinaryMode.SHORT;
-        else if (cls == Integer.class)
-            return BinaryMode.INT;
-        else if (cls == Long.class)
-            return BinaryMode.LONG;
-        else if (cls == Float.class)
-            return BinaryMode.FLOAT;
-        else if (cls == Double.class)
-            return BinaryMode.DOUBLE;
-
-            // Other types
-        else if (cls == byte[].class)
-            return BinaryMode.BYTE_ARR;
-        else if (cls == String.class)
-            return BinaryMode.STRING;
-        else if (cls == UUID.class)
-            return BinaryMode.UUID;
-        else if (cls == BitSet.class)
-            return BinaryMode.BITSET;
-
-        return null;
-    }
+public class JavaSerializer implements Serializer {
 
     /**
      * Reads value object from tuple.
@@ -253,8 +203,8 @@ public class JavaSerializer {
         this.keyClass = keyClass;
         this.valClass = valClass;
 
-        keyMarsh = MarshallerFactory.createMarshaller(schema.keyColumns(), 0, 
keyClass);
-        valMarsh = MarshallerFactory.createMarshaller(schema.valueColumns(), 
schema.keyColumns().length(), valClass);
+        keyMarsh = Marshaller.createMarshaller(schema.keyColumns(), 0, 
keyClass);
+        valMarsh = Marshaller.createMarshaller(schema.valueColumns(), 
schema.keyColumns().length(), valClass);
     }
 
     /**
@@ -264,7 +214,7 @@ public class JavaSerializer {
      * @param val Value object.
      * @return Serialized key-value pair.
      */
-    public byte[] serialize(Object key, Object val) throws 
SerializationException {
+    @Override public byte[] serialize(Object key, Object val) throws 
SerializationException {
         assert keyClass.isInstance(key);
         assert val == null || valClass.isInstance(val);
 
@@ -286,9 +236,8 @@ public class JavaSerializer {
      * @param key Key object.
      * @param val Value object.
      * @return Tuple assembler.
-     * @throws SerializationException If failed.
      */
-    private TupleAssembler createAssembler(Object key, Object val) throws 
SerializationException {
+    private TupleAssembler createAssembler(Object key, Object val) {
         ObjectStatistic keyStat = collectObjectStats(schema.keyColumns(), 
keyMarsh, key);
         ObjectStatistic valStat = collectObjectStats(schema.valueColumns(), 
valMarsh, val);
 
@@ -328,29 +277,9 @@ public class JavaSerializer {
     }
 
     /**
-     * Calculates size for serialized value of varlen type.
-     *
-     * @param val Field value.
-     * @param type Mapped type.
-     * @return Serialized value size.
-     */
-    private int getValueSize(Object val, NativeType type) {
-        switch (type.spec()) {
-            case BYTES:
-                return ((byte[])val).length;
-
-            case STRING:
-                return TupleAssembler.utf8EncodedLength((CharSequence)val);
-
-            default:
-                throw new IllegalStateException("Unsupported test varsize 
type: " + type);
-        }
-    }
-
-    /**
      * @return Key object.
      */
-    public Object deserializeKey(byte[] data) throws SerializationException {
+    @Override public Object deserializeKey(byte[] data) throws 
SerializationException {
         final Tuple tuple = new ByteBufferTuple(schema, data);
 
         final Object o = keyMarsh.readObject(tuple);
@@ -363,7 +292,7 @@ public class JavaSerializer {
     /**
      * @return Value object.
      */
-    public Object deserializeValue(byte[] data) throws SerializationException {
+    @Override public Object deserializeValue(byte[] data) throws 
SerializationException {
         final Tuple tuple = new ByteBufferTuple(schema, data);
 
         // TODO: add tomstone support.
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerFactory.java
similarity index 74%
copy from 
modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
copy to 
modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerFactory.java
index aa8a497..93351bb 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerFactory.java
@@ -17,17 +17,10 @@
 
 package org.apache.ignite.internal.schema.marshaller;
 
-/**
- * Serialization exception.
- */
-public class SerializationException extends Exception {
-    /**
-     * Constructor.
-     *
-     * @param message Message.
-     * @param cause Cause.
-     */
-    public SerializationException(String message, Throwable cause) {
-        super(message, cause);
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+
+public class JavaSerializerFactory implements SerializerFactory {
+    @Override public Serializer create(SchemaDescriptor schema, Class<?> 
keyClass, Class<?> valClass) {
+        return new JavaSerializer(schema, keyClass, valClass);
     }
 }
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/Marshaller.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/Marshaller.java
index 3b73a3e..deb6150 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/Marshaller.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/Marshaller.java
@@ -35,6 +35,8 @@
 package org.apache.ignite.internal.schema.marshaller;
 
 import java.util.Objects;
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.Columns;
 import org.apache.ignite.internal.schema.Tuple;
 import org.apache.ignite.internal.schema.TupleAssembler;
 import org.jetbrains.annotations.Nullable;
@@ -44,10 +46,44 @@ import org.jetbrains.annotations.Nullable;
  */
 public class Marshaller {
     /**
+     * Creates marshaller for class.
+     *
+     * @param cols Columns.
+     * @param firstColId First column position in schema.
+     * @param aClass Type.
+     * @return Marshaller.
+     */
+    public static Marshaller createMarshaller(Columns cols, int firstColId, 
Class<? extends Object> aClass) {
+        final BinaryMode mode = MarshallerUtil.mode(aClass);
+
+        if (mode != null) {
+            final Column col = cols.column(0);
+
+            assert cols.length() == 1;
+            assert mode.typeSpec() == col.type().spec() : "Target type is not 
compatible.";
+            assert !aClass.isPrimitive() : "Non-nullable types are not 
allowed.";
+
+            return new 
Marshaller(UnsafeFieldAccessor.createIdentityAccessor(col, firstColId, mode));
+        }
+
+        UnsafeFieldAccessor[] fieldAccessors = new 
UnsafeFieldAccessor[cols.length()];
+
+        // Build accessors
+        for (int i = 0; i < cols.length(); i++) {
+            final Column col = cols.column(i);
+
+            final int colIdx = firstColId + i; /* Absolute column idx in 
schema. */
+            fieldAccessors[i] = UnsafeFieldAccessor.create(aClass, col, 
colIdx);
+        }
+
+        return new Marshaller(new ObjectFactory<>(aClass), fieldAccessors);
+    }
+
+    /**
      * Field accessors for mapped columns.
      * Array has same size and order as columns.
      */
-    private final FieldAccessor[] fieldAccessors;
+    private final UnsafeFieldAccessor[] fieldAccessors;
 
     /**
      * Object factory for complex types or {@code null} for basic type.
@@ -62,7 +98,7 @@ public class Marshaller {
      * @param fieldAccessors Object field accessors for mapped columns.
      */
     @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
-    public Marshaller(Factory<?> factory, FieldAccessor[] fieldAccessors) {
+    public Marshaller(Factory<?> factory, UnsafeFieldAccessor[] 
fieldAccessors) {
         this.fieldAccessors = fieldAccessors;
         this.factory = Objects.requireNonNull(factory);
     }
@@ -73,8 +109,8 @@ public class Marshaller {
      *
      * @param fieldAccessor Identity field accessor for object of basic type.
      */
-    public Marshaller(FieldAccessor fieldAccessor) {
-        fieldAccessors = new FieldAccessor[] {fieldAccessor};
+    public Marshaller(UnsafeFieldAccessor fieldAccessor) {
+        fieldAccessors = new UnsafeFieldAccessor[] {fieldAccessor};
         factory = null;
     }
 
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerFactory.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerFactory.java
deleted file mode 100644
index 3e642da..0000000
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerFactory.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * 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.ignite.internal.schema.marshaller;
-
-import org.apache.ignite.internal.schema.Column;
-import org.apache.ignite.internal.schema.Columns;
-
-public abstract class MarshallerFactory {
-    /**
-     * Creates marshaller for class.
-     *
-     * @param cols Columns.
-     * @param firstColId First column position in schema.
-     * @param aClass Type.
-     * @return Marshaller.
-     */
-    public static Marshaller createMarshaller(Columns cols, int firstColId, 
Class<? extends Object> aClass) {
-        final BinaryMode mode = JavaSerializer.mode(aClass);
-
-        if (mode != null) {
-            final Column col = cols.column(0);
-
-            assert cols.length() == 1;
-            assert mode.typeSpec() == col.type().spec() : "Target type is not 
compatible.";
-            assert !aClass.isPrimitive() : "Non-nullable types are not 
allowed.";
-
-            return new Marshaller(FieldAccessor.createIdentityAccessor(col, 
firstColId, mode));
-        }
-
-        FieldAccessor[] fieldAccessors = new FieldAccessor[cols.length()];
-
-        // Build accessors
-        for (int i = 0; i < cols.length(); i++) {
-            final Column col = cols.column(i);
-
-            final int colIdx = firstColId + i; /* Absolute column idx in 
schema. */
-            fieldAccessors[i] = FieldAccessor.create(aClass, col, colIdx);
-        }
-
-        return new Marshaller(new ObjectFactory<>(aClass), fieldAccessors);
-    }
-}
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
new file mode 100644
index 0000000..d6ff9eb
--- /dev/null
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
@@ -0,0 +1,95 @@
+/*
+ * 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.ignite.internal.schema.marshaller;
+
+import java.util.BitSet;
+import java.util.UUID;
+import org.apache.ignite.internal.schema.NativeType;
+import org.apache.ignite.internal.schema.TupleAssembler;
+
+public class MarshallerUtil {
+    /**
+     * Calculates size for serialized value of varlen type.
+     *
+     * @param val Field value.
+     * @param type Mapped type.
+     * @return Serialized value size.
+     */
+    public static int getValueSize(Object val, NativeType type) {
+        switch (type.spec()) {
+            case BYTES:
+                return ((byte[])val).length;
+
+            case STRING:
+                return TupleAssembler.utf8EncodedLength((CharSequence)val);
+
+            default:
+                throw new IllegalStateException("Unsupported test varsize 
type: " + type);
+        }
+    }
+
+    /**
+     * Gets binary read/write mode for given class.
+     *
+     * @param cls Type.
+     * @return Binary mode.
+     */
+    public static BinaryMode mode(Class<?> cls) {
+        assert cls != null;
+
+        // Primitives.
+        if (cls == byte.class)
+            return BinaryMode.P_BYTE;
+        else if (cls == short.class)
+            return BinaryMode.P_SHORT;
+        else if (cls == int.class)
+            return BinaryMode.P_INT;
+        else if (cls == long.class)
+            return BinaryMode.P_LONG;
+        else if (cls == float.class)
+            return BinaryMode.P_FLOAT;
+        else if (cls == double.class)
+            return BinaryMode.P_DOUBLE;
+
+            // Boxed primitives.
+        else if (cls == Byte.class)
+            return BinaryMode.BYTE;
+        else if (cls == Short.class)
+            return BinaryMode.SHORT;
+        else if (cls == Integer.class)
+            return BinaryMode.INT;
+        else if (cls == Long.class)
+            return BinaryMode.LONG;
+        else if (cls == Float.class)
+            return BinaryMode.FLOAT;
+        else if (cls == Double.class)
+            return BinaryMode.DOUBLE;
+
+            // Other types
+        else if (cls == byte[].class)
+            return BinaryMode.BYTE_ARR;
+        else if (cls == String.class)
+            return BinaryMode.STRING;
+        else if (cls == UUID.class)
+            return BinaryMode.UUID;
+        else if (cls == BitSet.class)
+            return BinaryMode.BITSET;
+
+        return null;
+    }
+}
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/ObjectMarshallerExprGenerator.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/ObjectMarshallerExprGenerator.java
new file mode 100644
index 0000000..f6a274a
--- /dev/null
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/ObjectMarshallerExprGenerator.java
@@ -0,0 +1,68 @@
+/*
+ * 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.ignite.internal.schema.marshaller;
+
+class ObjectMarshallerExprGenerator {
+    private final String classFieldExpr;
+    protected FieldAccessExprGenerator[] accessors;
+
+    public ObjectMarshallerExprGenerator(String classFieldExpr, 
FieldAccessExprGenerator[] accessors) {
+        this.accessors = accessors;
+        this.classFieldExpr = classFieldExpr;
+    }
+
+    public void unmarshallObject(StringBuilder sb, String indent) {
+        sb.append(indent).append("Object obj;" + JaninoSerializerGenerator.LF);
+        sb.append(indent).append("try {" + JaninoSerializerGenerator.LF);
+        sb.append(indent).append(JaninoSerializerGenerator.TAB + "obj = 
IgniteUnsafeUtils.allocateInstance(").append(classFieldExpr).append(");" + 
JaninoSerializerGenerator.LF);
+
+        for (int i = 0; i < accessors.length; i++)
+            accessors[i].addPutFieldExpr(sb, accessors[i].readColumnExpr(), 
indent + JaninoSerializerGenerator.TAB);
+        sb.append(indent).append("} catch (InstantiationException ex) {" + 
JaninoSerializerGenerator.LF);
+
+        sb.append(indent).append(JaninoSerializerGenerator.TAB + "throw new 
SerializationException(\"Failed to instantiate object: \" + ")
+            .append(classFieldExpr).append(".getSimpleName(), 
ex);").append(JaninoSerializerGenerator.LF);
+        sb.append(indent).append("}" + JaninoSerializerGenerator.LF);
+    }
+
+    public void marshallObject(StringBuilder sb, String indent) {
+        sb.append(indent).append("try {" + JaninoSerializerGenerator.LF);
+
+        for (int i = 0; i < accessors.length; i++)
+            accessors[i].addWriteColumnExpr(sb, accessors[i].getFieldExpr(), 
indent + JaninoSerializerGenerator.TAB);
+
+        sb.append(indent).append("} catch (Exception ex) {" + 
JaninoSerializerGenerator.LF);
+        sb.append(indent).append(JaninoSerializerGenerator.TAB + "throw new 
SerializationException(ex);").append(JaninoSerializerGenerator.LF);
+        sb.append(indent).append("}" + JaninoSerializerGenerator.LF);
+    }
+
+    static class IdentityObjectMarshaller extends 
ObjectMarshallerExprGenerator {
+        IdentityObjectMarshaller(FieldAccessExprGenerator accessors) {
+            super(null, new FieldAccessExprGenerator[] {accessors});
+        }
+
+        @Override public void marshallObject(StringBuilder sb, String indent) {
+            for (int i = 0; i < accessors.length; i++)
+                accessors[i].addWriteColumnExpr(sb, "obj", indent);
+        }
+
+        @Override public void unmarshallObject(StringBuilder sb, String 
indent) {
+            sb.append(indent).append("Object obj = 
").append(accessors[0].readColumnExpr()).append(";" + 
JaninoSerializerGenerator.LF);
+        }
+    }
+}
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
index aa8a497..e690710 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
@@ -24,6 +24,16 @@ public class SerializationException extends Exception {
     /**
      * Constructor.
      *
+     * @param cause Cause.
+     */
+    public SerializationException(Throwable cause) {
+        // Used by serializers generated with Janino.
+        super(cause);
+    }
+
+    /**
+     * Constructor.
+     *
      * @param message Message.
      * @param cause Cause.
      */
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/Serializer.java
similarity index 63%
copy from 
modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
copy to 
modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/Serializer.java
index aa8a497..21a1560 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/Serializer.java
@@ -18,16 +18,25 @@
 package org.apache.ignite.internal.schema.marshaller;
 
 /**
- * Serialization exception.
+ * Key-value objects (de)serializer.
  */
-public class SerializationException extends Exception {
+public interface Serializer {
     /**
-     * Constructor.
+     * Writes key-value pair to tuple.
      *
-     * @param message Message.
-     * @param cause Cause.
+     * @param key Key object.
+     * @param val Value object.
+     * @return Serialized key-value pair.
      */
-    public SerializationException(String message, Throwable cause) {
-        super(message, cause);
-    }
+    byte[] serialize(Object key, Object val) throws SerializationException;
+
+    /**
+     * @return Key object.
+     */
+    Object deserializeKey(byte[] data) throws SerializationException;
+
+    /**
+     * @return Value object.
+     */
+    Object deserializeValue(byte[] data) throws SerializationException;
 }
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializerFactory.java
similarity index 66%
copy from 
modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
copy to 
modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializerFactory.java
index aa8a497..b83e9b9 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializationException.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializerFactory.java
@@ -17,17 +17,17 @@
 
 package org.apache.ignite.internal.schema.marshaller;
 
-/**
- * Serialization exception.
- */
-public class SerializationException extends Exception {
-    /**
-     * Constructor.
-     *
-     * @param message Message.
-     * @param cause Cause.
-     */
-    public SerializationException(String message, Throwable cause) {
-        super(message, cause);
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+
+public interface SerializerFactory {
+    public static SerializerFactory createJaninoSerializerFactory() {
+        return new JaninoSerializerGenerator();
+    }
+
+    public static SerializerFactory createJavaSerializerFactory() {
+        return new JavaSerializerFactory();
+
     }
+
+    public Serializer create(SchemaDescriptor schema, Class<?> keyClass, 
Class<?> valClass);
 }
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/FieldAccessor.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/UnsafeFieldAccessor.java
similarity index 92%
rename from 
modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/FieldAccessor.java
rename to 
modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/UnsafeFieldAccessor.java
index 713553d..1f286c6 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/FieldAccessor.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/UnsafeFieldAccessor.java
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable;
  * Field accessor to speedup access.
  */
 // TODO: Extract interface, move to java-8 profile and add Java9+ 
implementation using VarHandles.
-public abstract class FieldAccessor {
+public abstract class UnsafeFieldAccessor {
     /**
      * TODO: implement sesitive information filtering.
      *
@@ -64,14 +64,14 @@ public abstract class FieldAccessor {
      * @param colIdx Column index in schema.
      * @return Accessor.
      */
-    static FieldAccessor create(Class<?> type, Column col, int colIdx) {
+    static UnsafeFieldAccessor create(Class<?> type, Column col, int colIdx) {
         try {
             final Field field = type.getDeclaredField(col.name());
 
             if (field.getType().isPrimitive() && col.nullable())
                 throw new IllegalArgumentException("Failed to map non-nullable 
field to nullable column [name=" + field.getName() + ']');
 
-            BinaryMode mode = JavaSerializer.mode(field.getType());
+            BinaryMode mode = MarshallerUtil.mode(field.getType());
 
             switch (mode) {
                 case P_BYTE:
@@ -123,7 +123,7 @@ public abstract class FieldAccessor {
      * @param mode Binary mode.
      * @return Accessor.
      */
-    static FieldAccessor createIdentityAccessor(Column col, int colIdx, 
BinaryMode mode) {
+    static UnsafeFieldAccessor createIdentityAccessor(Column col, int colIdx, 
BinaryMode mode) {
         switch (mode) {
             //  Marshaller read/write object contract methods allowed boxed 
types only.
             case P_BYTE:
@@ -160,7 +160,7 @@ public abstract class FieldAccessor {
      * @param colIdx Column index.
      * @param mode Binary mode;
      */
-    protected FieldAccessor(Field field, int colIdx, BinaryMode mode) {
+    protected UnsafeFieldAccessor(Field field, int colIdx, BinaryMode mode) {
         assert field != null;
         assert colIdx >= 0;
         assert mode != null;
@@ -169,8 +169,6 @@ public abstract class FieldAccessor {
         this.mode = mode;
         offset = IgniteUnsafeUtils.objectFieldOffset(field);
         name = field.getName();
-
-        field.setAccessible(true);
     }
 
     /**
@@ -179,7 +177,7 @@ public abstract class FieldAccessor {
      * @param colIdx Column index.
      * @param mode Binary mode;
      */
-    private FieldAccessor(int colIdx, BinaryMode mode) {
+    private UnsafeFieldAccessor(int colIdx, BinaryMode mode) {
         assert colIdx >= 0;
         assert mode != null;
 
@@ -211,7 +209,7 @@ public abstract class FieldAccessor {
         }
         catch (Exception ex) {
             if (includeSensitive() && name != null)
-                throw new SerializationException("Failed to write field 
[name=" + name + ']', ex);
+                throw new SerializationException("Failed to read field [id=" + 
colIdx + ']', ex);
             else
                 throw new SerializationException("Failed to write field [id=" 
+ colIdx + ']', ex);
         }
@@ -277,7 +275,7 @@ public abstract class FieldAccessor {
     /**
      * Accessor for field of primitive {@code byte} type.
      */
-    private static class IdentityAccessor extends FieldAccessor {
+    private static class IdentityAccessor extends UnsafeFieldAccessor {
         /**
          * Constructor.
          *
@@ -312,7 +310,7 @@ public abstract class FieldAccessor {
     /**
      * Accessor for field of primitive {@code byte} type.
      */
-    private static class BytePrimitiveAccessor extends FieldAccessor {
+    private static class BytePrimitiveAccessor extends UnsafeFieldAccessor {
         /**
          * Constructor.
          *
@@ -341,7 +339,7 @@ public abstract class FieldAccessor {
     /**
      * Accessor for field of primitive {@code short} type.
      */
-    private static class ShortPrimitiveAccessor extends FieldAccessor {
+    private static class ShortPrimitiveAccessor extends UnsafeFieldAccessor {
         /**
          * Constructor.
          *
@@ -370,7 +368,7 @@ public abstract class FieldAccessor {
     /**
      * Accessor for field of primitive {@code int} type.
      */
-    private static class IntPrimitiveAccessor extends FieldAccessor {
+    private static class IntPrimitiveAccessor extends UnsafeFieldAccessor {
         /**
          * Constructor.
          *
@@ -399,7 +397,7 @@ public abstract class FieldAccessor {
     /**
      * Accessor for field of primitive {@code long} type.
      */
-    private static class LongPrimitiveAccessor extends FieldAccessor {
+    private static class LongPrimitiveAccessor extends UnsafeFieldAccessor {
         /**
          * Constructor.
          *
@@ -428,7 +426,7 @@ public abstract class FieldAccessor {
     /**
      * Accessor for field of primitive {@code float} type.
      */
-    private static class FloatPrimitiveAccessor extends FieldAccessor {
+    private static class FloatPrimitiveAccessor extends UnsafeFieldAccessor {
         /**
          * Constructor.
          *
@@ -457,7 +455,7 @@ public abstract class FieldAccessor {
     /**
      * Accessor for field of primitive {@code double} type.
      */
-    private static class DoublePrimitiveAccessor extends FieldAccessor {
+    private static class DoublePrimitiveAccessor extends UnsafeFieldAccessor {
         /**
          * Constructor.
          *
@@ -486,7 +484,7 @@ public abstract class FieldAccessor {
     /**
      * Accessor for field of reference type.
      */
-    private static class ReferenceFieldAccessor extends FieldAccessor {
+    private static class ReferenceFieldAccessor extends UnsafeFieldAccessor {
         /**
          * Constructor.
          *
diff --git 
a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/FieldAccessorTest.java
 
b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/FieldAccessorTest.java
index 461d66a..a4a3c56 100644
--- 
a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/FieldAccessorTest.java
+++ 
b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/FieldAccessorTest.java
@@ -101,7 +101,7 @@ public class FieldAccessorTest {
         final TestObject obj = TestObject.randomObject(rnd);
 
         for (int i = 0; i < cols.length; i++) {
-            FieldAccessor accessor = FieldAccessor.create(TestObject.class, 
cols[i], i);
+            UnsafeFieldAccessor accessor = 
UnsafeFieldAccessor.create(TestObject.class, cols[i], i);
 
             accessor.write(obj, tupleAssembler);
         }
@@ -109,7 +109,7 @@ public class FieldAccessorTest {
         final TestObject restoredObj = new TestObject();
 
         for (int i = 0; i < cols.length; i++) {
-            FieldAccessor accessor = FieldAccessor.create(TestObject.class, 
cols[i], i);
+            UnsafeFieldAccessor accessor = 
UnsafeFieldAccessor.create(TestObject.class, cols[i], i);
 
             accessor.read(restoredObj, tuple);
         }
@@ -139,7 +139,7 @@ public class FieldAccessorTest {
      */
     @Test
     public void testIdentityAccessor() throws Exception {
-        final FieldAccessor accessor = FieldAccessor.createIdentityAccessor(
+        final UnsafeFieldAccessor accessor = 
UnsafeFieldAccessor.createIdentityAccessor(
             new Column("col0", STRING, true),
             0,
             BinaryMode.STRING);
@@ -157,7 +157,7 @@ public class FieldAccessorTest {
      */
     @Test
     public void testWrongIdentityAccessor() throws Exception {
-        final FieldAccessor accessor = FieldAccessor.createIdentityAccessor(
+        final UnsafeFieldAccessor accessor = 
UnsafeFieldAccessor.createIdentityAccessor(
             new Column("col0", STRING, true),
             42,
             BinaryMode.UUID);
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 3cfb0da..53550b5 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
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.schema.marshaller;
 
 import java.util.Arrays;
 import java.util.BitSet;
+import java.util.List;
 import java.util.Objects;
 import java.util.Random;
 import java.util.UUID;
@@ -30,7 +31,8 @@ import org.apache.ignite.internal.schema.NativeTypeSpec;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.TestUtils;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import static org.apache.ignite.internal.schema.NativeType.BYTE;
 import static org.apache.ignite.internal.schema.NativeType.BYTES;
@@ -43,13 +45,20 @@ import static 
org.apache.ignite.internal.schema.NativeType.STRING;
 import static org.apache.ignite.internal.schema.NativeType.UUID;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * Serializer test.
  */
 public class JavaSerializerTest {
+
+    private static List<SerializerFactory> serializerFactoryProvider() {
+        return Arrays.asList(
+            new JaninoSerializerGenerator(),
+            new JavaSerializerFactory()
+        );
+    }
+
     /** Random. */
     private Random rnd;
 
@@ -66,189 +75,202 @@ public class JavaSerializerTest {
     }
 
     /**
-     * @throws SerializationException If serialization failed.
+     *
      */
-    @Test
-    public void testBasicTypes() throws SerializationException {
+    @ParameterizedTest
+    @MethodSource("serializerFactoryProvider")
+    public void testBasicTypes(SerializerFactory factory) throws 
SerializationException {
         // Fixed types:
-        checkBasicType(BYTE, BYTE);
-        checkBasicType(SHORT, SHORT);
-        checkBasicType(INTEGER, INTEGER);
-        checkBasicType(LONG, LONG);
-        checkBasicType(FLOAT, FLOAT);
-        checkBasicType(DOUBLE, DOUBLE);
-        checkBasicType(UUID, UUID);
-        checkBasicType(Bitmask.of(4), Bitmask.of(5));
+        checkBasicType(factory, BYTE, BYTE);
+        checkBasicType(factory, SHORT, SHORT);
+        checkBasicType(factory, INTEGER, INTEGER);
+        checkBasicType(factory, LONG, LONG);
+        checkBasicType(factory, FLOAT, FLOAT);
+        checkBasicType(factory, DOUBLE, DOUBLE);
+        checkBasicType(factory, UUID, UUID);
+        checkBasicType(factory, Bitmask.of(4), Bitmask.of(5));
 
         // Varlen types:
-        checkBasicType(BYTES, BYTES);
-        checkBasicType(STRING, STRING);
+        checkBasicType(factory, BYTES, BYTES);
+        checkBasicType(factory, STRING, STRING);
 
         // Mixed:
-        checkBasicType(LONG, INTEGER);
-        checkBasicType(INTEGER, BYTES);
-        checkBasicType(STRING, LONG);
-        checkBasicType(Bitmask.of(9), BYTES);
-    }
-
-    /**
-     * @throws SerializationException If serialization failed.
-     */
-    @Test
-    public void testComplexType() throws SerializationException {
-        Column[] cols = new Column[] {
-            new Column("pByteCol", BYTE, false),
-            new Column("pShortCol", SHORT, false),
-            new Column("pIntCol", INTEGER, false),
-            new Column("pLongCol", LONG, false),
-            new Column("pFloatCol", FLOAT, false),
-            new Column("pDoubleCol", DOUBLE, false),
-
-            new Column("byteCol", BYTE, true),
-            new Column("shortCol", SHORT, true),
-            new Column("intCol", INTEGER, true),
-            new Column("longCol", LONG, true),
-            new Column("floatCol", FLOAT, true),
-            new Column("doubleCol", DOUBLE, true),
-
-            new Column("uuidCol", UUID, true),
-            new Column("bitmaskCol", Bitmask.of(42), true),
-            new Column("stringCol", STRING, true),
-            new Column("bytesCol", BYTES, true),
-        };
-
-        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
-
-        final Object key = TestObject.randomObject(rnd);
-        final Object val = TestObject.randomObject(rnd);
-
-        JavaSerializer serializer = new JavaSerializer(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);
-    }
-
-    /**
-     *
-     */
-    @Test
-    public void testClassWithIncorrectBitmaskSize() {
-        Column[] cols = new Column[] {
-            new Column("pLongCol", LONG, false),
-            new Column("bitmaskCol", Bitmask.of(9), true),
-        };
-
-        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
-
-        final Object key = TestObject.randomObject(rnd);
-        final Object val = TestObject.randomObject(rnd);
-
-        JavaSerializer serializer = new JavaSerializer(schema, key.getClass(), 
val.getClass());
-
-        assertThrows(
-            SerializationException.class,
-            () -> serializer.serialize(key, val),
-            "Failed to write field [name=bitmaskCol]"
-        );
-    }
-
-    /**
-     *
-     */
-    @Test
-    public void testClassWithWrongFieldType() {
-        Column[] cols = new Column[] {
-            new Column("bitmaskCol", Bitmask.of(42), true),
-            new Column("shortCol", UUID, true)
-        };
-
-        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
-
-        final Object key = TestObject.randomObject(rnd);
-        final Object val = TestObject.randomObject(rnd);
-
-        JavaSerializer serializer = new JavaSerializer(schema, key.getClass(), 
val.getClass());
-
-        assertThrows(
-            SerializationException.class,
-            () -> serializer.serialize(key, val),
-            "Failed to write field [name=shortCol]"
-        );
+        checkBasicType(factory, LONG, INTEGER);
+        checkBasicType(factory, FLOAT, DOUBLE);
+        checkBasicType(factory, INTEGER, BYTES);
+        checkBasicType(factory, STRING, LONG);
+        checkBasicType(factory, Bitmask.of(9), BYTES);
     }
 
-    /**
-     *
-     */
-    @Test
-    public void testClassWithPrivateConstructor() throws 
SerializationException {
-        Column[] cols = new Column[] {
-            new Column("pLongCol", LONG, false),
-        };
-
-        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
-
-        final Object key = PrivateTestObject.randomObject(rnd);
-        final Object val = PrivateTestObject.randomObject(rnd);
-
-        JavaSerializer serializer = new JavaSerializer(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);
-    }
-
-    /**
-     *
-     */
-    @Test
-    public void testClassWithNoDefaultConstructor() throws 
SerializationException {
-        Column[] cols = new Column[] {
-            new Column("pLongCol", LONG, false),
-        };
-
-        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
-
-        final Object key = WrongTestObject.randomObject(rnd);
-        final Object val = WrongTestObject.randomObject(rnd);
-
-        final JavaSerializer serializer = new JavaSerializer(schema, 
key.getClass(), val.getClass());
-
-        final 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);
-    }
+//    /**
+//     * @throws SerializationException If serialization failed.
+//     */
+//    @ParameterizedTest
+//    @DisplayName("testComplexType")
+//    @MethodSource("serializerFactoryProvider")
+//    public void testComplexType(SerializerFactory factory) throws 
SerializationException {
+//        Column[] cols = new Column[] {
+//            new Column("pByteCol", BYTE, false),
+//            new Column("pShortCol", SHORT, false),
+//            new Column("pIntCol", INTEGER, false),
+//            new Column("pLongCol", LONG, false),
+//            new Column("pFloatCol", FLOAT, false),
+//            new Column("pDoubleCol", DOUBLE, false),
+//
+//            new Column("byteCol", BYTE, true),
+//            new Column("shortCol", SHORT, true),
+//            new Column("intCol", INTEGER, true),
+//            new Column("longCol", LONG, true),
+//            new Column("floatCol", FLOAT, true),
+//            new Column("doubleCol", DOUBLE, true),
+//
+//            new Column("uuidCol", UUID, true),
+//            new Column("bitmaskCol", Bitmask.of(42), true),
+//            new Column("stringCol", STRING, true),
+//            new Column("bytesCol", BYTES, true),
+//        };
+//
+//        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
+//
+//        final Object key = TestObject.randomObject(rnd);
+//        final Object val = TestObject.randomObject(rnd);
+//
+//        Serializer serializer = factory.create(schema, key.getClass(), 
val.getClass());
+//
+//        byte[] bytes = serializer.serialize(key, val);
+//
+//        // Try different order.
+//        Object restoredVal = serializer.deserializeValue(bytes);
+//        Object restoredKey = serializer.deserializeKey(bytes);
+//
+//        assertTrue(key.getClass().isInstance(restoredKey));
+//        assertTrue(val.getClass().isInstance(restoredVal));
+//
+//        assertEquals(key, restoredKey);
+//        assertEquals(val, restoredVal);
+//    }
+//
+//    /**
+//     *
+//     */
+//    @ParameterizedTest
+//    @MethodSource("serializerFactoryProvider")
+//    public void testClassWithIncorrectBitmaskSize(SerializerFactory factory) 
{
+//        Column[] cols = new Column[] {
+//            new Column("pLongCol", LONG, false),
+//            new Column("bitmaskCol", Bitmask.of(9), true),
+//        };
+//
+//        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
+//
+//        final Object key = TestObject.randomObject(rnd);
+//        final Object val = TestObject.randomObject(rnd);
+//
+//        Serializer serializer = factory.create(schema, key.getClass(), 
val.getClass());
+//
+//        assertThrows(
+//            SerializationException.class,
+//            () -> serializer.serialize(key, val),
+//            "Failed to write field [name=bitmaskCol]"
+//        );
+//    }
+//
+//    /**
+//     *
+//     */
+//    @ParameterizedTest
+//    @DisplayName("testClassWithWrongFieldType")
+//    @MethodSource("serializerFactoryProvider")
+//    public void testClassWithWrongFieldType(SerializerFactory factory) 
throws Exception {
+//        Column[] cols = new Column[] {
+//            new Column("bitmaskCol", Bitmask.of(42), true),
+//            new Column("shortCol", UUID, true)
+//        };
+//
+//        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
+//
+//        final Object key = TestObject.randomObject(rnd);
+//        final Object val = TestObject.randomObject(rnd);
+//
+//        Serializer serializer = factory.create(schema, key.getClass(), 
val.getClass());
+//
+//        assertThrows(
+//            SerializationException.class,
+//            () -> serializer.serialize(key, val),
+//            "Failed to write field [name=shortCol]"
+//        );
+//    }
+//
+//    /**
+//     *
+//     */
+//    @ParameterizedTest
+//    @MethodSource("serializerFactoryProvider")
+//    public void testClassWithPrivateConstructor(SerializerFactory factory) 
throws SerializationException {
+//        Column[] cols = new Column[] {
+//            new Column("pLongCol", LONG, false),
+//        };
+//
+//        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
+//
+//        final Object key = PrivateTestObject.randomObject(rnd);
+//        final Object val = PrivateTestObject.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);
+//    }
+//
+//    /**
+//     *
+//     */
+//    @ParameterizedTest
+//    @DisplayName("testClassWithNoDefaultConstructor")
+//    @MethodSource("serializerFactoryProvider")
+//    public void testClassWithNoDefaultConstructor(SerializerFactory factory) 
throws SerializationException {
+//        Column[] cols = new Column[] {
+//            new Column("pLongCol", LONG, false),
+//        };
+//
+//        SchemaDescriptor schema = new SchemaDescriptor(1, new Columns(cols), 
new Columns(cols.clone()));
+//
+//        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);
+//    }
 
     /**
      * Generate random key-value pair of given types and
      * check serialization and deserialization works fine.
      *
+     * @param factory Serializer factory.
      * @param keyType Key type.
      * @param valType Value type.
      * @throws SerializationException If (de)serialization failed.
      */
-    private void checkBasicType(NativeType keyType, NativeType valType) throws 
SerializationException {
+    private void checkBasicType(SerializerFactory factory, NativeType keyType,
+        NativeType valType) throws SerializationException {
         final Object key = generateRandomValue(keyType);
         final Object val = generateRandomValue(valType);
 
@@ -257,7 +279,7 @@ public class JavaSerializerTest {
 
         SchemaDescriptor schema = new SchemaDescriptor(1, new 
Columns(keyCols), new Columns(valCols));
 
-        JavaSerializer serializer = new JavaSerializer(schema, key.getClass(), 
val.getClass());
+        Serializer serializer = factory.create(schema, key.getClass(), 
val.getClass());
 
         byte[] bytes = serializer.serialize(key, val);
 

Reply via email to