This is an automated email from the ASF dual-hosted git repository.

nizhikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 5ce8f9f2c44 IGNITE-27540 Move BinaryReader and BinaryWriter 
implementations to binary-impl (#12626)
5ce8f9f2c44 is described below

commit 5ce8f9f2c44c4ddf4245bc516f6fab63cca6718a
Author: Nikolay <[email protected]>
AuthorDate: Tue Jan 13 13:41:19 2026 +0300

    IGNITE-27540 Move BinaryReader and BinaryWriter implementations to 
binary-impl (#12626)
---
 .../ignite/internal/binary/BinariesFactory.java    | 102 +++
 .../internal/binary/BinaryClassDescriptor.java     | 126 +--
 .../ignite/internal/binary/BinaryContext.java      |   2 +-
 .../internal/binary/BinaryFieldAccessor.java       | 928 ---------------------
 .../internal/binary/BinaryFieldDescriptor.java     |  65 ++
 .../internal/binary/BinaryFieldMetadata.java       |   9 -
 .../ignite/internal/binary/BinaryObjectImpl.java   |   2 +-
 .../internal/binary/BinaryObjectOffheapImpl.java   |   2 +-
 .../ignite/internal/binary/BinaryReaderEx.java     |   7 +
 .../ignite/internal/binary/BinarySchema.java       |   2 +-
 .../apache/ignite/internal/binary/BinaryUtils.java |  62 +-
 .../ignite/internal/binary/BinaryWriterEx.java     |  54 ++
 .../internal/binary/BinariesFactoryImpl.java       | 145 ++++
 .../ignite/internal/binary/BinaryReaderExImpl.java | 411 ++++++++-
 .../ignite/internal/binary/BinaryWriterExImpl.java | 349 +++++++-
 ...g.apache.ignite.internal.binary.BinariesFactory |   1 +
 16 files changed, 1148 insertions(+), 1119 deletions(-)

diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinariesFactory.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinariesFactory.java
new file mode 100644
index 00000000000..102154b3604
--- /dev/null
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinariesFactory.java
@@ -0,0 +1,102 @@
+/*
+ * 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.binary;
+
+import java.lang.reflect.Field;
+import org.apache.ignite.internal.binary.streams.BinaryInputStream;
+import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Factory for binaries classes creation.
+ */
+public interface BinariesFactory {
+    /**
+     * Creates reader instance.
+     *
+     * @param ctx Context.
+     * @param in Input stream.
+     * @param ldr Class loader.
+     * @param forUnmarshal {@code True} if reader is needed to unmarshal 
object.
+     */
+    public BinaryReaderEx reader(BinaryContext ctx, BinaryInputStream in, 
ClassLoader ldr, boolean forUnmarshal);
+
+    /**
+     * Creates reader instance.
+     *
+     * @param ctx Context.
+     * @param in Input stream.
+     * @param ldr Class loader.
+     * @param hnds Context.
+     * @param forUnmarshal {@code True} if reader is needed to unmarshal 
object.
+     */
+    public BinaryReaderEx reader(BinaryContext ctx,
+                                 BinaryInputStream in,
+                                 ClassLoader ldr,
+                                 @Nullable BinaryReaderHandles hnds,
+                                 boolean forUnmarshal);
+
+    /**
+     * Constructor.
+     *
+     * @param ctx Context.
+     * @param in Input stream.
+     * @param ldr Class loader.
+     * @param hnds Context.
+     * @param skipHdrCheck Whether to skip header check.
+     * @param forUnmarshal {@code True} if reader is needed to unmarshal 
object.
+     */
+    public BinaryReaderEx reader(BinaryContext ctx,
+                                 BinaryInputStream in,
+                                 ClassLoader ldr,
+                                 @Nullable BinaryReaderHandles hnds,
+                                 boolean skipHdrCheck,
+                                 boolean forUnmarshal);
+
+    /**
+     * @param ctx Context.
+     * @param failIfUnregistered Flag to fail while writing object of 
unregistered type.
+     * @param typeId Type id.
+     * @return Writer instance.
+     */
+    public BinaryWriterEx writer(BinaryContext ctx, boolean 
failIfUnregistered, int typeId);
+
+    /**
+     * @param ctx Context.
+     * @param out Output stream.
+     * @return Writer instance.
+     */
+    public BinaryWriterEx writer(BinaryContext ctx, BinaryOutputStream out);
+
+    /**
+     * @param ctx Context.
+     * @param out Output stream.
+     * @param schema Schema holder
+     * @return Writer instance.
+     */
+    public BinaryWriterEx writer(BinaryContext ctx, BinaryOutputStream out, 
BinaryWriterSchemaHolder schema);
+
+    /**
+     * Create accessor for the field.
+     *
+     * @param field Field.
+     * @param id Field ID.
+     * @return Accessor.
+     */
+    public BinaryFieldDescriptor create(Field field, int id);
+}
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java
index a9ca32721a5..9b82ee2d9d0 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java
@@ -64,10 +64,10 @@ class BinaryClassDescriptor {
     private final BinaryContext ctx;
 
     /** */
-    private final Class<?> cls;
+    final Class<?> cls;
 
     /** Configured serializer. */
-    private final BinarySerializer serializer;
+    final BinarySerializer serializer;
 
     /** Serializer that is passed during BinaryClassDescriptor construction. 
Can differ from {@link #serializer}. */
     private final BinarySerializer initialSerializer;
@@ -76,7 +76,7 @@ class BinaryClassDescriptor {
     private final BinaryInternalMapper mapper;
 
     /** */
-    private final BinaryWriteMode mode;
+    final BinaryWriteMode mode;
 
     /** */
     private final boolean userType;
@@ -85,7 +85,7 @@ class BinaryClassDescriptor {
     private final int typeId;
 
     /** */
-    private final String typeName;
+    final String typeName;
 
     /** Affinity key field name. */
     private final String affKeyFieldName;
@@ -94,13 +94,13 @@ class BinaryClassDescriptor {
     private final Constructor<?> ctor;
 
     /** */
-    private final BinaryFieldAccessor[] fields;
+    final BinaryFieldDescriptor[] fields;
 
     /** Write replacer. */
     private final BinaryWriteReplacer writeReplacer;
 
     /** */
-    private final Method readResolveMtd;
+    final Method readResolveMtd;
 
     /** */
     private final Map<String, BinaryFieldMetadata> stableFieldsMeta;
@@ -328,7 +328,7 @@ class BinaryClassDescriptor {
                     stableSchema = null;
                 }
                 else {
-                    Map<Object, BinaryFieldAccessor> fields0;
+                    Map<Object, BinaryFieldDescriptor> fields0;
 
                     if (BinaryUtils.FIELDS_SORTED_ORDER) {
                         fields0 = new TreeMap<>();
@@ -365,21 +365,21 @@ class BinaryClassDescriptor {
                                 if (!ids.add(fieldId))
                                     throw new BinaryObjectException("Duplicate 
field ID: " + name);
 
-                                BinaryFieldAccessor fieldInfo = 
BinaryFieldAccessor.create(f, fieldId);
+                                BinaryFieldDescriptor fieldInfo = 
BinaryUtils.binariesFactory.create(f, fieldId);
 
                                 fields0.put(name, fieldInfo);
 
                                 if (metaDataEnabled)
-                                    stableFieldsMeta.put(name, new 
BinaryFieldMetadata(fieldInfo));
+                                    stableFieldsMeta.put(name, new 
BinaryFieldMetadata(fieldInfo.mode.typeId(), fieldInfo.id));
                             }
                         }
                     }
 
-                    fields = fields0.values().toArray(new 
BinaryFieldAccessor[fields0.size()]);
+                    fields = fields0.values().toArray(new 
BinaryFieldDescriptor[fields0.size()]);
 
                     BinarySchema.Builder schemaBuilder = 
BinarySchema.Builder.newBuilder();
 
-                    for (BinaryFieldAccessor field : fields)
+                    for (BinaryFieldDescriptor field : fields)
                         schemaBuilder.addField(field.id);
 
                     stableSchema = schemaBuilder.build();
@@ -602,7 +602,7 @@ class BinaryClassDescriptor {
      * @param writer Writer.
      * @throws BinaryObjectException In case of error.
      */
-    void write(Object obj, BinaryWriterExImpl writer) throws 
BinaryObjectException {
+    void write(Object obj, BinaryWriterEx writer) throws BinaryObjectException 
{
         try {
             assert obj != null;
             assert writer != null;
@@ -781,7 +781,7 @@ class BinaryClassDescriptor {
                     break;
 
                 case BINARY_ENUM:
-                    writer.writeBinaryEnum((BinaryEnumObjectImpl)obj);
+                    writer.writeBinaryEnum((BinaryObjectEx)obj);
 
                     break;
 
@@ -804,7 +804,7 @@ class BinaryClassDescriptor {
                     break;
 
                 case BINARY_OBJ:
-                    writer.writeBinaryObject((BinaryObjectImpl)obj);
+                    writer.writeBinaryObject((BinaryObjectEx)obj);
 
                     break;
 
@@ -870,8 +870,20 @@ class BinaryClassDescriptor {
 
                     if (preWrite(writer, obj)) {
                         try {
-                            for (BinaryFieldAccessor info : fields)
-                                info.write(obj, writer);
+                            for (BinaryFieldDescriptor info : fields) {
+                                try {
+                                    writer.writeField(obj, info);
+                                }
+                                catch (UnregisteredClassException | 
UnregisteredBinaryTypeException ex) {
+                                    throw ex;
+                                }
+                                catch (Exception ex) {
+                                    if (S.includeSensitive() && 
!F.isEmpty(info.name))
+                                        throw new 
BinaryObjectException("Failed to write field [name=" + info.name + ']', ex);
+                                    else
+                                        throw new 
BinaryObjectException("Failed to write field [id=" + info.id + ']', ex);
+                                }
+                            }
 
                             writer.schemaId(stableSchema.schemaId());
 
@@ -906,80 +918,6 @@ class BinaryClassDescriptor {
         }
     }
 
-    /**
-     * @param reader Reader.
-     * @return Object.
-     * @throws BinaryObjectException If failed.
-     */
-    Object read(BinaryReaderExImpl reader) throws BinaryObjectException {
-        try {
-            assert reader != null;
-            assert mode != BinaryWriteMode.OPTIMIZED : "OptimizedMarshaller 
should not be used here: " + cls.getName();
-
-            Object res;
-
-            switch (mode) {
-                case BINARY:
-                    res = newInstance();
-
-                    reader.setHandle(res);
-
-                    if (serializer != null)
-                        serializer.readBinary(res, reader);
-                    else
-                        ((Binarylizable)res).readBinary(reader);
-
-                    break;
-
-                case OBJECT:
-                    res = newInstance();
-
-                    reader.setHandle(res);
-
-                    for (BinaryFieldAccessor info : fields)
-                        info.read(res, reader);
-
-                    break;
-
-                default:
-                    assert false : "Invalid mode: " + mode;
-
-                    return null;
-            }
-
-            if (readResolveMtd != null) {
-                try {
-                    res = readResolveMtd.invoke(res);
-
-                    reader.setHandle(res);
-                }
-                catch (IllegalAccessException e) {
-                    throw new RuntimeException(e);
-                }
-                catch (InvocationTargetException e) {
-                    if (e.getTargetException() instanceof 
BinaryObjectException)
-                        throw (BinaryObjectException)e.getTargetException();
-
-                    throw new BinaryObjectException("Failed to execute 
readResolve() method on " + res, e);
-                }
-            }
-
-            return res;
-        }
-        catch (Exception e) {
-            String msg;
-
-            if (S.includeSensitive() && !F.isEmpty(typeName))
-                msg = "Failed to deserialize object [typeName=" + typeName + 
']';
-            else
-                msg = "Failed to deserialize object [typeId=" + typeId + ']';
-
-            CommonUtils.error(ctx.log(), msg, e);
-
-            throw new BinaryObjectException(msg, e);
-        }
-    }
-
     /**
      * @return A copy of this {@code BinaryClassDescriptor} marked as 
registered.
      */
@@ -1037,7 +975,7 @@ class BinaryClassDescriptor {
      * @param obj Object.
      * @return Whether further write is needed.
      */
-    private boolean preWrite(BinaryWriterExImpl writer, Object obj) {
+    private boolean preWrite(BinaryWriterEx writer, Object obj) {
         if (writer.tryWriteAsHandle(obj))
             return false;
 
@@ -1051,7 +989,7 @@ class BinaryClassDescriptor {
      *
      * @param writer Writer.
      */
-    private void postWrite(BinaryWriterExImpl writer) {
+    private void postWrite(BinaryWriterEx writer) {
         writer.postWrite(userType, registered);
     }
 
@@ -1061,7 +999,7 @@ class BinaryClassDescriptor {
      * @param writer Writer.
      * @param obj Object.
      */
-    private void postWriteHashCode(BinaryWriterExImpl writer, Object obj) {
+    private void postWriteHashCode(BinaryWriterEx writer, Object obj) {
         boolean postWriteRequired = !(obj instanceof CacheObject) || 
((CacheObject)obj).postWriteRequired();
         // No need to call "postWriteHashCode" here because we do not care 
about hash code.
         if (postWriteRequired)
@@ -1072,7 +1010,7 @@ class BinaryClassDescriptor {
      * @return Instance.
      * @throws BinaryObjectException In case of error.
      */
-    private Object newInstance() throws BinaryObjectException {
+    Object newInstance() throws BinaryObjectException {
         try {
             return ctor != null ? ctor.newInstance() : 
GridUnsafe.allocateInstance(cls);
         }
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
index 151254243c6..004593af1b3 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
@@ -1380,7 +1380,7 @@ public class BinaryContext {
                 typeName = meta.typeName();
             }
 
-            BinarySchema curSchema = 
((BinaryWriterExImpl)writer).currentSchema();
+            BinarySchema curSchema = writer.currentSchema();
 
             if (affFieldName == null)
                 affFieldName = affinityKeyFieldName(typeId);
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java
deleted file mode 100644
index dea0592156b..00000000000
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java
+++ /dev/null
@@ -1,928 +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.
- */
-
-package org.apache.ignite.internal.binary;
-
-import java.lang.reflect.Field;
-import java.math.BigDecimal;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-import java.util.UUID;
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.UnregisteredBinaryTypeException;
-import org.apache.ignite.internal.UnregisteredClassException;
-import org.apache.ignite.internal.util.CommonUtils;
-import org.apache.ignite.internal.util.GridUnsafe;
-import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.internal.util.typedef.internal.S;
-
-/**
- * Field accessor to speedup access.
- */
-abstract class BinaryFieldAccessor {
-    /** Field ID. */
-    protected final int id;
-
-    /** Field name */
-    protected final String name;
-
-    /** Mode. */
-    protected final BinaryWriteMode mode;
-
-    /**
-     * Create accessor for the field.
-     *
-     * @param field Field.
-     * @param id FIeld ID.
-     * @return Accessor.
-     */
-    public static BinaryFieldAccessor create(Field field, int id) {
-        BinaryWriteMode mode = BinaryUtils.mode(field.getType());
-
-        switch (mode) {
-            case P_BYTE:
-                return new BytePrimitiveAccessor(field, id);
-
-            case P_BOOLEAN:
-                return new BooleanPrimitiveAccessor(field, id);
-
-            case P_SHORT:
-                return new ShortPrimitiveAccessor(field, id);
-
-            case P_CHAR:
-                return new CharPrimitiveAccessor(field, id);
-
-            case P_INT:
-                return new IntPrimitiveAccessor(field, id);
-
-            case P_LONG:
-                return new LongPrimitiveAccessor(field, id);
-
-            case P_FLOAT:
-                return new FloatPrimitiveAccessor(field, id);
-
-            case P_DOUBLE:
-                return new DoublePrimitiveAccessor(field, id);
-
-            case BYTE:
-            case BOOLEAN:
-            case SHORT:
-            case CHAR:
-            case INT:
-            case LONG:
-            case FLOAT:
-            case DOUBLE:
-            case DECIMAL:
-            case STRING:
-            case UUID:
-            case DATE:
-            case TIMESTAMP:
-            case TIME:
-            case BYTE_ARR:
-            case SHORT_ARR:
-            case INT_ARR:
-            case LONG_ARR:
-            case FLOAT_ARR:
-            case DOUBLE_ARR:
-            case CHAR_ARR:
-            case BOOLEAN_ARR:
-            case DECIMAL_ARR:
-            case STRING_ARR:
-            case UUID_ARR:
-            case DATE_ARR:
-            case TIMESTAMP_ARR:
-            case TIME_ARR:
-            case ENUM_ARR:
-            case OBJECT_ARR:
-            case BINARY_OBJ:
-            case BINARY:
-                return new DefaultFinalClassAccessor(field, id, mode, false);
-
-            default:
-                return new DefaultFinalClassAccessor(field, id, mode, 
!CommonUtils.isFinal(field.getType()));
-        }
-    }
-
-    /**
-     * Protected constructor.
-     *
-     * @param id Field ID.
-     * @param mode Mode;
-     */
-    protected BinaryFieldAccessor(Field field, int id, BinaryWriteMode mode) {
-        assert field != null;
-        assert id != 0;
-        assert mode != null;
-
-        this.name = field.getName();
-        this.id = id;
-        this.mode = mode;
-    }
-
-    /**
-     * Get mode.
-     *
-     * @return Mode.
-     */
-    public BinaryWriteMode mode() {
-        return mode;
-    }
-
-    /**
-     * Write field.
-     *
-     * @param obj Object.
-     * @param writer Writer.
-     * @throws BinaryObjectException If failed.
-     */
-    public void write(Object obj, BinaryWriterExImpl writer) throws 
BinaryObjectException {
-        try {
-            write0(obj, writer);
-        }
-        catch (UnregisteredClassException | UnregisteredBinaryTypeException 
ex) {
-            throw ex;
-        }
-        catch (Exception ex) {
-            if (S.includeSensitive() && !F.isEmpty(name))
-                throw new BinaryObjectException("Failed to write field [name=" 
+ name + ']', ex);
-            else
-                throw new BinaryObjectException("Failed to write field [id=" + 
id + ']', ex);
-        }
-    }
-
-    /**
-     * Write field.
-     *
-     * @param obj Object.
-     * @param writer Writer.
-     * @throws BinaryObjectException If failed.
-     */
-    protected abstract void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException;
-
-    /**
-     * Read field.
-     *
-     * @param obj Object.
-     * @param reader Reader.
-     * @throws BinaryObjectException If failed.
-     */
-    public void read(Object obj, BinaryReaderExImpl reader) throws 
BinaryObjectException {
-        try {
-            read0(obj, reader);
-        }
-        catch (Exception ex) {
-            if (S.includeSensitive() && !F.isEmpty(name))
-                throw new BinaryObjectException("Failed to read field [name=" 
+ name + ']', ex);
-            else
-                throw new BinaryObjectException("Failed to read field [id=" + 
id + ']', ex);
-        }
-    }
-
-    /**
-     * Read field.
-     *
-     * @param obj Object.
-     * @param reader Reader.
-     * @throws BinaryObjectException If failed.
-     */
-    protected abstract void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException;
-
-    /**
-     * Base primitive field accessor.
-     */
-    private abstract static class AbstractPrimitiveAccessor extends 
BinaryFieldAccessor {
-        /** Offset. */
-        protected final long offset;
-
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         * @param id Field ID.
-         * @param mode Mode.
-         */
-        protected AbstractPrimitiveAccessor(Field field, int id, 
BinaryWriteMode mode) {
-            super(field, id, mode);
-
-            offset = GridUnsafe.objectFieldOffset(field);
-        }
-    }
-
-    /**
-     * Byte field accessor.
-     */
-    private static class BytePrimitiveAccessor extends 
AbstractPrimitiveAccessor {
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         */
-        public BytePrimitiveAccessor(Field field, int id) {
-            super(field, id, BinaryWriteMode.P_BYTE);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            byte val = GridUnsafe.getByteField(obj, offset);
-
-            writer.writeByteFieldPrimitive(val);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            byte val = reader.readByte(id);
-
-            GridUnsafe.putByteField(obj, offset, val);
-        }
-    }
-
-    /**
-     * Boolean field accessor.
-     */
-    private static class BooleanPrimitiveAccessor extends 
AbstractPrimitiveAccessor {
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         */
-        public BooleanPrimitiveAccessor(Field field, int id) {
-            super(field, id, BinaryWriteMode.P_BOOLEAN);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            boolean val = GridUnsafe.getBooleanField(obj, offset);
-
-            writer.writeBooleanFieldPrimitive(val);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            boolean val = reader.readBoolean(id);
-
-            GridUnsafe.putBooleanField(obj, offset, val);
-        }
-    }
-
-    /**
-     * Short field accessor.
-     */
-    private static class ShortPrimitiveAccessor extends 
AbstractPrimitiveAccessor {
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         */
-        public ShortPrimitiveAccessor(Field field, int id) {
-            super(field, id, BinaryWriteMode.P_SHORT);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            short val = GridUnsafe.getShortField(obj, offset);
-
-            writer.writeShortFieldPrimitive(val);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            short val = reader.readShort(id);
-
-            GridUnsafe.putShortField(obj, offset, val);
-        }
-    }
-
-    /**
-     * Char field accessor.
-     */
-    private static class CharPrimitiveAccessor extends 
AbstractPrimitiveAccessor {
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         */
-        public CharPrimitiveAccessor(Field field, int id) {
-            super(field, id, BinaryWriteMode.P_CHAR);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            char val = GridUnsafe.getCharField(obj, offset);
-
-            writer.writeCharFieldPrimitive(val);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            char val = reader.readChar(id);
-
-            GridUnsafe.putCharField(obj, offset, val);
-        }
-    }
-
-    /**
-     * Int field accessor.
-     */
-    private static class IntPrimitiveAccessor extends 
AbstractPrimitiveAccessor {
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         */
-        public IntPrimitiveAccessor(Field field, int id) {
-            super(field, id, BinaryWriteMode.P_INT);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            int val = GridUnsafe.getIntField(obj, offset);
-
-            writer.writeIntFieldPrimitive(val);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            int val = reader.readInt(id);
-
-            GridUnsafe.putIntField(obj, offset, val);
-        }
-    }
-
-    /**
-     * Long field accessor.
-     */
-    private static class LongPrimitiveAccessor extends 
AbstractPrimitiveAccessor {
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         */
-        public LongPrimitiveAccessor(Field field, int id) {
-            super(field, id, BinaryWriteMode.P_LONG);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            long val = GridUnsafe.getLongField(obj, offset);
-
-            writer.writeLongFieldPrimitive(val);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            long val = reader.readLong(id);
-
-            GridUnsafe.putLongField(obj, offset, val);
-        }
-    }
-
-    /**
-     * Float field accessor.
-     */
-    private static class FloatPrimitiveAccessor extends 
AbstractPrimitiveAccessor {
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         */
-        public FloatPrimitiveAccessor(Field field, int id) {
-            super(field, id, BinaryWriteMode.P_FLOAT);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            float val = GridUnsafe.getFloatField(obj, offset);
-
-            writer.writeFloatFieldPrimitive(val);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            float val = reader.readFloat(id);
-
-            GridUnsafe.putFloatField(obj, offset, val);
-        }
-    }
-
-    /**
-     * Double field accessor.
-     */
-    private static class DoublePrimitiveAccessor extends 
AbstractPrimitiveAccessor {
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         */
-        public DoublePrimitiveAccessor(Field field, int id) {
-            super(field, id, BinaryWriteMode.P_DOUBLE);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            double val = GridUnsafe.getDoubleField(obj, offset);
-
-            writer.writeDoubleFieldPrimitive(val);
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            double val = reader.readDouble(id);
-
-            GridUnsafe.putDoubleField(obj, offset, val);
-        }
-    }
-
-    /**
-     * Default accessor.
-     */
-    private static class DefaultFinalClassAccessor extends BinaryFieldAccessor 
{
-        /** Target field. */
-        private final Field field;
-
-        /** Dynamic accessor flag. */
-        private final boolean dynamic;
-
-        /**
-         * Constructor.
-         *
-         * @param field Field.
-         * @param id Field ID.
-         * @param mode Mode.
-         */
-        DefaultFinalClassAccessor(Field field, int id, BinaryWriteMode mode, 
boolean dynamic) {
-            super(field, id, mode);
-
-            this.field = field;
-            this.dynamic = dynamic;
-        }
-
-        /** {@inheritDoc} */
-        @Override protected void write0(Object obj, BinaryWriterExImpl writer) 
throws BinaryObjectException {
-            assert obj != null;
-            assert writer != null;
-
-            writer.writeFieldIdNoSchemaUpdate(id);
-
-            Object val;
-
-            try {
-                val = field.get(obj);
-            }
-            catch (IllegalAccessException e) {
-                throw new BinaryObjectException("Failed to get value for 
field: " + field, e);
-            }
-
-            switch (mode(val)) {
-                case BYTE:
-                    writer.writeByteField((Byte)val);
-
-                    break;
-
-                case SHORT:
-                    writer.writeShortField((Short)val);
-
-                    break;
-
-                case INT:
-                    writer.writeIntField((Integer)val);
-
-                    break;
-
-                case LONG:
-                    writer.writeLongField((Long)val);
-
-                    break;
-
-                case FLOAT:
-                    writer.writeFloatField((Float)val);
-
-                    break;
-
-                case DOUBLE:
-                    writer.writeDoubleField((Double)val);
-
-                    break;
-
-                case CHAR:
-                    writer.writeCharField((Character)val);
-
-                    break;
-
-                case BOOLEAN:
-                    writer.writeBooleanField((Boolean)val);
-
-                    break;
-
-                case DECIMAL:
-                    writer.writeDecimal((BigDecimal)val);
-
-                    break;
-
-                case STRING:
-                    writer.writeString((String)val);
-
-                    break;
-
-                case UUID:
-                    writer.writeUuid((UUID)val);
-
-                    break;
-
-                case DATE:
-                    writer.writeDate((Date)val);
-
-                    break;
-
-                case TIMESTAMP:
-                    writer.writeTimestamp((Timestamp)val);
-
-                    break;
-
-                case TIME:
-                    writer.writeTime((Time)val);
-
-                    break;
-
-                case BYTE_ARR:
-                    writer.writeByteArray((byte[])val);
-
-                    break;
-
-                case SHORT_ARR:
-                    writer.writeShortArray((short[])val);
-
-                    break;
-
-                case INT_ARR:
-                    writer.writeIntArray((int[])val);
-
-                    break;
-
-                case LONG_ARR:
-                    writer.writeLongArray((long[])val);
-
-                    break;
-
-                case FLOAT_ARR:
-                    writer.writeFloatArray((float[])val);
-
-                    break;
-
-                case DOUBLE_ARR:
-                    writer.writeDoubleArray((double[])val);
-
-                    break;
-
-                case CHAR_ARR:
-                    writer.writeCharArray((char[])val);
-
-                    break;
-
-                case BOOLEAN_ARR:
-                    writer.writeBooleanArray((boolean[])val);
-
-                    break;
-
-                case DECIMAL_ARR:
-                    writer.writeDecimalArray((BigDecimal[])val);
-
-                    break;
-
-                case STRING_ARR:
-                    writer.writeStringArray((String[])val);
-
-                    break;
-
-                case UUID_ARR:
-                    writer.writeUuidArray((UUID[])val);
-
-                    break;
-
-                case DATE_ARR:
-                    writer.writeDateArray((Date[])val);
-
-                    break;
-
-                case TIMESTAMP_ARR:
-                    writer.writeTimestampArray((Timestamp[])val);
-
-                    break;
-
-                case TIME_ARR:
-                    writer.writeTimeArray((Time[])val);
-
-                    break;
-
-                case OBJECT_ARR:
-                    writer.writeObjectArray((Object[])val);
-
-                    break;
-
-                case COL:
-                    writer.writeCollection((Collection<?>)val);
-
-                    break;
-
-                case MAP:
-                    writer.writeMap((Map<?, ?>)val);
-
-                    break;
-
-                case BINARY_OBJ:
-                    writer.writeBinaryObject((BinaryObjectImpl)val);
-
-                    break;
-
-                case ENUM:
-                    writer.writeEnum((Enum<?>)val);
-
-                    break;
-
-                case BINARY_ENUM:
-                    writer.writeBinaryEnum((BinaryEnumObjectImpl)val);
-
-                    break;
-
-                case ENUM_ARR:
-                    writer.doWriteEnumArray((Object[])val);
-
-                    break;
-
-                case BINARY:
-                case OBJECT:
-                case PROXY:
-                    writer.writeObject(val);
-
-                    break;
-
-                case CLASS:
-                    writer.writeClass((Class)val);
-
-                    break;
-
-                default:
-                    assert false : "Invalid mode: " + mode;
-            }
-        }
-
-        /** {@inheritDoc} */
-        @Override public void read0(Object obj, BinaryReaderExImpl reader) 
throws BinaryObjectException {
-            Object val = dynamic ? reader.readField(id) : 
readFixedType(reader);
-
-            try {
-                if (val != null || !field.getType().isPrimitive())
-                    field.set(obj, val);
-            }
-            catch (IllegalAccessException e) {
-                throw new BinaryObjectException("Failed to set value for 
field: " + field, e);
-            }
-        }
-
-        /**
-         * Reads fixed type from the given reader with flags validation.
-         *
-         * @param reader Reader to read from.
-         * @return Read value.
-         * @throws BinaryObjectException If failed to read value from the 
stream.
-         */
-        protected Object readFixedType(BinaryReaderExImpl reader) throws 
BinaryObjectException {
-            Object val = null;
-
-            switch (mode) {
-                case BYTE:
-                    val = reader.readByteNullable(id);
-
-                    break;
-
-                case SHORT:
-                    val = reader.readShortNullable(id);
-
-                    break;
-
-                case INT:
-                    val = reader.readIntNullable(id);
-
-                    break;
-
-                case LONG:
-                    val = reader.readLongNullable(id);
-
-                    break;
-
-                case FLOAT:
-                    val = reader.readFloatNullable(id);
-
-                    break;
-
-                case DOUBLE:
-                    val = reader.readDoubleNullable(id);
-
-                    break;
-
-                case CHAR:
-                    val = reader.readCharNullable(id);
-
-                    break;
-
-                case BOOLEAN:
-                    val = reader.readBooleanNullable(id);
-
-                    break;
-
-                case DECIMAL:
-                    val = reader.readDecimal(id);
-
-                    break;
-
-                case STRING:
-                    val = reader.readString(id);
-
-                    break;
-
-                case UUID:
-                    val = reader.readUuid(id);
-
-                    break;
-
-                case DATE:
-                    val = reader.readDate(id);
-
-                    break;
-
-                case TIMESTAMP:
-                    val = reader.readTimestamp(id);
-
-                    break;
-
-                case TIME:
-                    val = reader.readTime(id);
-
-                    break;
-
-                case BYTE_ARR:
-                    val = reader.readByteArray(id);
-
-                    break;
-
-                case SHORT_ARR:
-                    val = reader.readShortArray(id);
-
-                    break;
-
-                case INT_ARR:
-                    val = reader.readIntArray(id);
-
-                    break;
-
-                case LONG_ARR:
-                    val = reader.readLongArray(id);
-
-                    break;
-
-                case FLOAT_ARR:
-                    val = reader.readFloatArray(id);
-
-                    break;
-
-                case DOUBLE_ARR:
-                    val = reader.readDoubleArray(id);
-
-                    break;
-
-                case CHAR_ARR:
-                    val = reader.readCharArray(id);
-
-                    break;
-
-                case BOOLEAN_ARR:
-                    val = reader.readBooleanArray(id);
-
-                    break;
-
-                case DECIMAL_ARR:
-                    val = reader.readDecimalArray(id);
-
-                    break;
-
-                case STRING_ARR:
-                    val = reader.readStringArray(id);
-
-                    break;
-
-                case UUID_ARR:
-                    val = reader.readUuidArray(id);
-
-                    break;
-
-                case DATE_ARR:
-                    val = reader.readDateArray(id);
-
-                    break;
-
-                case TIMESTAMP_ARR:
-                    val = reader.readTimestampArray(id);
-
-                    break;
-
-                case TIME_ARR:
-                    val = reader.readTimeArray(id);
-
-                    break;
-
-                case OBJECT_ARR:
-                    val = reader.readObjectArray(id);
-
-                    break;
-
-                case COL:
-                    val = reader.readCollection(id, null);
-
-                    break;
-
-                case MAP:
-                    val = reader.readMap(id, null);
-
-                    break;
-
-                case BINARY_OBJ:
-                    val = reader.readBinaryObject(id);
-
-                    break;
-
-                case ENUM:
-                    val = reader.readEnum(id, field.getType());
-
-                    break;
-
-                case ENUM_ARR:
-                    val = reader.readEnumArray(id, 
field.getType().getComponentType());
-
-                    break;
-
-                case BINARY_ENUM:
-                    val = reader.readBinaryEnum(id);
-
-                    break;
-
-                case BINARY:
-                case OBJECT:
-                    val = reader.readObject(id);
-
-                    break;
-
-                case CLASS:
-                    val = reader.readClass(id);
-
-                    break;
-
-                default:
-                    assert false : "Invalid mode: " + mode;
-            }
-
-            return val;
-        }
-
-        /**
-         * @param val Val to get write mode for.
-         * @return Write mode.
-         */
-        protected BinaryWriteMode mode(Object val) {
-            return dynamic ?
-                val == null ? BinaryWriteMode.OBJECT : 
BinaryUtils.mode(val.getClass()) :
-                mode;
-        }
-    }
-}
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldDescriptor.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldDescriptor.java
new file mode 100644
index 00000000000..3b0ad342e8a
--- /dev/null
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldDescriptor.java
@@ -0,0 +1,65 @@
+/*
+ * 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.binary;
+
+import java.lang.reflect.Field;
+
+/**
+ * Field descriptor.
+ */
+class BinaryFieldDescriptor {
+    /** Field ID. */
+    final int id;
+
+    /** Field name. */
+    final String name;
+
+    /** Mode. */
+    final BinaryWriteMode mode;
+
+    /** Offset. Used for primitive fields, only. */
+    final long offset;
+
+    /** Target field. */
+    final Field field;
+
+    /** Dynamic accessor flag. */
+    final boolean dynamic;
+
+    /**
+     * Protected constructor.
+     *
+     * @param field Field.
+     * @param id Field ID.
+     * @param mode Mode.
+     * @param offset Offset of the field in the byte array.
+     * @param dynamic If {@code true} then field is not final.
+     */
+    protected BinaryFieldDescriptor(Field field, int id, BinaryWriteMode mode, 
long offset, boolean dynamic) {
+        assert field != null;
+        assert id != 0;
+        assert mode != null;
+
+        this.name = field.getName();
+        this.id = id;
+        this.mode = mode;
+        this.offset = offset;
+        this.field = field;
+        this.dynamic = dynamic;
+    }
+}
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldMetadata.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldMetadata.java
index 3cfe54fb6f1..eeba2477485 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldMetadata.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryFieldMetadata.java
@@ -58,15 +58,6 @@ public class BinaryFieldMetadata implements Externalizable {
         this.fieldId = fieldId;
     }
 
-    /**
-     * Constructor.
-     * @param accessor Field accessor.
-     */
-    public BinaryFieldMetadata(BinaryFieldAccessor accessor) {
-        this.typeId = accessor.mode().typeId();
-        this.fieldId = accessor.id;
-    }
-
     /**
      * @return Field ID in binary schema.
      */
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
index 07e68aef38b..683f413e694 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
@@ -743,7 +743,7 @@ final class BinaryObjectImpl extends BinaryObjectExImpl 
implements Externalizabl
 
     /** {@inheritDoc} */
     @Override BinarySchema createSchema() {
-        return ((BinaryReaderExImpl)reader(null, false)).getOrCreateSchema();
+        return reader(null, false).getOrCreateSchema();
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
index 1d1318f8b02..c2a046c1d08 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
@@ -129,7 +129,7 @@ class BinaryObjectOffheapImpl extends BinaryObjectExImpl 
implements Externalizab
 
     /** {@inheritDoc} */
     @Override BinarySchema createSchema() {
-        return ((BinaryReaderExImpl)reader(null, false)).getOrCreateSchema();
+        return reader(null, false).getOrCreateSchema();
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryReaderEx.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryReaderEx.java
index 4dbbdc94b72..1b1911297e8 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryReaderEx.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryReaderEx.java
@@ -85,4 +85,11 @@ public interface BinaryReaderEx extends BinaryReader, 
BinaryRawReader, BinaryRea
      * @return Offset.
      */
     public boolean findFieldByName(String name);
+
+    /**
+     * Get or create object schema.
+     *
+     * @return Schema.
+     */
+    public BinarySchema getOrCreateSchema();
 }
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinarySchema.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinarySchema.java
index 45f1245b5e9..7b3e7257c46 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinarySchema.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinarySchema.java
@@ -35,7 +35,7 @@ import org.apache.ignite.internal.util.typedef.internal.S;
  * for quick comparisons performed within already fetched L1 cache line.
  * - When there are more fields, we store them inside a hash map.
  */
-class BinarySchema implements Externalizable {
+public class BinarySchema implements Externalizable {
     /** */
     private static final long serialVersionUID = 0L;
 
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
index 6b0a71f81a0..93f691dc121 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
@@ -43,6 +43,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -71,13 +72,13 @@ import org.apache.ignite.binary.BinaryType;
 import org.apache.ignite.binary.Binarylizable;
 import org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
-import org.apache.ignite.internal.binary.streams.BinaryStreams;
 import org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
 import org.apache.ignite.internal.util.CommonUtils;
 import org.apache.ignite.internal.util.GridUnsafe;
 import org.apache.ignite.internal.util.MutableSingletonList;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.A;
 import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.marshaller.Marshallers;
@@ -179,6 +180,20 @@ public class BinaryUtils {
     /** FNV1 hash prime. */
     private static final int FNV1_PRIME = 0x01000193;
 
+    /** */
+    public static final BinariesFactory binariesFactory;
+
+    static {
+        Iterator<BinariesFactory> factories = 
CommonUtils.loadService(BinariesFactory.class).iterator();
+
+        A.ensure(
+            factories.hasNext(),
+            "Implementation for " + BinariesFactory.class.getSimpleName() + " 
service not found. Please add ignite-binary-impl to classpath"
+        );
+
+        binariesFactory = factories.next();
+    }
+
     /*
      * Static class initializer.
      */
@@ -1566,7 +1581,7 @@ public class BinaryUtils {
      * @param in Input stream.
      * @return Plain type.
      */
-    private static EnumType doReadEnumType(BinaryInputStream in) {
+    static EnumType doReadEnumType(BinaryInputStream in) {
         int typeId = in.readInt();
 
         if (typeId != GridBinaryMarshaller.UNREGISTERED_TYPE_ID)
@@ -1653,17 +1668,6 @@ public class BinaryUtils {
         return cls;
     }
 
-    /**
-     * Read binary enum.
-     *
-     * @param in Input stream.
-     * @param ctx Binary context.
-     * @return Enum.
-     */
-    static BinaryEnumObjectImpl doReadBinaryEnum(BinaryInputStream in, 
BinaryContext ctx) {
-        return doReadBinaryEnum(in, ctx, doReadEnumType(in));
-    }
-
     /**
      * Read binary enum.
      *
@@ -1672,7 +1676,7 @@ public class BinaryUtils {
      * @param type Plain type.
      * @return Enum.
      */
-    private static BinaryEnumObjectImpl doReadBinaryEnum(BinaryInputStream in, 
BinaryContext ctx,
+    static BinaryEnumObjectImpl doReadBinaryEnum(BinaryInputStream in, 
BinaryContext ctx,
         EnumType type) {
         return new BinaryEnumObjectImpl(ctx, type.typeId, type.clsName, 
in.readInt());
     }
@@ -2846,7 +2850,7 @@ public class BinaryUtils {
      * @param forUnmarshal {@code True} if reader is needed to unmarshal 
object.
      */
     public static BinaryReaderEx reader(BinaryContext ctx, BinaryInputStream 
in, ClassLoader ldr, boolean forUnmarshal) {
-        return new BinaryReaderExImpl(ctx, in, ldr, forUnmarshal);
+        return binariesFactory.reader(ctx, in, ldr, forUnmarshal);
     }
 
     /**
@@ -2880,7 +2884,7 @@ public class BinaryUtils {
                                         ClassLoader ldr,
                                         @Nullable BinaryReaderHandles hnds,
                                         boolean forUnmarshal) {
-        return new BinaryReaderExImpl(ctx, in, ldr, hnds, forUnmarshal);
+        return binariesFactory.reader(ctx, in, ldr, hnds, forUnmarshal);
     }
 
     /**
@@ -2916,7 +2920,7 @@ public class BinaryUtils {
                                         @Nullable BinaryReaderHandles hnds,
                                         boolean skipHdrCheck,
                                         boolean forUnmarshal) {
-        return new BinaryReaderExImpl(ctx, in, ldr, hnds, skipHdrCheck, 
forUnmarshal);
+        return binariesFactory.reader(ctx, in, ldr, hnds, skipHdrCheck, 
forUnmarshal);
     }
 
     /**
@@ -2926,16 +2930,7 @@ public class BinaryUtils {
      * @return Writer instance.
      */
     public static BinaryWriterEx writer(BinaryContext ctx, boolean 
failIfUnregistered, int typeId) {
-        BinaryThreadLocalContext locCtx = BinaryThreadLocalContext.get();
-
-        return new BinaryWriterExImpl(
-            ctx,
-            BinaryStreams.outputStream((int)CommonUtils.KB, locCtx.chunk()),
-            locCtx.schemaHolder(),
-            null,
-            failIfUnregistered,
-            typeId
-        );
+        return binariesFactory.writer(ctx, failIfUnregistered, typeId);
     }
 
     /**
@@ -2944,14 +2939,7 @@ public class BinaryUtils {
      * @return Writer instance.
      */
     public static BinaryWriterEx writer(BinaryContext ctx, BinaryOutputStream 
out) {
-        return new BinaryWriterExImpl(
-            ctx,
-            out,
-            BinaryThreadLocalContext.get().schemaHolder(),
-            null,
-            false,
-            GridBinaryMarshaller.UNREGISTERED_TYPE_ID
-        );
+        return binariesFactory.writer(ctx, out);
     }
 
     /**
@@ -2960,7 +2948,7 @@ public class BinaryUtils {
      * @return Writer instance.
      */
     public static BinaryWriterEx writer(BinaryContext ctx, BinaryOutputStream 
out, BinaryWriterSchemaHolder schema) {
-        return new BinaryWriterExImpl(ctx, out, schema, null, false, 
GridBinaryMarshaller.UNREGISTERED_TYPE_ID);
+        return binariesFactory.writer(ctx, out, schema);
     }
 
     /** @return Instance of caching handler. */
@@ -3105,7 +3093,7 @@ public class BinaryUtils {
      * @param order Order.
      */
     public static int fieldId(BinaryReaderEx reader, int order) {
-        return ((BinaryReaderExImpl)reader).getOrCreateSchema().fieldId(order);
+        return reader.getOrCreateSchema().fieldId(order);
     }
 
     /**
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryWriterEx.java
 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryWriterEx.java
index 3327753c4b4..a382361432b 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryWriterEx.java
+++ 
b/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryWriterEx.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.binary;
 
 import java.io.InputStream;
 import java.io.ObjectOutput;
+import java.lang.reflect.Proxy;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryRawWriter;
 import org.apache.ignite.binary.BinaryWriter;
@@ -131,6 +132,11 @@ public interface BinaryWriterEx extends BinaryWriter, 
BinaryRawWriter, ObjectOut
      */
     public int schemaId();
 
+    /**
+     * @param schemaId Schema ID.
+     */
+    public void schemaId(int schemaId);
+
     /**
      * @return Binary context.
      */
@@ -197,4 +203,52 @@ public interface BinaryWriterEx extends BinaryWriter, 
BinaryRawWriter, ObjectOut
      * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
      */
     public void writeBinaryObject(@Nullable BinaryObjectEx po) throws 
BinaryObjectException;
+
+    /**
+     * Write field.
+     *
+     * @param obj Object.
+     * @param fld Field.
+     * @throws BinaryObjectException If failed.
+     */
+    public void writeField(Object obj, BinaryFieldDescriptor fld) throws 
BinaryObjectException;
+
+    /**
+     * @return Current writer's schema.
+     */
+    public BinarySchema currentSchema();
+
+    /**
+     * Attempts to write the object as a handle.
+     *
+     * @param obj Object to write.
+     * @return {@code true} if the object has been written as a handle.
+     */
+    public boolean tryWriteAsHandle(Object obj);
+
+    /**
+     * @param val Array wrapper.
+     * @throws BinaryObjectException In case of error.
+     */
+    public void writeBinaryArray(BinaryArray val);
+
+    /**
+     * @param val Array.
+     */
+    public void doWriteEnumArray(Object[] val);
+
+    /**
+     * @param val Value.
+     */
+    public void writeBinaryEnum(BinaryObjectEx val);
+
+    /**
+     * @param val Class.
+     */
+    public void writeClass(Class val);
+
+    /**
+     * @param proxy Proxy.
+     */
+    public void writeProxy(Proxy proxy, Class<?>[] intfs);
 }
diff --git 
a/modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinariesFactoryImpl.java
 
b/modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinariesFactoryImpl.java
new file mode 100644
index 00000000000..94021fb5ca6
--- /dev/null
+++ 
b/modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinariesFactoryImpl.java
@@ -0,0 +1,145 @@
+/*
+ * 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.binary;
+
+import java.lang.reflect.Field;
+import org.apache.ignite.internal.binary.streams.BinaryInputStream;
+import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
+import org.apache.ignite.internal.binary.streams.BinaryStreams;
+import org.apache.ignite.internal.util.CommonUtils;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Binary objects factory implementation.
+ * @see CommonUtils#loadService(Class)
+ */
+public class BinariesFactoryImpl implements BinariesFactory {
+    /** {@inheritDoc} */
+    @Override public BinaryReaderEx reader(BinaryContext ctx, 
BinaryInputStream in, ClassLoader ldr, boolean forUnmarshal) {
+        return new BinaryReaderExImpl(ctx, in, ldr, forUnmarshal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryReaderEx reader(
+        BinaryContext ctx,
+        BinaryInputStream in,
+        ClassLoader ldr,
+        @Nullable BinaryReaderHandles hnds,
+        boolean forUnmarshal
+    ) {
+        return new BinaryReaderExImpl(ctx, in, ldr, hnds, forUnmarshal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryReaderEx reader(
+        BinaryContext ctx,
+        BinaryInputStream in,
+        ClassLoader ldr,
+        @Nullable BinaryReaderHandles hnds,
+        boolean skipHdrCheck,
+        boolean forUnmarshal
+    ) {
+        return new BinaryReaderExImpl(ctx, in, ldr, hnds, skipHdrCheck, 
forUnmarshal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryWriterEx writer(BinaryContext ctx, boolean 
failIfUnregistered, int typeId) {
+        BinaryThreadLocalContext locCtx = BinaryThreadLocalContext.get();
+
+        return new BinaryWriterExImpl(
+            ctx,
+            BinaryStreams.outputStream((int)CommonUtils.KB, locCtx.chunk()),
+            locCtx.schemaHolder(),
+            null,
+            failIfUnregistered,
+            typeId
+        );
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryWriterEx writer(BinaryContext ctx, 
BinaryOutputStream out) {
+        return new BinaryWriterExImpl(
+            ctx,
+            out,
+            BinaryThreadLocalContext.get().schemaHolder(),
+            null,
+            false,
+            GridBinaryMarshaller.UNREGISTERED_TYPE_ID
+        );
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryWriterEx writer(BinaryContext ctx, 
BinaryOutputStream out, BinaryWriterSchemaHolder schema) {
+        return new BinaryWriterExImpl(ctx, out, schema, null, false, 
GridBinaryMarshaller.UNREGISTERED_TYPE_ID);
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryFieldDescriptor create(Field field, int id) {
+        BinaryWriteMode mode = BinaryUtils.mode(field.getType());
+
+        switch (mode) {
+            case P_BYTE:
+            case P_BOOLEAN:
+            case P_SHORT:
+            case P_CHAR:
+            case P_INT:
+            case P_LONG:
+            case P_FLOAT:
+            case P_DOUBLE:
+                return new BinaryFieldDescriptor(field, id, mode, 
GridUnsafe.objectFieldOffset(field), false);
+
+            case BYTE:
+            case BOOLEAN:
+            case SHORT:
+            case CHAR:
+            case INT:
+            case LONG:
+            case FLOAT:
+            case DOUBLE:
+            case DECIMAL:
+            case STRING:
+            case UUID:
+            case DATE:
+            case TIMESTAMP:
+            case TIME:
+            case BYTE_ARR:
+            case SHORT_ARR:
+            case INT_ARR:
+            case LONG_ARR:
+            case FLOAT_ARR:
+            case DOUBLE_ARR:
+            case CHAR_ARR:
+            case BOOLEAN_ARR:
+            case DECIMAL_ARR:
+            case STRING_ARR:
+            case UUID_ARR:
+            case DATE_ARR:
+            case TIMESTAMP_ARR:
+            case TIME_ARR:
+            case ENUM_ARR:
+            case OBJECT_ARR:
+            case BINARY_OBJ:
+            case BINARY:
+                return new BinaryFieldDescriptor(field, id, mode, -1L, false);
+
+            default:
+                return new BinaryFieldDescriptor(field, id, mode, -1L, 
!CommonUtils.isFinal(field.getType()));
+        }
+    }
+}
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
 
b/modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
similarity index 87%
rename from 
modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
rename to 
modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
index 26592843819..4bb061ff7f3 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
+++ 
b/modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.binary;
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
 import java.sql.Time;
 import java.sql.Timestamp;
@@ -34,8 +35,11 @@ import org.apache.ignite.binary.BinaryMapFactory;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.binary.Binarylizable;
 import org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.util.CommonUtils;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.apache.ignite.marshaller.Marshallers;
@@ -1422,8 +1426,8 @@ class BinaryReaderExImpl implements BinaryReaderEx {
      * @return Binary Enum
      * @throws BinaryObjectException If failed.
      */
-    @Nullable BinaryEnumObjectImpl readBinaryEnum(int fieldId) throws 
BinaryObjectException {
-        return findFieldById(fieldId) ? BinaryUtils.doReadBinaryEnum(in, ctx) 
: null;
+    @Nullable BinaryObjectEx readBinaryEnum(int fieldId) throws 
BinaryObjectException {
+        return findFieldById(fieldId) ? doReadBinaryEnum(in, ctx) : null;
     }
 
     /**
@@ -1753,7 +1757,7 @@ class BinaryReaderExImpl implements BinaryReaderEx {
                 if (desc == null)
                     throw new BinaryInvalidTypeException("Unknown type ID: " + 
typeId);
 
-                obj = desc.read(this);
+                obj = read(desc);
 
                 streamPosition(footerStart + footerLen);
 
@@ -1933,7 +1937,7 @@ class BinaryReaderExImpl implements BinaryReaderEx {
                 break;
 
             case BINARY_ENUM:
-                obj = BinaryUtils.doReadBinaryEnum(in, ctx);
+                obj = doReadBinaryEnum(in, ctx);
 
                 break;
 
@@ -1981,12 +1985,8 @@ class BinaryReaderExImpl implements BinaryReaderEx {
         return mapper.fieldId(typeId, name);
     }
 
-    /**
-     * Get or create object schema.
-     *
-     * @return Schema.
-     */
-    BinarySchema getOrCreateSchema() {
+    /** {@inheritDoc} */
+    @Override public BinarySchema getOrCreateSchema() {
         BinarySchema schema = ctx.schemaRegistry(typeId).schema(schemaId);
 
         if (schema == null) {
@@ -2358,6 +2358,397 @@ class BinaryReaderExImpl implements BinaryReaderEx {
         return ctx;
     }
 
+    /**
+     * @param desc Class descriptor.
+     * @return Object.
+     * @throws BinaryObjectException If failed.
+     */
+    private Object read(BinaryClassDescriptor desc) throws 
BinaryObjectException {
+        try {
+            assert desc.mode != BinaryWriteMode.OPTIMIZED : 
"OptimizedMarshaller should not be used here: " + desc.cls.getName();
+
+            Object res;
+
+            switch (desc.mode) {
+                case BINARY:
+                    res = desc.newInstance();
+
+                    setHandle(res);
+
+                    if (desc.serializer != null)
+                        desc.serializer.readBinary(res, this);
+                    else
+                        ((Binarylizable)res).readBinary(this);
+
+                    break;
+
+                case OBJECT:
+                    res = desc.newInstance();
+
+                    setHandle(res);
+
+                    for (BinaryFieldDescriptor info : desc.fields)
+                        readField(res, info);
+
+                    break;
+
+                default:
+                    assert false : "Invalid mode: " + desc.mode;
+
+                    return null;
+            }
+
+            if (desc.readResolveMtd != null) {
+                try {
+                    res = desc.readResolveMtd.invoke(res);
+
+                    setHandle(res);
+                }
+                catch (IllegalAccessException e) {
+                    throw new RuntimeException(e);
+                }
+                catch (InvocationTargetException e) {
+                    if (e.getTargetException() instanceof 
BinaryObjectException)
+                        throw (BinaryObjectException)e.getTargetException();
+
+                    throw new BinaryObjectException("Failed to execute 
readResolve() method on " + res, e);
+                }
+            }
+
+            return res;
+        }
+        catch (Exception e) {
+            String msg;
+
+            if (S.includeSensitive() && !F.isEmpty(desc.typeName))
+                msg = "Failed to deserialize object [typeName=" + 
desc.typeName + ']';
+            else
+                msg = "Failed to deserialize object [typeId=" + typeId + ']';
+
+            CommonUtils.error(ctx.log(), msg, e);
+
+            throw new BinaryObjectException(msg, e);
+        }
+    }
+
+    /**
+     * Read field.
+     *
+     * @param obj Object.
+     * @param fld Field info.
+     * @throws BinaryObjectException If failed.
+     */
+    private void readField(Object obj, BinaryFieldDescriptor fld) {
+        try {
+            switch (fld.mode) {
+                case P_BYTE:
+                    GridUnsafe.putByteField(obj, fld.offset, readByte(fld.id));
+
+                    break;
+
+                case P_BOOLEAN:
+                    GridUnsafe.putBooleanField(obj, fld.offset, 
readBoolean(fld.id));
+
+                    break;
+
+                case P_SHORT:
+                    GridUnsafe.putShortField(obj, fld.offset, 
readShort(fld.id));
+
+                    break;
+
+                case P_CHAR:
+                    GridUnsafe.putCharField(obj, fld.offset, readChar(fld.id));
+
+                    break;
+
+                case P_INT:
+                    GridUnsafe.putIntField(obj, fld.offset, readInt(fld.id));
+
+                    break;
+
+                case P_LONG:
+                    GridUnsafe.putLongField(obj, fld.offset, readLong(fld.id));
+
+                    break;
+
+                case P_FLOAT:
+                    GridUnsafe.putFloatField(obj, fld.offset, 
readFloat(fld.id));
+
+                    break;
+
+                case P_DOUBLE:
+                    GridUnsafe.putDoubleField(obj, fld.offset, 
readDouble(fld.id));
+
+                    break;
+
+                case BYTE:
+                case BOOLEAN:
+                case SHORT:
+                case CHAR:
+                case INT:
+                case LONG:
+                case FLOAT:
+                case DOUBLE:
+                case DECIMAL:
+                case STRING:
+                case UUID:
+                case DATE:
+                case TIMESTAMP:
+                case TIME:
+                case BYTE_ARR:
+                case SHORT_ARR:
+                case INT_ARR:
+                case LONG_ARR:
+                case FLOAT_ARR:
+                case DOUBLE_ARR:
+                case CHAR_ARR:
+                case BOOLEAN_ARR:
+                case DECIMAL_ARR:
+                case STRING_ARR:
+                case UUID_ARR:
+                case DATE_ARR:
+                case TIMESTAMP_ARR:
+                case TIME_ARR:
+                case ENUM_ARR:
+                case OBJECT_ARR:
+                case BINARY_OBJ:
+                case BINARY:
+                default:
+
+                    Object val = fld.dynamic ? readField(fld.id) : 
readFixedType(fld);
+
+                    try {
+                        if (val != null || !fld.field.getType().isPrimitive())
+                            fld.field.set(obj, val);
+                    }
+                    catch (IllegalAccessException e) {
+                        throw new BinaryObjectException("Failed to set value 
for field: " + fld.field, e);
+                    }
+            }
+        }
+        catch (Exception ex) {
+            if (S.includeSensitive() && !F.isEmpty(fld.name))
+                throw new BinaryObjectException("Failed to read field [name=" 
+ fld.name + ']', ex);
+            else
+                throw new BinaryObjectException("Failed to read field [id=" + 
fld.id + ']', ex);
+        }
+    }
+
+    /**
+     * Reads fixed type from the given reader with flags validation.
+     *
+     * @param fld Binary field.
+     * @return Read value.
+     * @throws BinaryObjectException If failed to read value from the stream.
+     */
+    protected Object readFixedType(BinaryFieldDescriptor fld) throws 
BinaryObjectException {
+        Object val = null;
+
+        switch (fld.mode) {
+            case BYTE:
+                val = readByteNullable(fld.id);
+
+                break;
+
+            case SHORT:
+                val = readShortNullable(fld.id);
+
+                break;
+
+            case INT:
+                val = readIntNullable(fld.id);
+
+                break;
+
+            case LONG:
+                val = readLongNullable(fld.id);
+
+                break;
+
+            case FLOAT:
+                val = readFloatNullable(fld.id);
+
+                break;
+
+            case DOUBLE:
+                val = readDoubleNullable(fld.id);
+
+                break;
+
+            case CHAR:
+                val = readCharNullable(fld.id);
+
+                break;
+
+            case BOOLEAN:
+                val = readBooleanNullable(fld.id);
+
+                break;
+
+            case DECIMAL:
+                val = readDecimal(fld.id);
+
+                break;
+
+            case STRING:
+                val = readString(fld.id);
+
+                break;
+
+            case UUID:
+                val = readUuid(fld.id);
+
+                break;
+
+            case DATE:
+                val = readDate(fld.id);
+
+                break;
+
+            case TIMESTAMP:
+                val = readTimestamp(fld.id);
+
+                break;
+
+            case TIME:
+                val = readTime(fld.id);
+
+                break;
+
+            case BYTE_ARR:
+                val = readByteArray(fld.id);
+
+                break;
+
+            case SHORT_ARR:
+                val = readShortArray(fld.id);
+
+                break;
+
+            case INT_ARR:
+                val = readIntArray(fld.id);
+
+                break;
+
+            case LONG_ARR:
+                val = readLongArray(fld.id);
+
+                break;
+
+            case FLOAT_ARR:
+                val = readFloatArray(fld.id);
+
+                break;
+
+            case DOUBLE_ARR:
+                val = readDoubleArray(fld.id);
+
+                break;
+
+            case CHAR_ARR:
+                val = readCharArray(fld.id);
+
+                break;
+
+            case BOOLEAN_ARR:
+                val = readBooleanArray(fld.id);
+
+                break;
+
+            case DECIMAL_ARR:
+                val = readDecimalArray(fld.id);
+
+                break;
+
+            case STRING_ARR:
+                val = readStringArray(fld.id);
+
+                break;
+
+            case UUID_ARR:
+                val = readUuidArray(fld.id);
+
+                break;
+
+            case DATE_ARR:
+                val = readDateArray(fld.id);
+
+                break;
+
+            case TIMESTAMP_ARR:
+                val = readTimestampArray(fld.id);
+
+                break;
+
+            case TIME_ARR:
+                val = readTimeArray(fld.id);
+
+                break;
+
+            case OBJECT_ARR:
+                val = readObjectArray(fld.id);
+
+                break;
+
+            case COL:
+                val = readCollection(fld.id, null);
+
+                break;
+
+            case MAP:
+                val = readMap(fld.id, null);
+
+                break;
+
+            case BINARY_OBJ:
+                val = readBinaryObject(fld.id);
+
+                break;
+
+            case ENUM:
+                val = readEnum(fld.id, fld.field.getType());
+
+                break;
+
+            case ENUM_ARR:
+                val = readEnumArray(fld.id, 
fld.field.getType().getComponentType());
+
+                break;
+
+            case BINARY_ENUM:
+                val = readBinaryEnum(fld.id);
+
+                break;
+
+            case BINARY:
+            case OBJECT:
+                val = readObject(fld.id);
+
+                break;
+
+            case CLASS:
+                val = readClass(fld.id);
+
+                break;
+
+            default:
+                assert false : "Invalid mode: " + fld.mode;
+        }
+
+        return val;
+    }
+
+    /**
+     * Read binary enum.
+     *
+     * @param in Input stream.
+     * @param ctx Binary context.
+     * @return Enum.
+     */
+    private static BinaryObjectEx doReadBinaryEnum(BinaryInputStream in, 
BinaryContext ctx) {
+        return BinaryUtils.doReadBinaryEnum(in, ctx, 
BinaryUtils.doReadEnumType(in));
+    }
+
     /**
      * Flag.
      */
diff --git 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
 
b/modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
similarity index 84%
rename from 
modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
rename to 
modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
index 2bf503b0435..033be969abc 100644
--- 
a/modules/binary/api/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
+++ 
b/modules/binary/impl/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
@@ -35,6 +35,7 @@ import org.apache.ignite.binary.BinaryRawWriter;
 import org.apache.ignite.internal.UnregisteredClassException;
 import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
 import org.apache.ignite.internal.util.CommonUtils;
+import org.apache.ignite.internal.util.GridUnsafe;
 import org.apache.ignite.internal.util.typedef.internal.A;
 import org.apache.ignite.marshaller.Marshallers;
 import org.jetbrains.annotations.Nullable;
@@ -339,11 +340,8 @@ class BinaryWriterExImpl implements BinaryWriterEx {
         out.write(val, off, len);
     }
 
-    /**
-     * @param val Array wrapper.
-     * @throws BinaryObjectException In case of error.
-     */
-    void writeBinaryArray(BinaryArray val) throws BinaryObjectException {
+    /** {@inheritDoc} */
+    @Override public void writeBinaryArray(BinaryArray val) throws 
BinaryObjectException {
         if (val.array() == null)
             out.writeByte(GridBinaryMarshaller.NULL);
         else {
@@ -367,11 +365,9 @@ class BinaryWriterExImpl implements BinaryWriterEx {
         }
     }
 
-    /**
-     * @param val Value.
-     */
-    void writeBinaryEnum(BinaryEnumObjectImpl val) {
-        assert val != null;
+    /** {@inheritDoc} */
+    @Override public void writeBinaryEnum(BinaryObjectEx val) {
+        assert val instanceof BinaryEnumObjectImpl;
 
         int typeId = val.typeId();
 
@@ -394,10 +390,8 @@ class BinaryWriterExImpl implements BinaryWriterEx {
         }
     }
 
-    /**
-     * @param proxy Proxy.
-     */
-    public void writeProxy(Proxy proxy, Class<?>[] intfs) {
+    /** {@inheritDoc} */
+    @Override public void writeProxy(Proxy proxy, Class<?>[] intfs) {
         if (proxy == null)
             out.writeByte(GridBinaryMarshaller.NULL);
         else {
@@ -444,10 +438,8 @@ class BinaryWriterExImpl implements BinaryWriterEx {
             writeByteFieldPrimitive(val);
     }
 
-    /**
-     * @param val Class.
-     */
-    void writeClass(@Nullable Class val) {
+    /** {@inheritDoc} */
+    @Override public void writeClass(@Nullable Class val) {
         if (val == null)
             out.writeByte(GridBinaryMarshaller.NULL);
         else {
@@ -1297,10 +1289,8 @@ class BinaryWriterExImpl implements BinaryWriterEx {
         doWriteEnumArray(val);
     }
 
-    /**
-     * @param val Array.
-     */
-    void doWriteEnumArray(@Nullable Object[] val) {
+    /** {@inheritDoc} */
+    @Override public void doWriteEnumArray(@Nullable Object[] val) {
         assert val == null || val.getClass().getComponentType().isEnum();
 
         if (val == null)
@@ -1500,10 +1490,8 @@ class BinaryWriterExImpl implements BinaryWriterEx {
         return written;
     }
 
-    /**
-     * @param schemaId Schema ID.
-     */
-    public void schemaId(int schemaId) {
+    /** {@inheritDoc} */
+    @Override public void schemaId(int schemaId) {
         this.schemaId = schemaId;
     }
 
@@ -1512,10 +1500,8 @@ class BinaryWriterExImpl implements BinaryWriterEx {
         return schemaId;
     }
 
-    /**
-     * @return Current writer's schema.
-     */
-    BinarySchema currentSchema() {
+    /** {@inheritDoc} */
+    @Override public BinarySchema currentSchema() {
         BinarySchema.Builder builder = BinarySchema.Builder.newBuilder();
 
         if (schema != null)
@@ -1537,13 +1523,8 @@ class BinaryWriterExImpl implements BinaryWriterEx {
         return handles;
     }
 
-    /**
-     * Attempts to write the object as a handle.
-     *
-     * @param obj Object to write.
-     * @return {@code true} if the object has been written as a handle.
-     */
-    boolean tryWriteAsHandle(Object obj) {
+    /** {@inheritDoc} */
+    @Override public boolean tryWriteAsHandle(Object obj) {
         assert obj != null;
 
         int pos = out.position();
@@ -1586,4 +1567,298 @@ class BinaryWriterExImpl implements BinaryWriterEx {
         if (clearHandler)
             this.handles = null;
     }
+
+    /** {@inheritDoc} */
+    @Override public void writeField(Object obj, BinaryFieldDescriptor fld) 
throws BinaryObjectException {
+        writeFieldIdNoSchemaUpdate(fld.id);
+
+        switch (fld.mode) {
+            case P_BYTE:
+                writeByteFieldPrimitive(GridUnsafe.getByteField(obj, 
fld.offset));
+
+                break;
+
+            case P_BOOLEAN:
+                writeBooleanFieldPrimitive(GridUnsafe.getBooleanField(obj, 
fld.offset));
+
+                break;
+
+            case P_SHORT:
+                writeShortFieldPrimitive(GridUnsafe.getShortField(obj, 
fld.offset));
+
+                break;
+
+            case P_CHAR:
+                writeCharFieldPrimitive(GridUnsafe.getCharField(obj, 
fld.offset));
+
+                break;
+
+            case P_INT:
+                writeIntFieldPrimitive(GridUnsafe.getIntField(obj, 
fld.offset));
+
+                break;
+
+            case P_LONG:
+                writeLongFieldPrimitive(GridUnsafe.getLongField(obj, 
fld.offset));
+
+                break;
+
+            case P_FLOAT:
+                writeFloatFieldPrimitive(GridUnsafe.getFloatField(obj, 
fld.offset));
+
+                break;
+
+            case P_DOUBLE:
+                writeDoubleFieldPrimitive(GridUnsafe.getDoubleField(obj, 
fld.offset));
+
+                break;
+
+            case BYTE:
+            case BOOLEAN:
+            case SHORT:
+            case CHAR:
+            case INT:
+            case LONG:
+            case FLOAT:
+            case DOUBLE:
+            case DECIMAL:
+            case STRING:
+            case UUID:
+            case DATE:
+            case TIMESTAMP:
+            case TIME:
+            case BYTE_ARR:
+            case SHORT_ARR:
+            case INT_ARR:
+            case LONG_ARR:
+            case FLOAT_ARR:
+            case DOUBLE_ARR:
+            case CHAR_ARR:
+            case BOOLEAN_ARR:
+            case DECIMAL_ARR:
+            case STRING_ARR:
+            case UUID_ARR:
+            case DATE_ARR:
+            case TIMESTAMP_ARR:
+            case TIME_ARR:
+            case ENUM_ARR:
+            case OBJECT_ARR:
+            case BINARY_OBJ:
+            case BINARY:
+            default:
+                assert obj != null;
+
+                Object val;
+
+                try {
+                    val = fld.field.get(obj);
+                }
+                catch (IllegalAccessException e) {
+                    throw new BinaryObjectException("Failed to get value for 
field: " + fld.field, e);
+                }
+
+                switch (mode(fld, val)) {
+                    case BYTE:
+                        writeByteField((Byte)val);
+
+                        break;
+
+                    case SHORT:
+                        writeShortField((Short)val);
+
+                        break;
+
+                    case INT:
+                        writeIntField((Integer)val);
+
+                        break;
+
+                    case LONG:
+                        writeLongField((Long)val);
+
+                        break;
+
+                    case FLOAT:
+                        writeFloatField((Float)val);
+
+                        break;
+
+                    case DOUBLE:
+                        writeDoubleField((Double)val);
+
+                        break;
+
+                    case CHAR:
+                        writeCharField((Character)val);
+
+                        break;
+
+                    case BOOLEAN:
+                        writeBooleanField((Boolean)val);
+
+                        break;
+
+                    case DECIMAL:
+                        writeDecimal((BigDecimal)val);
+
+                        break;
+
+                    case STRING:
+                        writeString((String)val);
+
+                        break;
+
+                    case UUID:
+                        writeUuid((UUID)val);
+
+                        break;
+
+                    case DATE:
+                        writeDate((Date)val);
+
+                        break;
+
+                    case TIMESTAMP:
+                        writeTimestamp((Timestamp)val);
+
+                        break;
+
+                    case TIME:
+                        writeTime((Time)val);
+
+                        break;
+
+                    case BYTE_ARR:
+                        writeByteArray((byte[])val);
+
+                        break;
+
+                    case SHORT_ARR:
+                        writeShortArray((short[])val);
+
+                        break;
+
+                    case INT_ARR:
+                        writeIntArray((int[])val);
+
+                        break;
+
+                    case LONG_ARR:
+                        writeLongArray((long[])val);
+
+                        break;
+
+                    case FLOAT_ARR:
+                        writeFloatArray((float[])val);
+
+                        break;
+
+                    case DOUBLE_ARR:
+                        writeDoubleArray((double[])val);
+
+                        break;
+
+                    case CHAR_ARR:
+                        writeCharArray((char[])val);
+
+                        break;
+
+                    case BOOLEAN_ARR:
+                        writeBooleanArray((boolean[])val);
+
+                        break;
+
+                    case DECIMAL_ARR:
+                        writeDecimalArray((BigDecimal[])val);
+
+                        break;
+
+                    case STRING_ARR:
+                        writeStringArray((String[])val);
+
+                        break;
+
+                    case UUID_ARR:
+                        writeUuidArray((UUID[])val);
+
+                        break;
+
+                    case DATE_ARR:
+                        writeDateArray((Date[])val);
+
+                        break;
+
+                    case TIMESTAMP_ARR:
+                        writeTimestampArray((Timestamp[])val);
+
+                        break;
+
+                    case TIME_ARR:
+                        writeTimeArray((Time[])val);
+
+                        break;
+
+                    case OBJECT_ARR:
+                        writeObjectArray((Object[])val);
+
+                        break;
+
+                    case COL:
+                        writeCollection((Collection<?>)val);
+
+                        break;
+
+                    case MAP:
+                        writeMap((Map<?, ?>)val);
+
+                        break;
+
+                    case BINARY_OBJ:
+                        writeBinaryObject((BinaryObjectImpl)val);
+
+                        break;
+
+                    case ENUM:
+                        writeEnum((Enum<?>)val);
+
+                        break;
+
+                    case BINARY_ENUM:
+                        writeBinaryEnum((BinaryObjectEx)val);
+
+                        break;
+
+                    case ENUM_ARR:
+                        doWriteEnumArray((Object[])val);
+
+                        break;
+
+                    case BINARY:
+                    case OBJECT:
+                    case PROXY:
+                        writeObject(val);
+
+                        break;
+
+                    case CLASS:
+                        writeClass((Class)val);
+
+                        break;
+
+                    default:
+                        assert false : "Invalid mode: " + fld.mode;
+                }
+        }
+    }
+
+    /**
+     * @param fld Field.
+     * @param val Val to get write mode for.
+     * @return Write mode.
+     */
+    protected BinaryWriteMode mode(BinaryFieldDescriptor fld, Object val) {
+        return fld.dynamic ?
+            val == null ? BinaryWriteMode.OBJECT : 
BinaryUtils.mode(val.getClass()) :
+            fld.mode;
+    }
 }
diff --git 
a/modules/binary/impl/src/main/resources/META-INF/services/org.apache.ignite.internal.binary.BinariesFactory
 
b/modules/binary/impl/src/main/resources/META-INF/services/org.apache.ignite.internal.binary.BinariesFactory
new file mode 100644
index 00000000000..b6a426eade4
--- /dev/null
+++ 
b/modules/binary/impl/src/main/resources/META-INF/services/org.apache.ignite.internal.binary.BinariesFactory
@@ -0,0 +1 @@
+org.apache.ignite.internal.binary.BinariesFactoryImpl
\ No newline at end of file


Reply via email to