You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/12/11 10:58:32 UTC

[3/3] ignite git commit: Merge branch 'ignite-2064-4' into ignite-1.5

Merge branch 'ignite-2064-4' into ignite-1.5

2

(cherry picked from commit 599d2edc6c4f3ce60654a53bb431d36db982bc87)


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0ac39c97
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0ac39c97
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0ac39c97

Branch: refs/heads/ignite-1.5
Commit: 0ac39c976116b655304699d2477f207802cb5f8e
Parents: 1dbf20e 599d2ed
Author: Anton Vinogradov <av...@apache.org>
Authored: Fri Dec 11 12:54:50 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Fri Dec 11 12:54:50 2015 +0300

----------------------------------------------------------------------
 .../org/apache/ignite/internal/binary/BinaryObjectImpl.java   | 1 -
 .../ignite/internal/binary/BinaryObjectOffheapImpl.java       | 6 ++++--
 .../internal/binary/builder/BinaryObjectBuilderImpl.java      | 3 +--
 .../ignite/internal/binary/builder/PortableBuilderEnum.java   | 3 +--
 .../ignite/internal/binary/builder/PortableBuilderReader.java | 5 +++--
 .../internal/binary/builder/PortableEnumArrayLazyValue.java   | 3 +--
 .../internal/binary/builder/PortableObjectArrayLazyValue.java | 3 +--
 .../internal/processors/platform/PlatformContextImpl.java     | 7 +++++--
 .../context/IgniteCacheAbstractExecutionContextTest.java      | 3 ---
 9 files changed, 16 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
index a23330e,0000000..18adbc1
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
@@@ -1,570 -1,0 +1,569 @@@
 +/*
 + * 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.io.Externalizable;
 +import java.io.IOException;
 +import java.io.ObjectInput;
 +import java.io.ObjectOutput;
 +import java.math.BigDecimal;
 +import java.math.BigInteger;
 +import java.nio.ByteBuffer;
 +import java.sql.Timestamp;
 +import java.util.Date;
 +import java.util.UUID;
 +import org.apache.ignite.IgniteCheckedException;
 +import org.apache.ignite.binary.BinaryObject;
 +import org.apache.ignite.binary.BinaryObjectException;
 +import org.apache.ignite.binary.BinaryType;
 +import org.apache.ignite.internal.GridDirectTransient;
 +import org.apache.ignite.internal.IgniteCodeGeneratingFail;
 +import org.apache.ignite.internal.binary.streams.PortableHeapInputStream;
 +import org.apache.ignite.internal.processors.cache.CacheObject;
 +import org.apache.ignite.internal.processors.cache.CacheObjectContext;
 +import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 +import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
 +import org.apache.ignite.internal.util.typedef.internal.U;
 +import org.apache.ignite.plugin.extensions.communication.MessageReader;
 +import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 +import org.jetbrains.annotations.Nullable;
 +
 +import static java.nio.charset.StandardCharsets.UTF_8;
 +
 +/**
 + * Portable object implementation.
 + */
 +@IgniteCodeGeneratingFail // Fields arr and start should not be generated by MessageCodeGenerator.
 +public final class BinaryObjectImpl extends BinaryObjectExImpl implements Externalizable, KeyCacheObject {
 +    /** */
 +    private static final long serialVersionUID = 0L;
 +
 +    /** */
 +    @GridDirectTransient
 +    private PortableContext ctx;
 +
 +    /** */
 +    private byte[] arr;
 +
 +    /** */
 +    private int start;
 +
 +    /** */
 +    @GridDirectTransient
 +    private Object obj;
 +
 +    /** */
 +    @GridDirectTransient
 +    private boolean detachAllowed;
 +
 +    /**
 +     * For {@link Externalizable}.
 +     */
 +    public BinaryObjectImpl() {
 +        // No-op.
 +    }
 +
 +    /**
 +     * @param ctx Context.
 +     * @param arr Array.
 +     * @param start Start.
 +     */
 +    public BinaryObjectImpl(PortableContext ctx, byte[] arr, int start) {
 +        assert ctx != null;
 +        assert arr != null;
 +
 +        this.ctx = ctx;
 +        this.arr = arr;
 +        this.start = start;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte cacheObjectType() {
 +        return TYPE_BINARY;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean isPlatformType() {
 +        return false;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean internal() {
 +        return false;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) {
 +        Object obj0 = obj;
 +
 +        if (obj0 == null || (cpy && needCopy(ctx)))
 +            obj0 = deserializeValue(ctx);
 +
 +        return (T)obj0;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException {
 +        if (detached())
 +            return array();
 +
 +        int len = length();
 +
 +        byte[] arr0 = new byte[len];
 +
 +        U.arrayCopy(arr, start, arr0, 0, len);
 +
 +        return arr0;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
 +        if (detached())
 +            return this;
 +
 +        return (BinaryObjectImpl)detach();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
 +        this.ctx = ((CacheObjectBinaryProcessorImpl)ctx.processor()).portableContext();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException {
 +        // No-op.
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int length() {
 +        return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.TOTAL_LEN_POS);
 +    }
 +
 +    /**
 +     * @return Detached portable object.
 +     */
 +    public BinaryObject detach() {
 +        if (!detachAllowed || detached())
 +            return this;
 +
 +        int len = length();
 +
 +        byte[] arr0 = new byte[len];
 +
 +        U.arrayCopy(arr, start, arr0, 0, len);
 +
 +        return new BinaryObjectImpl(ctx, arr0, 0);
 +    }
 +
 +    /**
 +     * @return Detached or not.
 +     */
 +    public boolean detached() {
 +        return start == 0 && length() == arr.length;
 +    }
 +
 +    /**
 +     * @param detachAllowed Detach allowed flag.
 +     */
 +    public void detachAllowed(boolean detachAllowed) {
 +        this.detachAllowed = detachAllowed;
 +    }
 +
 +    /**
 +     * @return Context.
 +     */
 +    public PortableContext context() {
 +        return ctx;
 +    }
 +
 +    /**
 +     * @param ctx Context.
 +     */
 +    public void context(PortableContext ctx) {
 +        this.ctx = ctx;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte[] array() {
 +        return arr;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int start() {
 +        return start;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public long offheapAddress() {
 +        return 0;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected boolean hasArray() {
 +        return true;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int typeId() {
 +        return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.TYPE_ID_POS);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Nullable @Override public BinaryType type() throws BinaryObjectException {
 +        if (ctx == null)
 +            throw new BinaryObjectException("PortableContext is not set for the object.");
 +
 +        return ctx.metadata(typeId());
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override public <F> F field(String fieldName) throws BinaryObjectException {
 +        return (F) reader(null).unmarshalField(fieldName);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override public <F> F field(int fieldId) throws BinaryObjectException {
 +        return (F) reader(null).unmarshalField(fieldId);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override protected <F> F fieldByOrder(int order) {
 +        Object val;
 +
 +        // Calculate field position.
 +        int schemaOffset = PortablePrimitives.readInt(arr, start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS);
 +
 +        short flags = PortablePrimitives.readShort(arr, start + GridPortableMarshaller.FLAGS_POS);
 +
 +        int fieldIdLen = PortableUtils.isCompactFooter(flags) ? 0 : PortableUtils.FIELD_ID_LEN;
 +        int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
 +
 +        int fieldOffsetPos = start + schemaOffset + order * (fieldIdLen + fieldOffsetLen) + fieldIdLen;
 +
 +        int fieldPos;
 +
 +        if (fieldOffsetLen == PortableUtils.OFFSET_1)
 +            fieldPos = start + ((int)PortablePrimitives.readByte(arr, fieldOffsetPos) & 0xFF);
 +        else if (fieldOffsetLen == PortableUtils.OFFSET_2)
 +            fieldPos = start + ((int)PortablePrimitives.readShort(arr, fieldOffsetPos) & 0xFFFF);
 +        else
 +            fieldPos = start + PortablePrimitives.readInt(arr, fieldOffsetPos);
 +
 +        // Read header and try performing fast lookup for well-known types (the most common types go first).
 +        byte hdr = PortablePrimitives.readByte(arr, fieldPos);
 +
 +        switch (hdr) {
 +            case GridPortableMarshaller.INT:
 +                val = PortablePrimitives.readInt(arr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.LONG:
 +                val = PortablePrimitives.readLong(arr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.BOOLEAN:
 +                val = PortablePrimitives.readBoolean(arr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.SHORT:
 +                val = PortablePrimitives.readShort(arr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.BYTE:
 +                val = PortablePrimitives.readByte(arr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.CHAR:
 +                val = PortablePrimitives.readChar(arr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.FLOAT:
 +                val = PortablePrimitives.readFloat(arr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.DOUBLE:
 +                val = PortablePrimitives.readDouble(arr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.STRING: {
 +                int dataLen = PortablePrimitives.readInt(arr, fieldPos + 1);
 +
 +                val = new String(arr, fieldPos + 5, dataLen, UTF_8);
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.DATE: {
 +                long time = PortablePrimitives.readLong(arr, fieldPos + 1);
 +
 +                val = new Date(time);
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.TIMESTAMP: {
 +                long time = PortablePrimitives.readLong(arr, fieldPos + 1);
 +                int nanos = PortablePrimitives.readInt(arr, fieldPos + 1 + 8);
 +
 +                Timestamp ts = new Timestamp(time);
 +
 +                ts.setNanos(ts.getNanos() + nanos);
 +
 +                val = ts;
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.UUID: {
 +                long most = PortablePrimitives.readLong(arr, fieldPos + 1);
 +                long least = PortablePrimitives.readLong(arr, fieldPos + 1 + 8);
 +
 +                val = new UUID(most, least);
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.DECIMAL: {
 +                int scale = PortablePrimitives.readInt(arr, fieldPos + 1);
 +
 +                int dataLen = PortablePrimitives.readInt(arr, fieldPos + 5);
 +                byte[] data = PortablePrimitives.readByteArray(arr, fieldPos + 9, dataLen);
 +
 +                BigInteger intVal = new BigInteger(data);
 +
 +                if (scale < 0) {
 +                    scale &= 0x7FFFFFFF;
 +
 +                    intVal = intVal.negate();
 +                }
 +
 +                val = new BigDecimal(intVal, scale);
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.NULL:
 +                val = null;
 +
 +                break;
 +
 +            default:
 +                val = PortableUtils.unmarshal(PortableHeapInputStream.create(arr, fieldPos), ctx, null);
 +
 +                break;
 +        }
 +
 +        return (F)val;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override protected <F> F field(BinaryReaderHandles rCtx, String fieldName) {
 +        return (F)reader(rCtx).unmarshalField(fieldName);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean hasField(String fieldName) {
 +        return reader(null).findFieldByName(fieldName);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override public <T> T deserialize() throws BinaryObjectException {
 +        Object obj0 = obj;
 +
 +        if (obj0 == null)
 +            obj0 = deserializeValue(null);
 +
 +        return (T)obj0;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public BinaryObject clone() throws CloneNotSupportedException {
 +        return super.clone();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int hashCode() {
 +        return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.HASH_CODE_POS);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected int schemaId() {
 +        return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.SCHEMA_ID_POS);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected PortableSchema createSchema() {
 +        return reader(null).getOrCreateSchema();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void writeExternal(ObjectOutput out) throws IOException {
 +        out.writeObject(ctx);
 +
 +        if (detachAllowed) {
 +            int len = length();
 +
 +            out.writeInt(len);
 +            out.write(arr, start, len);
 +            out.writeInt(0);
 +        }
 +        else {
 +            out.writeInt(arr.length);
 +            out.write(arr);
 +            out.writeInt(start);
 +        }
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
 +        ctx = (PortableContext)in.readObject();
 +
 +        arr = new byte[in.readInt()];
 +
 +        in.readFully(arr);
 +
 +        start = in.readInt();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
 +        writer.setBuffer(buf);
 +
 +        if (!writer.isHeaderWritten()) {
 +            if (!writer.writeHeader(directType(), fieldsCount()))
 +                return false;
 +
 +            writer.onHeaderWritten();
 +        }
 +
 +        switch (writer.state()) {
 +            case 0:
 +                if (!writer.writeByteArray("arr",
 +                    arr,
 +                    detachAllowed ? start : 0,
 +                    detachAllowed ? length() : arr.length))
 +                    return false;
 +
 +                writer.incrementState();
 +
 +            case 1:
 +                if (!writer.writeInt("start", detachAllowed ? 0 : start))
 +                    return false;
 +
 +                writer.incrementState();
 +
 +        }
 +
 +        return true;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
 +        reader.setBuffer(buf);
 +
 +        if (!reader.beforeMessageRead())
 +            return false;
 +
 +        switch (reader.state()) {
 +            case 0:
 +                arr = reader.readByteArray("arr");
 +
 +                if (!reader.isLastRead())
 +                    return false;
 +
 +                reader.incrementState();
 +
 +            case 1:
 +                start = reader.readInt("start");
 +
 +                if (!reader.isLastRead())
 +                    return false;
 +
 +                reader.incrementState();
 +
 +        }
 +
 +        return true;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte directType() {
 +        return 113;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte fieldsCount() {
 +        return 3;
 +    }
 +
 +    /**
 +     * Runs value deserialization regardless of whether obj already has the deserialized value.
 +     * Will set obj if descriptor is configured to keep deserialized values.
 +     * @param coCtx CacheObjectContext.
 +     * @return Object.
 +     */
 +    private Object deserializeValue(@Nullable CacheObjectContext coCtx) {
-         // TODO: IGNITE-1272 - Deserialize with proper class loader.
 +        BinaryReaderExImpl reader = reader(null);
 +
 +        Object obj0 = reader.deserialize();
 +
 +        PortableClassDescriptor desc = reader.descriptor();
 +
 +        assert desc != null;
 +
 +        if (coCtx != null && coCtx.storeValue())
 +            obj = obj0;
 +
 +        return obj0;
 +    }
 +
 +    /**
 +     * @param ctx Context.
 +     * @return {@code True} need to copy value returned to user.
 +     */
 +    private boolean needCopy(CacheObjectContext ctx) {
 +        return ctx.copyOnGet() && obj != null && !ctx.processor().immutable(obj);
 +    }
 +
 +    /**
 +     * Create new reader for this object.
 +     *
 +     * @param rCtx Reader context.
 +     * @return Reader.
 +     */
 +    private BinaryReaderExImpl reader(@Nullable BinaryReaderHandles rCtx) {
 +        return new BinaryReaderExImpl(ctx,
 +            PortableHeapInputStream.create(arr, start),
 +            ctx.configuration().getClassLoader(),
 +            rCtx);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
index 27b46c1,0000000..2944099
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
@@@ -1,430 -1,0 +1,432 @@@
 +/*
 + * 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 org.apache.ignite.IgniteCheckedException;
 +import org.apache.ignite.binary.BinaryObject;
 +import org.apache.ignite.binary.BinaryObjectException;
 +import org.apache.ignite.binary.BinaryType;
 +import org.apache.ignite.internal.binary.streams.PortableOffheapInputStream;
 +import org.apache.ignite.internal.binary.streams.PortableOffheapInputStream;
 +import org.apache.ignite.internal.processors.cache.CacheObject;
 +import org.apache.ignite.internal.processors.cache.CacheObjectContext;
 +import org.apache.ignite.internal.util.GridUnsafe;
 +import org.apache.ignite.internal.util.typedef.internal.U;
 +import org.apache.ignite.plugin.extensions.communication.MessageReader;
 +import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 +import org.jetbrains.annotations.Nullable;
 +import sun.misc.Unsafe;
 +
 +import java.io.Externalizable;
 +import java.io.IOException;
 +import java.io.ObjectInput;
 +import java.io.ObjectOutput;
 +import java.math.BigDecimal;
 +import java.math.BigInteger;
 +import java.nio.ByteBuffer;
 +import java.sql.Timestamp;
 +import java.util.Date;
 +import java.util.UUID;
 +
 +import static java.nio.charset.StandardCharsets.UTF_8;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.BOOLEAN;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.BYTE;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.CHAR;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.DATE;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.DECIMAL;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.DOUBLE;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.FLOAT;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.INT;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.LONG;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.NULL;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.SHORT;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.STRING;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.TIMESTAMP;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.UUID;
 +
 +/**
 + *  Portable object implementation over offheap memory
 + */
 +public class BinaryObjectOffheapImpl extends BinaryObjectExImpl implements Externalizable, CacheObject {
 +    /** */
 +    private static final long serialVersionUID = 0L;
 +
 +    /** */
 +    private static final Unsafe UNSAFE = GridUnsafe.unsafe();
 +
 +    /** */
 +    private final PortableContext ctx;
 +
 +    /** */
 +    private final long ptr;
 +
 +    /** */
 +    private final int start;
 +
 +    /** */
 +    private final int size;
 +
 +    /**
 +     * For {@link Externalizable} (not supported).
 +     */
 +    public BinaryObjectOffheapImpl() {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /**
 +     * @param ctx Context.
 +     * @param ptr Memory address.
 +     * @param start Object start.
 +     * @param size Memory size.
 +     */
 +    public BinaryObjectOffheapImpl(PortableContext ctx, long ptr, int start, int size) {
 +        this.ctx = ctx;
 +        this.ptr = ptr;
 +        this.start = start;
 +        this.size = size;
 +    }
 +
 +    /**
 +     * @return Heap-based copy.
 +     */
 +    public BinaryObject heapCopy() {
 +        return new BinaryObjectImpl(ctx, U.copyMemory(ptr, size), start);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int typeId() {
 +        return UNSAFE.getInt(ptr + start + GridPortableMarshaller.TYPE_ID_POS);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int length() {
 +        return UNSAFE.getInt(ptr + start + GridPortableMarshaller.TOTAL_LEN_POS);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int hashCode() {
 +        return UNSAFE.getInt(ptr + start + GridPortableMarshaller.HASH_CODE_POS);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected int schemaId() {
 +        return UNSAFE.getInt(ptr + start + GridPortableMarshaller.SCHEMA_ID_POS);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected PortableSchema createSchema() {
 +        return reader(null).getOrCreateSchema();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int start() {
 +        return start;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte[] array() {
 +        return null;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public long offheapAddress() {
 +        return ptr;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected boolean hasArray() {
 +        return false;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Nullable @Override public BinaryType type() throws BinaryObjectException {
 +        if (ctx == null)
 +            throw new BinaryObjectException("PortableContext is not set for the object.");
 +
 +        return ctx.metadata(typeId());
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override public <F> F field(String fieldName) throws BinaryObjectException {
 +        return (F) reader(null).unmarshalField(fieldName);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override public <F> F field(int fieldId) throws BinaryObjectException {
 +        return (F) reader(null).unmarshalField(fieldId);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override protected <F> F fieldByOrder(int order) {
 +        Object val;
 +
 +        // Calculate field position.
 +        int schemaOffset = PortablePrimitives.readInt(ptr, start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS);
 +
 +        short flags = PortablePrimitives.readShort(ptr, start + GridPortableMarshaller.FLAGS_POS);
 +
 +        int fieldIdLen = PortableUtils.isCompactFooter(flags) ? 0 : PortableUtils.FIELD_ID_LEN;
 +        int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
 +
 +        int fieldOffsetPos = start + schemaOffset + order * (fieldIdLen + fieldOffsetLen) + fieldIdLen;
 +
 +        int fieldPos;
 +
 +        if (fieldOffsetLen == PortableUtils.OFFSET_1)
 +            fieldPos = start + ((int)PortablePrimitives.readByte(ptr, fieldOffsetPos) & 0xFF);
 +        else if (fieldOffsetLen == PortableUtils.OFFSET_2)
 +            fieldPos = start + ((int)PortablePrimitives.readShort(ptr, fieldOffsetPos) & 0xFFFF);
 +        else
 +            fieldPos = start + PortablePrimitives.readInt(ptr, fieldOffsetPos);
 +
 +        // Read header and try performing fast lookup for well-known types (the most common types go first).
 +        byte hdr = PortablePrimitives.readByte(ptr, fieldPos);
 +
 +        switch (hdr) {
 +            case GridPortableMarshaller.INT:
 +                val = PortablePrimitives.readInt(ptr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.LONG:
 +                val = PortablePrimitives.readLong(ptr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.BOOLEAN:
 +                val = PortablePrimitives.readBoolean(ptr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.SHORT:
 +                val = PortablePrimitives.readShort(ptr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.BYTE:
 +                val = PortablePrimitives.readByte(ptr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.CHAR:
 +                val = PortablePrimitives.readChar(ptr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.FLOAT:
 +                val = PortablePrimitives.readFloat(ptr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.DOUBLE:
 +                val = PortablePrimitives.readDouble(ptr, fieldPos + 1);
 +
 +                break;
 +
 +            case GridPortableMarshaller.STRING: {
 +                int dataLen = PortablePrimitives.readInt(ptr, fieldPos + 1);
 +                byte[] data = PortablePrimitives.readByteArray(ptr, fieldPos + 5, dataLen);
 +
 +                val = new String(data, UTF_8);
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.DATE: {
 +                long time = PortablePrimitives.readLong(ptr, fieldPos + 1);
 +
 +                val = new Date(time);
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.TIMESTAMP: {
 +                long time = PortablePrimitives.readLong(ptr, fieldPos + 1);
 +                int nanos = PortablePrimitives.readInt(ptr, fieldPos + 1 + 8);
 +
 +                Timestamp ts = new Timestamp(time);
 +
 +                ts.setNanos(ts.getNanos() + nanos);
 +
 +                val = ts;
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.UUID: {
 +                long most = PortablePrimitives.readLong(ptr, fieldPos + 1);
 +                long least = PortablePrimitives.readLong(ptr, fieldPos + 1 + 8);
 +
 +                val = new UUID(most, least);
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.DECIMAL: {
 +                int scale = PortablePrimitives.readInt(ptr, fieldPos + 1);
 +
 +                int dataLen = PortablePrimitives.readInt(ptr, fieldPos + 5);
 +                byte[] data = PortablePrimitives.readByteArray(ptr, fieldPos + 9, dataLen);
 +
 +                BigInteger intVal = new BigInteger(data);
 +
 +                if (scale < 0) {
 +                    scale &= 0x7FFFFFFF;
 +
 +                    intVal = intVal.negate();
 +                }
 +
 +                val = new BigDecimal(intVal, scale);
 +
 +                break;
 +            }
 +
 +            case GridPortableMarshaller.NULL:
 +                val = null;
 +
 +                break;
 +
 +            default:
 +                PortableOffheapInputStream stream = new PortableOffheapInputStream(ptr, size, false);
 +
 +                stream.position(fieldPos);
 +
 +                val = PortableUtils.unmarshal(stream, ctx, null);
 +
 +                break;
 +        }
 +
 +        return (F)val;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override protected <F> F field(BinaryReaderHandles rCtx, String fieldName) {
 +        return (F)reader(rCtx).unmarshalField(fieldName);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean hasField(String fieldName) {
 +        return reader(null).findFieldByName(fieldName);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override public <T> T deserialize() throws BinaryObjectException {
 +        return (T)deserializeValue();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("CloneDoesntCallSuperClone")
 +    @Override public BinaryObject clone() throws CloneNotSupportedException {
 +        return heapCopy();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte cacheObjectType() {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean isPlatformType() {
 +        return false;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) {
 +        return (T)deserializeValue();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte directType() {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte fieldsCount() {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void writeExternal(ObjectOutput out) throws IOException {
 +        throw new UnsupportedOperationException(); // To make sure it is not marshalled.
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
 +        throw new UnsupportedOperationException(); // To make sure it is not marshalled.
 +    }
 +
 +    /**
 +     * @return Deserialized value.
 +     */
 +    private Object deserializeValue() {
-         // TODO: IGNITE-1272 - Deserialize with proper class loader.
 +        return reader(null).deserialize();
 +    }
 +
 +    /**
 +     * Create new reader for this object.
 +     *
 +     * @param rCtx Reader context.
 +     * @return Reader.
 +     */
 +    private BinaryReaderExImpl reader(@Nullable BinaryReaderHandles rCtx) {
 +        PortableOffheapInputStream stream = new PortableOffheapInputStream(ptr, size, false);
 +
 +        stream.position(start);
 +
-         return new BinaryReaderExImpl(ctx, stream, null, rCtx);
++        return new BinaryReaderExImpl(ctx,
++            stream,
++            ctx.configuration().getClassLoader(),
++            rCtx);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
index f5e4e06,0000000..f1d4185
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
@@@ -1,587 -1,0 +1,586 @@@
 +/*
 + * 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.builder;
 +
 +import org.apache.ignite.binary.BinaryInvalidTypeException;
 +import org.apache.ignite.binary.BinaryObject;
 +import org.apache.ignite.binary.BinaryObjectBuilder;
 +import org.apache.ignite.binary.BinaryObjectException;
 +import org.apache.ignite.binary.BinaryType;
 +import org.apache.ignite.internal.binary.BinaryMetadata;
 +import org.apache.ignite.internal.binary.BinaryObjectImpl;
 +import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 +import org.apache.ignite.internal.binary.GridPortableMarshaller;
 +import org.apache.ignite.internal.binary.PortableContext;
 +import org.apache.ignite.internal.binary.PortableSchema;
 +import org.apache.ignite.internal.binary.PortableSchemaRegistry;
 +import org.apache.ignite.internal.binary.BinaryMetadata;
 +import org.apache.ignite.internal.binary.BinaryObjectImpl;
 +import org.apache.ignite.internal.binary.BinaryObjectOffheapImpl;
 +import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 +import org.apache.ignite.internal.binary.GridPortableMarshaller;
 +import org.apache.ignite.internal.binary.PortableContext;
 +import org.apache.ignite.internal.binary.PortableSchema;
 +import org.apache.ignite.internal.binary.PortableSchemaRegistry;
 +import org.apache.ignite.internal.binary.PortableUtils;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.apache.ignite.internal.util.typedef.internal.U;
 +import org.apache.ignite.lang.IgniteBiTuple;
 +import org.jetbrains.annotations.Nullable;
 +
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.LinkedHashMap;
 +import java.util.Map;
 +import java.util.Set;
 +
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.DFLT_HDR_LEN;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.FLAGS_POS;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.HASH_CODE_POS;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.PROTO_VER_POS;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.TYPE_ID_POS;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.UNREGISTERED_TYPE_ID;
 +
 +/**
 + *
 + */
 +public class BinaryObjectBuilderImpl implements BinaryObjectBuilder {
 +    /** */
 +    private static final Object REMOVED_FIELD_MARKER = new Object();
 +
 +    /** */
 +    private final PortableContext ctx;
 +
 +    /** */
 +    private final int typeId;
 +
 +    /** May be null. */
 +    private String typeName;
 +
 +    /** May be null. */
 +    private String clsNameToWrite;
 +
 +    /** */
 +    private boolean registeredType = true;
 +
 +    /** */
 +    private Map<String, Object> assignedVals;
 +
 +    /** */
 +    private Map<Integer, Object> readCache;
 +
 +    /** Position of object in source array, or -1 if object is not created from PortableObject. */
 +    private final int start;
 +
 +    /** Flags. */
 +    private final short flags;
 +
 +    /** Total header length */
 +    private final int hdrLen;
 +
 +    /** Context of PortableObject reading process. Or {@code null} if object is not created from PortableObject. */
 +    private final PortableBuilderReader reader;
 +
 +    /** */
 +    private int hashCode;
 +
 +    /**
 +     * @param clsName Class name.
 +     * @param ctx Portable context.
 +     */
 +    public BinaryObjectBuilderImpl(PortableContext ctx, String clsName) {
 +        this(ctx, ctx.typeId(clsName), PortableContext.typeName(clsName));
 +    }
 +
 +    /**
 +     * @param typeName Type name.
 +     * @param ctx Context.
 +     * @param typeId Type id.
 +     */
 +    public BinaryObjectBuilderImpl(PortableContext ctx, int typeId, String typeName) {
 +        this.typeId = typeId;
 +        this.typeName = typeName;
 +        this.ctx = ctx;
 +
 +        start = -1;
 +        flags = -1;
 +        reader = null;
 +        hdrLen = GridPortableMarshaller.DFLT_HDR_LEN;
 +
 +        readCache = Collections.emptyMap();
 +    }
 +
 +    /**
 +     * @param obj Object to wrap.
 +     */
 +    public BinaryObjectBuilderImpl(BinaryObjectImpl obj) {
 +        this(new PortableBuilderReader(obj), obj.start());
 +
 +        reader.registerObject(this);
 +    }
 +
 +    /**
 +     * @param reader ctx
 +     * @param start Start.
 +     */
 +    BinaryObjectBuilderImpl(PortableBuilderReader reader, int start) {
 +        this.reader = reader;
 +        this.start = start;
 +        this.flags = reader.readShortPositioned(start + GridPortableMarshaller.FLAGS_POS);
 +
 +        byte ver = reader.readBytePositioned(start + GridPortableMarshaller.PROTO_VER_POS);
 +
 +        PortableUtils.checkProtocolVersion(ver);
 +
 +        int typeId = reader.readIntPositioned(start + GridPortableMarshaller.TYPE_ID_POS);
 +        ctx = reader.portableContext();
 +        hashCode = reader.readIntPositioned(start + GridPortableMarshaller.HASH_CODE_POS);
 +
 +        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
 +            int mark = reader.position();
 +
 +            reader.position(start + GridPortableMarshaller.DFLT_HDR_LEN);
 +
 +            clsNameToWrite = reader.readString();
 +
 +            Class cls;
 +
 +            try {
-                 // TODO: IGNITE-1272 - Is class loader needed here?
-                 cls = U.forName(clsNameToWrite, null);
++                cls = U.forName(clsNameToWrite, ctx.configuration().getClassLoader());
 +            }
 +            catch (ClassNotFoundException e) {
 +                throw new BinaryInvalidTypeException("Failed to load the class: " + clsNameToWrite, e);
 +            }
 +
 +            this.typeId = ctx.descriptorForClass(cls, false).typeId();
 +
 +            registeredType = false;
 +
 +            hdrLen = reader.position() - mark;
 +
 +            reader.position(mark);
 +        }
 +        else {
 +            this.typeId = typeId;
 +            hdrLen = GridPortableMarshaller.DFLT_HDR_LEN;
 +        }
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public BinaryObject build() {
 +        try (BinaryWriterExImpl writer = new BinaryWriterExImpl(ctx)) {
 +            writer.typeId(typeId);
 +
 +            PortableBuilderSerializer serializationCtx = new PortableBuilderSerializer();
 +
 +            serializationCtx.registerObjectWriting(this, 0);
 +
 +            serializeTo(writer, serializationCtx);
 +
 +            byte[] arr = writer.array();
 +
 +            return new BinaryObjectImpl(ctx, arr, 0);
 +        }
 +    }
 +
 +    /**
 +     * @param writer Writer.
 +     * @param serializer Serializer.
 +     */
 +    void serializeTo(BinaryWriterExImpl writer, PortableBuilderSerializer serializer) {
 +        try {
 +            writer.preWrite(registeredType ? null : clsNameToWrite);
 +
 +            Set<Integer> remainsFlds = null;
 +
 +            if (reader != null) {
 +                PortableSchema schema = reader.schema();
 +
 +                Map<Integer, Object> assignedFldsById;
 +
 +                if (assignedVals != null) {
 +                    assignedFldsById = U.newHashMap(assignedVals.size());
 +
 +                    for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
 +                        int fieldId = ctx.fieldId(typeId, entry.getKey());
 +
 +                        assignedFldsById.put(fieldId, entry.getValue());
 +                    }
 +
 +                    remainsFlds = assignedFldsById.keySet();
 +                }
 +                else
 +                    assignedFldsById = Collections.emptyMap();
 +
 +                // Get footer details.
 +                int fieldIdLen = PortableUtils.fieldIdLength(flags);
 +                int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
 +
 +                IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(reader, start);
 +
 +                int footerPos = footer.get1();
 +                int footerEnd = footer.get2();
 +
 +                // Get raw position.
 +                int rawPos = PortableUtils.rawOffsetAbsolute(reader, start);
 +
 +                // Position reader on data.
 +                reader.position(start + hdrLen);
 +
 +                int idx = 0;
 +
 +                while (reader.position() < rawPos) {
 +                    int fieldId = schema.fieldId(idx++);
 +                    int fieldLen =
 +                        fieldPositionAndLength(footerPos, footerEnd, rawPos, fieldIdLen, fieldOffsetLen).get2();
 +
 +                    int postPos = reader.position() + fieldLen; // Position where reader will be placed afterwards.
 +
 +                    footerPos += fieldIdLen + fieldOffsetLen;
 +
 +                    if (assignedFldsById.containsKey(fieldId)) {
 +                        Object assignedVal = assignedFldsById.remove(fieldId);
 +
 +                        if (assignedVal != REMOVED_FIELD_MARKER) {
 +                            writer.writeFieldId(fieldId);
 +
 +                            serializer.writeValue(writer, assignedVal);
 +                        }
 +                    }
 +                    else {
 +                        int type = fieldLen != 0 ? reader.readByte(0) : 0;
 +
 +                        if (fieldLen != 0 && !PortableUtils.isPlainArrayType(type) && PortableUtils.isPlainType(type)) {
 +                            writer.writeFieldId(fieldId);
 +
 +                            writer.write(reader.array(), reader.position(), fieldLen);
 +                        }
 +                        else {
 +                            writer.writeFieldId(fieldId);
 +
 +                            Object val;
 +
 +                            if (fieldLen == 0)
 +                                val = null;
 +                            else if (readCache == null) {
 +                                val = reader.parseValue();
 +
 +                                assert reader.position() == postPos;
 +                            }
 +                            else
 +                                val = readCache.get(fieldId);
 +
 +                            serializer.writeValue(writer, val);
 +                        }
 +                    }
 +
 +                    reader.position(postPos);
 +                }
 +            }
 +
 +            BinaryType meta = ctx.metadata(typeId);
 +
 +            Map<String, Integer> fieldsMeta = null;
 +
 +            if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) {
 +                for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
 +                    Object val = entry.getValue();
 +
 +                    if (val == REMOVED_FIELD_MARKER)
 +                        continue;
 +
 +                    String name = entry.getKey();
 +
 +                    int fieldId = ctx.fieldId(typeId, name);
 +
 +                    if (remainsFlds != null && !remainsFlds.contains(fieldId))
 +                        continue;
 +
 +                    writer.writeFieldId(fieldId);
 +
 +                    serializer.writeValue(writer, val);
 +
 +                    String oldFldTypeName = meta == null ? null : meta.fieldTypeName(name);
 +
 +                    boolean nullObjField = false;
 +
 +                    int newFldTypeId;
 +
 +                    if (val instanceof PortableValueWithType) {
 +                        newFldTypeId = ((PortableValueWithType)val).typeId();
 +
 +                        if (newFldTypeId == GridPortableMarshaller.OBJ && ((PortableValueWithType)val).value() == null)
 +                            nullObjField = true;
 +                    }
 +                    else
 +                        newFldTypeId = PortableUtils.typeByClass(val.getClass());
 +
 +                    String newFldTypeName = PortableUtils.fieldTypeName(newFldTypeId);
 +
 +                    if (oldFldTypeName == null) {
 +                        // It's a new field, we have to add it to metadata.
 +                        if (fieldsMeta == null)
 +                            fieldsMeta = new HashMap<>();
 +
 +                        fieldsMeta.put(name, PortableUtils.fieldTypeId(newFldTypeName));
 +                    }
 +                    else if (!nullObjField) {
 +                        String objTypeName = PortableUtils.fieldTypeName(GridPortableMarshaller.OBJ);
 +
 +                        if (!objTypeName.equals(oldFldTypeName) && !oldFldTypeName.equals(newFldTypeName)) {
 +                            throw new BinaryObjectException(
 +                                "Wrong value has been set [" +
 +                                    "typeName=" + (typeName == null ? meta.typeName() : typeName) +
 +                                    ", fieldName=" + name +
 +                                    ", fieldType=" + oldFldTypeName +
 +                                    ", assignedValueType=" + newFldTypeName + ']'
 +                            );
 +                        }
 +                    }
 +                }
 +            }
 +
 +            if (reader != null) {
 +                // Write raw data if any.
 +                int rawOff = PortableUtils.rawOffsetAbsolute(reader, start);
 +                int footerStart = PortableUtils.footerStartAbsolute(reader, start);
 +
 +                if (rawOff < footerStart) {
 +                    writer.rawWriter();
 +
 +                    writer.write(reader.array(), rawOff, footerStart - rawOff);
 +                }
 +
 +                // Shift reader to the end of the object.
 +                reader.position(start + PortableUtils.length(reader, start));
 +            }
 +
 +            writer.postWrite(true, registeredType, hashCode);
 +
 +            // Update metadata if needed.
 +            int schemaId = writer.schemaId();
 +
 +            PortableSchemaRegistry schemaReg = ctx.schemaRegistry(typeId);
 +
 +            if (schemaReg.schema(schemaId) == null) {
 +                String typeName = this.typeName;
 +
 +                if (typeName == null) {
 +                    assert meta != null;
 +
 +                    typeName = meta.typeName();
 +                }
 +
 +                PortableSchema curSchema = writer.currentSchema();
 +
 +                ctx.updateMetadata(typeId, new BinaryMetadata(typeId, typeName, fieldsMeta,
 +                    ctx.affinityKeyFieldName(typeId), Collections.singleton(curSchema), false));
 +
 +                schemaReg.addSchema(curSchema.schemaId(), curSchema);
 +            }
 +        }
 +        finally {
 +            writer.popSchema();
 +        }
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public BinaryObjectBuilderImpl hashCode(int hashCode) {
 +        this.hashCode = hashCode;
 +
 +        return this;
 +    }
 +
 +    /**
 +     * Get field position and length.
 +     *
 +     * @param footerPos Field position inside the footer (absolute).
 +     * @param footerEnd Footer end (absolute).
 +     * @param rawPos Raw data position (absolute).
 +     * @param fieldIdLen Field ID length.
 +     * @param fieldOffsetLen Field offset length.
 +     * @return Tuple with field position and length.
 +     */
 +    private IgniteBiTuple<Integer, Integer> fieldPositionAndLength(int footerPos, int footerEnd, int rawPos,
 +        int fieldIdLen, int fieldOffsetLen) {
 +        // Get field offset first.
 +        int fieldOffset = PortableUtils.fieldOffsetRelative(reader, footerPos + fieldIdLen, fieldOffsetLen);
 +        int fieldPos = start + fieldOffset;
 +
 +        // Get field length.
 +        int fieldLen;
 +
 +        if (footerPos + fieldIdLen + fieldOffsetLen == footerEnd)
 +            // This is the last field, compare to raw offset.
 +            fieldLen = rawPos - fieldPos;
 +        else {
 +            // Field is somewhere in the middle, get difference with the next offset.
 +            int nextFieldOffset = PortableUtils.fieldOffsetRelative(reader,
 +                footerPos + fieldIdLen + fieldOffsetLen + fieldIdLen, fieldOffsetLen);
 +
 +            fieldLen = nextFieldOffset - fieldOffset;
 +        }
 +
 +        return F.t(fieldPos, fieldLen);
 +    }
 +
 +    /**
 +     * Initialize read cache if needed.
 +     */
 +    private void ensureReadCacheInit() {
 +        assert reader != null;
 +
 +        if (readCache == null) {
 +            int fieldIdLen = PortableUtils.fieldIdLength(flags);
 +            int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
 +
 +            PortableSchema schema = reader.schema();
 +
 +            Map<Integer, Object> readCache = new HashMap<>();
 +
 +            IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(reader, start);
 +
 +            int footerPos = footer.get1();
 +            int footerEnd = footer.get2();
 +
 +            int rawPos = PortableUtils.rawOffsetAbsolute(reader, start);
 +
 +            int idx = 0;
 +
 +            while (footerPos + fieldIdLen < footerEnd) {
 +                int fieldId = schema.fieldId(idx++);
 +
 +                IgniteBiTuple<Integer, Integer> posAndLen =
 +                    fieldPositionAndLength(footerPos, footerEnd, rawPos, fieldIdLen, fieldOffsetLen);
 +
 +                Object val = reader.getValueQuickly(posAndLen.get1(), posAndLen.get2());
 +
 +                readCache.put(fieldId, val);
 +
 +                // Shift current footer position.
 +                footerPos += fieldIdLen + fieldOffsetLen;
 +            }
 +
 +            this.readCache = readCache;
 +        }
 +    }
 +
 +    /** {@inheritDoc} */
 +    @SuppressWarnings("unchecked")
 +    @Override public <T> T getField(String name) {
 +        Object val;
 +
 +        if (assignedVals != null && assignedVals.containsKey(name)) {
 +            val = assignedVals.get(name);
 +
 +            if (val == REMOVED_FIELD_MARKER)
 +                return null;
 +        }
 +        else {
 +            ensureReadCacheInit();
 +
 +            int fldId = ctx.fieldId(typeId, name);
 +
 +            val = readCache.get(fldId);
 +        }
 +
 +        return (T)PortableUtils.unwrapLazy(val);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public BinaryObjectBuilder setField(String name, Object val0) {
 +        Object val = val0 == null ? new PortableValueWithType(PortableUtils.typeByClass(Object.class), null) : val0;
 +
 +        if (assignedVals == null)
 +            assignedVals = new LinkedHashMap<>();
 +
 +        Object oldVal = assignedVals.put(name, val);
 +
 +        if (oldVal instanceof PortableValueWithType && val0 != null) {
 +            ((PortableValueWithType)oldVal).value(val);
 +
 +            assignedVals.put(name, oldVal);
 +        }
 +
 +        return this;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public <T> BinaryObjectBuilder setField(String name, @Nullable T val, Class<? super T> type) {
 +        if (assignedVals == null)
 +            assignedVals = new LinkedHashMap<>();
 +
 +        assignedVals.put(name, new PortableValueWithType(PortableUtils.typeByClass(type), val));
 +
 +        return this;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public BinaryObjectBuilder setField(String name, @Nullable BinaryObjectBuilder builder) {
 +        if (builder == null)
 +            return setField(name, null, Object.class);
 +        else
 +            return setField(name, (Object)builder);
 +    }
 +
 +    /**
 +     * Removes field from portable object.
 +     *
 +     * @param name Field name.
 +     * @return {@code this} instance for chaining.
 +     */
 +    @Override public BinaryObjectBuilderImpl removeField(String name) {
 +        if (assignedVals == null)
 +            assignedVals = new LinkedHashMap<>();
 +
 +        assignedVals.put(name, REMOVED_FIELD_MARKER);
 +
 +        return this;
 +    }
 +
 +    /**
 +     * Creates builder initialized by specified portable object.
 +     *
 +     * @param obj Portable object to initialize builder.
 +     * @return New builder.
 +     */
 +    public static BinaryObjectBuilderImpl wrap(BinaryObject obj) {
 +        BinaryObjectImpl heapObj;
 +
 +        if (obj instanceof BinaryObjectOffheapImpl)
 +            heapObj = (BinaryObjectImpl)((BinaryObjectOffheapImpl)obj).heapCopy();
 +        else
 +            heapObj = (BinaryObjectImpl)obj;
 +
 +        return new BinaryObjectBuilderImpl(heapObj);
 +    }
 +
 +    /**
 +     * @return Object start position in source array.
 +     */
 +    int start() {
 +        return start;
 +    }
 +
 +    /**
 +     * @return Object type id.
 +     */
 +    public int typeId() {
 +        return typeId;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderEnum.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderEnum.java
index 3bb8194,0000000..779c514
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderEnum.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderEnum.java
@@@ -1,116 -1,0 +1,115 @@@
 +/*
 + * 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.builder;
 +
 +import org.apache.ignite.internal.binary.GridPortableMarshaller;
 +import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 +import org.apache.ignite.internal.util.typedef.internal.U;
 +import org.apache.ignite.binary.BinaryInvalidTypeException;
 +
 +/**
 + *
 + */
 +public class PortableBuilderEnum implements PortableBuilderSerializationAware {
 +    /** */
 +    private final int ordinal;
 +
 +    /** */
 +    private final int typeId;
 +
 +    /** */
 +    private final String clsName;
 +
 +    /**
 +     * @param typeId Type ID.
 +     * @param anEnum Enum instance.
 +     */
 +    public PortableBuilderEnum(int typeId, Enum anEnum) {
 +        ordinal = anEnum.ordinal();
 +        this.typeId = typeId;
 +        clsName = null;
 +    }
 +
 +    /**
 +     * @param reader PortableBuilderReader.
 +     */
 +    public PortableBuilderEnum(PortableBuilderReader reader) {
 +        int typeId = reader.readInt();
 +
 +        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
 +            clsName = reader.readString();
 +
 +            Class cls;
 +
 +            try {
-                 // TODO: IGNITE-1272 - Is class loader needed here?
-                 cls = U.forName(reader.readString(), null);
++                cls = U.forName(reader.readString(), reader.portableContext().configuration().getClassLoader());
 +            }
 +            catch (ClassNotFoundException e) {
 +                throw new BinaryInvalidTypeException("Failed to load the class: " + clsName, e);
 +            }
 +
 +            this.typeId = reader.portableContext().descriptorForClass(cls, false).typeId();
 +        }
 +        else {
 +            this.typeId = typeId;
 +            this.clsName = null;
 +        }
 +
 +        ordinal = reader.readInt();
 +    }
 +
 +    /**
 +     * @return Ordinal.
 +     */
 +    public int getOrdinal() {
 +        return ordinal;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void writeTo(BinaryWriterExImpl writer, PortableBuilderSerializer ctx) {
 +        writer.writeByte(GridPortableMarshaller.ENUM);
 +
 +        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
 +            writer.writeInt(GridPortableMarshaller.UNREGISTERED_TYPE_ID);
 +            writer.writeString(clsName);
 +        }
 +        else
 +            writer.writeInt(typeId);
 +
 +        writer.writeInt(ordinal);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean equals(Object o) {
 +        if (o == null || getClass() != o.getClass())
 +            return false;
 +
 +        PortableBuilderEnum that = (PortableBuilderEnum)o;
 +
 +        return ordinal == that.ordinal && typeId == that.typeId;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int hashCode() {
 +        int result = ordinal;
 +
 +        result = 31 * result + typeId;
 +
 +        return result;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderReader.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderReader.java
index 2b28e3d,0000000..c86fb95
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderReader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderReader.java
@@@ -1,856 -1,0 +1,857 @@@
 +/*
 + * 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.builder;
 +
 +import org.apache.ignite.binary.BinaryObjectException;
 +import org.apache.ignite.internal.binary.BinaryObjectImpl;
 +import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 +import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 +import org.apache.ignite.internal.binary.GridPortableMarshaller;
 +import org.apache.ignite.internal.binary.PortableContext;
 +import org.apache.ignite.internal.binary.PortablePositionReadable;
 +import org.apache.ignite.internal.binary.PortablePrimitives;
 +import org.apache.ignite.internal.binary.PortableSchema;
 +import org.apache.ignite.internal.binary.streams.PortableHeapInputStream;
 +import org.apache.ignite.internal.binary.BinaryObjectImpl;
 +import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 +import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 +import org.apache.ignite.internal.binary.GridPortableMarshaller;
 +import org.apache.ignite.internal.binary.PortableContext;
 +import org.apache.ignite.internal.binary.PortablePositionReadable;
 +import org.apache.ignite.internal.binary.PortablePrimitives;
 +import org.apache.ignite.internal.binary.PortableSchema;
 +import org.apache.ignite.internal.binary.PortableUtils;
 +import org.apache.ignite.internal.binary.streams.PortableHeapInputStream;
 +
 +import java.sql.Timestamp;
 +import java.util.Date;
 +import java.util.HashMap;
 +import java.util.Map;
 +
 +import static java.nio.charset.StandardCharsets.UTF_8;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.NULL;
 +import static org.apache.ignite.internal.binary.GridPortableMarshaller.STRING;
 +
 +/**
 + *
 + */
 +public class PortableBuilderReader implements PortablePositionReadable {
 +    /** */
 +    private final PortableContext ctx;
 +
 +    /** */
 +    private final byte[] arr;
 +
 +    /** */
 +    private final BinaryReaderExImpl reader;
 +
 +    /** */
 +    private final Map<Integer, BinaryObjectBuilderImpl> objMap;
 +
 +    /** */
 +    private int pos;
 +
 +    /*
 +     * Constructor.
 +     *
 +     * @param objImpl Portable object
 +     */
 +    PortableBuilderReader(BinaryObjectImpl objImpl) {
 +        ctx = objImpl.context();
 +        arr = objImpl.array();
 +        pos = objImpl.start();
 +
-         // TODO: IGNITE-1272 - Is class loader needed here?
-         reader = new BinaryReaderExImpl(ctx, PortableHeapInputStream.create(arr, pos), null);
++        reader = new BinaryReaderExImpl(ctx,
++            PortableHeapInputStream.create(arr, pos),
++            ctx.configuration().getClassLoader());
 +
 +        objMap = new HashMap<>();
 +    }
 +
 +    /**
 +     * Copying constructor.
 +     *
 +     * @param other Other reader.
 +     * @param start Start position.
 +     */
 +    PortableBuilderReader(PortableBuilderReader other, int start) {
 +        this.ctx = other.ctx;
 +        this.arr = other.arr;
 +        this.pos = start;
 +
 +        reader = new BinaryReaderExImpl(ctx, PortableHeapInputStream.create(arr, start), null, other.reader.handles());
 +
 +        this.objMap = other.objMap;
 +    }
 +
 +    /**
 +     * @return Portable context.
 +     */
 +    public PortableContext portableContext() {
 +        return ctx;
 +    }
 +
 +    /**
 +     * @param obj Mutable portable object.
 +     */
 +    public void registerObject(BinaryObjectBuilderImpl obj) {
 +        objMap.put(obj.start(), obj);
 +    }
 +
 +    /**
 +     * Get schema of the object, starting at the given position.
 +     *
 +     * @return Object's schema.
 +     */
 +    public PortableSchema schema() {
 +        return reader.getOrCreateSchema();
 +    }
 +
 +    /**
 +     * @return Read int value.
 +     */
 +    public int readInt() {
 +        int res = readInt(0);
 +
 +        pos += 4;
 +
 +        return res;
 +    }
 +
 +    /**
 +     * @return Read int value.
 +     */
 +    public byte readByte() {
 +        return arr[pos++];
 +    }
 +
 +    /**
 +     * @return Read boolean value.
 +     */
 +    public boolean readBoolean() {
 +        return readByte() == 1;
 +    }
 +
 +    /**
 +     * @return Read int value.
 +     */
 +    public byte readByte(int off) {
 +        return arr[pos + off];
 +    }
 +
 +    /**
 +     * @param off Offset related to {@link #pos}
 +     * @return Read int value.
 +     */
 +    public int readInt(int off) {
 +        return PortablePrimitives.readInt(arr, pos + off);
 +    }
 +
 +    /**
 +     * @param pos Position in the source array.
 +     * @return Read byte value.
 +     */
 +    public byte readBytePositioned(int pos) {
 +        return PortablePrimitives.readByte(arr, pos);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public short readShortPositioned(int pos) {
 +        return PortablePrimitives.readShort(arr, pos);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int readIntPositioned(int pos) {
 +        return PortablePrimitives.readInt(arr, pos);
 +    }
 +
 +    /**
 +     * @return Read length of array.
 +     */
 +    public int readLength() {
 +        return PortablePrimitives.readInt(arr, pos);
 +    }
 +
 +    /**
 +     * Read string length.
 +     *
 +     * @return String length.
 +     */
 +    public int readStringLength() {
 +        return PortablePrimitives.readInt(arr, pos);
 +    }
 +
 +    /**
 +     * Reads string.
 +     *
 +     * @return String.
 +     */
 +    public String readString() {
 +        byte flag = readByte();
 +
 +        if (flag == GridPortableMarshaller.NULL)
 +            return null;
 +
 +        if (flag != GridPortableMarshaller.STRING)
 +            throw new BinaryObjectException("Failed to deserialize String.");
 +
 +        int len = readInt();
 +
 +        String str = new String(arr, pos, len, UTF_8);
 +
 +        pos += len;
 +
 +        return str;
 +    }
 +
 +    /**
 +     *
 +     */
 +    public void skipValue() {
 +        byte type = arr[pos++];
 +
 +        int len;
 +
 +        switch (type) {
 +            case GridPortableMarshaller.NULL:
 +                return;
 +
 +            case GridPortableMarshaller.OBJ:
 +                pos += readInt(GridPortableMarshaller.TOTAL_LEN_POS - 1) - 1;
 +
 +                return;
 +
 +            case GridPortableMarshaller.BOOLEAN:
 +            case GridPortableMarshaller.BYTE:
 +                len = 1;
 +                break;
 +
 +            case GridPortableMarshaller.CHAR:
 +            case GridPortableMarshaller.SHORT:
 +                len = 2;
 +
 +                break;
 +
 +            case GridPortableMarshaller.HANDLE:
 +            case GridPortableMarshaller.FLOAT:
 +            case GridPortableMarshaller.INT:
 +                len = 4;
 +
 +                break;
 +
 +            case GridPortableMarshaller.ENUM:
 +                //skipping type id and ordinal value
 +                len = 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.LONG:
 +            case GridPortableMarshaller.DOUBLE:
 +                len = 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.BYTE_ARR:
 +            case GridPortableMarshaller.BOOLEAN_ARR:
 +                len = 4 + readLength();
 +
 +                break;
 +
 +            case GridPortableMarshaller.STRING:
 +                len = 4 + readStringLength();
 +
 +                break;
 +
 +            case GridPortableMarshaller.DECIMAL:
 +                len = /** scale */ 4  + /** mag len */ 4  + /** mag bytes count */ readInt(4);
 +
 +                break;
 +
 +            case GridPortableMarshaller.UUID:
 +                len = 8 + 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.DATE:
 +                len = 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.TIMESTAMP:
 +                len = 8 + 4;
 +
 +                break;
 +
 +            case GridPortableMarshaller.CHAR_ARR:
 +            case GridPortableMarshaller.SHORT_ARR:
 +                len = 4 + readLength() * 2;
 +
 +                break;
 +
 +            case GridPortableMarshaller.INT_ARR:
 +            case GridPortableMarshaller.FLOAT_ARR:
 +                len = 4 + readLength() * 4;
 +
 +                break;
 +
 +            case GridPortableMarshaller.LONG_ARR:
 +            case GridPortableMarshaller.DOUBLE_ARR:
 +                len = 4 + readLength() * 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.DECIMAL_ARR:
 +            case GridPortableMarshaller.DATE_ARR:
 +            case GridPortableMarshaller.TIMESTAMP_ARR:
 +            case GridPortableMarshaller.OBJ_ARR:
 +            case GridPortableMarshaller.ENUM_ARR:
 +            case GridPortableMarshaller.UUID_ARR:
 +            case GridPortableMarshaller.STRING_ARR: {
 +                int size = readInt();
 +
 +                for (int i = 0; i < size; i++)
 +                    skipValue();
 +
 +                return;
 +            }
 +
 +            case GridPortableMarshaller.COL: {
 +                int size = readInt();
 +
 +                pos++; // skip collection type
 +
 +                for (int i = 0; i < size; i++)
 +                    skipValue();
 +
 +                return;
 +            }
 +
 +            case GridPortableMarshaller.MAP: {
 +                int size = readInt();
 +
 +                pos++; // skip collection type
 +
 +                for (int i = 0; i < size; i++) {
 +                    skipValue(); // skip key.
 +                    skipValue(); // skip value.
 +                }
 +
 +                return;
 +            }
 +
 +            case GridPortableMarshaller.PORTABLE_OBJ:
 +                len = readInt() + 4;
 +
 +                break;
 +
 +            default:
 +                throw new BinaryObjectException("Invalid flag value: " + type);
 +        }
 +
 +        pos += len;
 +    }
 +
 +    /**
 +     * @param pos Position.
 +     * @param len Length.
 +     * @return Object.
 +     */
 +    public Object getValueQuickly(int pos, int len) {
 +        byte type = arr[pos];
 +
 +        switch (type) {
 +            case GridPortableMarshaller.NULL:
 +                return null;
 +
 +            case GridPortableMarshaller.HANDLE: {
 +                int objStart = pos - readIntPositioned(pos + 1);
 +
 +                BinaryObjectBuilderImpl res = objMap.get(objStart);
 +
 +                if (res == null) {
 +                    res = new BinaryObjectBuilderImpl(new PortableBuilderReader(this, objStart), objStart);
 +
 +                    objMap.put(objStart, res);
 +                }
 +
 +                return res;
 +            }
 +
 +            case GridPortableMarshaller.OBJ: {
 +                BinaryObjectBuilderImpl res = objMap.get(pos);
 +
 +                if (res == null) {
 +                    res = new BinaryObjectBuilderImpl(new PortableBuilderReader(this, pos), pos);
 +
 +                    objMap.put(pos, res);
 +                }
 +
 +                return res;
 +            }
 +
 +            case GridPortableMarshaller.BYTE:
 +                return arr[pos + 1];
 +
 +            case GridPortableMarshaller.SHORT:
 +                return PortablePrimitives.readShort(arr, pos + 1);
 +
 +            case GridPortableMarshaller.INT:
 +                return PortablePrimitives.readInt(arr, pos + 1);
 +
 +            case GridPortableMarshaller.LONG:
 +                return PortablePrimitives.readLong(arr, pos + 1);
 +
 +            case GridPortableMarshaller.FLOAT:
 +                return PortablePrimitives.readFloat(arr, pos + 1);
 +
 +            case GridPortableMarshaller.DOUBLE:
 +                return PortablePrimitives.readDouble(arr, pos + 1);
 +
 +            case GridPortableMarshaller.CHAR:
 +                return PortablePrimitives.readChar(arr, pos + 1);
 +
 +            case GridPortableMarshaller.BOOLEAN:
 +                return arr[pos + 1] != 0;
 +
 +            case GridPortableMarshaller.DECIMAL:
 +            case GridPortableMarshaller.STRING:
 +            case GridPortableMarshaller.UUID:
 +            case GridPortableMarshaller.DATE:
 +            case GridPortableMarshaller.TIMESTAMP:
 +                return new PortablePlainLazyValue(this, pos, len);
 +
 +            case GridPortableMarshaller.BYTE_ARR:
 +            case GridPortableMarshaller.SHORT_ARR:
 +            case GridPortableMarshaller.INT_ARR:
 +            case GridPortableMarshaller.LONG_ARR:
 +            case GridPortableMarshaller.FLOAT_ARR:
 +            case GridPortableMarshaller.DOUBLE_ARR:
 +            case GridPortableMarshaller.CHAR_ARR:
 +            case GridPortableMarshaller.BOOLEAN_ARR:
 +            case GridPortableMarshaller.DECIMAL_ARR:
 +            case GridPortableMarshaller.DATE_ARR:
 +            case GridPortableMarshaller.TIMESTAMP_ARR:
 +            case GridPortableMarshaller.UUID_ARR:
 +            case GridPortableMarshaller.STRING_ARR:
 +            case GridPortableMarshaller.ENUM_ARR:
 +            case GridPortableMarshaller.OBJ_ARR:
 +            case GridPortableMarshaller.COL:
 +            case GridPortableMarshaller.MAP:
 +                return new LazyCollection(pos);
 +
 +            case GridPortableMarshaller.ENUM: {
 +                if (len == 1) {
 +                    assert readByte(pos) == GridPortableMarshaller.NULL;
 +
 +                    return null;
 +                }
 +
 +                int mark = position();
 +                position(pos + 1);
 +
 +                PortableBuilderEnum builderEnum = new PortableBuilderEnum(this);
 +
 +                position(mark);
 +
 +                return builderEnum;
 +            }
 +
 +            case GridPortableMarshaller.PORTABLE_OBJ: {
 +                int size = readIntPositioned(pos + 1);
 +
 +                int start = readIntPositioned(pos + 4 + size);
 +
 +                BinaryObjectImpl portableObj = new BinaryObjectImpl(ctx, arr, pos + 4 + start);
 +
 +                return new PortablePlainPortableObject(portableObj);
 +            }
 +
 +            default:
 +                throw new BinaryObjectException("Invalid flag value: " + type);
 +        }
 +    }
 +
 +    /**
 +     * @return Parsed value.
 +     */
 +    public Object parseValue() {
 +        int valPos = pos;
 +
 +        byte type = arr[pos++];
 +
 +        int plainLazyValLen;
 +
 +        boolean modifiableLazyVal = false;
 +
 +        switch (type) {
 +            case GridPortableMarshaller.NULL:
 +                return null;
 +
 +            case GridPortableMarshaller.HANDLE: {
 +                int objStart = pos - 1 - readInt();
 +
 +                BinaryObjectBuilderImpl res = objMap.get(objStart);
 +
 +                if (res == null) {
 +                    res = new BinaryObjectBuilderImpl(new PortableBuilderReader(this, objStart), objStart);
 +
 +                    objMap.put(objStart, res);
 +                }
 +
 +                return res;
 +            }
 +
 +            case GridPortableMarshaller.OBJ: {
 +                pos--;
 +
 +                BinaryObjectBuilderImpl res = objMap.get(pos);
 +
 +                if (res == null) {
 +                    res = new BinaryObjectBuilderImpl(new PortableBuilderReader(this, pos), pos);
 +
 +                    objMap.put(pos, res);
 +                }
 +
 +                pos += readInt(GridPortableMarshaller.TOTAL_LEN_POS);
 +
 +                return res;
 +            }
 +
 +            case GridPortableMarshaller.BYTE:
 +                return arr[pos++];
 +
 +            case GridPortableMarshaller.SHORT: {
 +                Object res = PortablePrimitives.readShort(arr, pos);
 +                pos += 2;
 +                return res;
 +            }
 +
 +            case GridPortableMarshaller.INT:
 +                return readInt();
 +
 +            case GridPortableMarshaller.LONG:
 +                plainLazyValLen = 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.FLOAT:
 +                plainLazyValLen = 4;
 +
 +                break;
 +
 +            case GridPortableMarshaller.DOUBLE:
 +                plainLazyValLen = 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.CHAR:
 +                plainLazyValLen = 2;
 +
 +                break;
 +
 +            case GridPortableMarshaller.BOOLEAN:
 +                return arr[pos++] != 0;
 +
 +            case GridPortableMarshaller.DECIMAL:
 +                plainLazyValLen = /** scale */ 4  + /** mag len */ 4  + /** mag bytes count */ readInt(4);
 +
 +                break;
 +
 +            case GridPortableMarshaller.STRING:
 +                plainLazyValLen = 4 + readStringLength();
 +
 +                break;
 +
 +            case GridPortableMarshaller.UUID:
 +                plainLazyValLen = 8 + 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.DATE:
 +                plainLazyValLen = 8;
 +
 +                break;
 +
 +            case GridPortableMarshaller.TIMESTAMP:
 +                plainLazyValLen = 8 + 4;
 +
 +                break;
 +
 +            case GridPortableMarshaller.BYTE_ARR:
 +                plainLazyValLen = 4 + readLength();
 +                modifiableLazyVal = true;
 +
 +                break;
 +
 +            case GridPortableMarshaller.SHORT_ARR:
 +                plainLazyValLen = 4 + readLength() * 2;
 +                modifiableLazyVal = true;
 +
 +                break;
 +
 +            case GridPortableMarshaller.INT_ARR:
 +                plainLazyValLen = 4 + readLength() * 4;
 +                modifiableLazyVal = true;
 +
 +                break;
 +
 +            case GridPortableMarshaller.LONG_ARR:
 +                plainLazyValLen = 4 + readLength() * 8;
 +                modifiableLazyVal = true;
 +
 +                break;
 +
 +            case GridPortableMarshaller.FLOAT_ARR:
 +                plainLazyValLen = 4 + readLength() * 4;
 +                modifiableLazyVal = true;
 +
 +                break;
 +
 +            case GridPortableMarshaller.DOUBLE_ARR:
 +                plainLazyValLen = 4 + readLength() * 8;
 +                modifiableLazyVal = true;
 +
 +                break;
 +
 +            case GridPortableMarshaller.CHAR_ARR:
 +                plainLazyValLen = 4 + readLength() * 2;
 +                modifiableLazyVal = true;
 +
 +                break;
 +
 +            case GridPortableMarshaller.BOOLEAN_ARR:
 +                plainLazyValLen = 4 + readLength();
 +                modifiableLazyVal = true;
 +
 +                break;
 +
 +            case GridPortableMarshaller.OBJ_ARR:
 +                return new PortableObjectArrayLazyValue(this);
 +
 +            case GridPortableMarshaller.DATE_ARR: {
 +                int size = readInt();
 +
 +                Date[] res = new Date[size];
 +
 +                for (int i = 0; i < res.length; i++) {
 +                    byte flag = arr[pos++];
 +
 +                    if (flag == GridPortableMarshaller.NULL) continue;
 +
 +                    if (flag != GridPortableMarshaller.DATE)
 +                        throw new BinaryObjectException("Invalid flag value: " + flag);
 +
 +                    long time = PortablePrimitives.readLong(arr, pos);
 +
 +                    pos += 8;
 +
 +                    res[i] = new Date(time);
 +                }
 +
 +                return res;
 +            }
 +
 +            case GridPortableMarshaller.TIMESTAMP_ARR: {
 +                int size = readInt();
 +
 +                Timestamp[] res = new Timestamp[size];
 +
 +                for (int i = 0; i < res.length; i++) {
 +                    byte flag = arr[pos++];
 +
 +                    if (flag == GridPortableMarshaller.NULL)
 +                        continue;
 +
 +                    if (flag != GridPortableMarshaller.TIMESTAMP)
 +                        throw new BinaryObjectException("Invalid flag value: " + flag);
 +
 +                    long time = PortablePrimitives.readLong(arr, pos);
 +
 +                    pos += 8;
 +
 +                    int nano = PortablePrimitives.readInt(arr, pos);
 +
 +                    pos += 4;
 +
 +                    Timestamp ts = new Timestamp(time);
 +
 +                    ts.setNanos(ts.getNanos() + nano);
 +
 +                    res[i] = ts;
 +                }
 +
 +                return res;
 +            }
 +
 +            case GridPortableMarshaller.UUID_ARR:
 +            case GridPortableMarshaller.STRING_ARR:
 +            case GridPortableMarshaller.DECIMAL_ARR: {
 +                int size = readInt();
 +
 +                for (int i = 0; i < size; i++) {
 +                    byte flag = arr[pos++];
 +
 +                    if (flag == GridPortableMarshaller.UUID)
 +                        pos += 8 + 8;
 +                    else if (flag == GridPortableMarshaller.STRING)
 +                        pos += 4 + readStringLength();
 +                    else if (flag == GridPortableMarshaller.DECIMAL) {
 +                        pos += 4; // scale value
 +                        pos += 4 + readLength();
 +                    }
 +                    else
 +                        assert flag == GridPortableMarshaller.NULL;
 +                }
 +
 +                return new PortableModifiableLazyValue(this, valPos, pos - valPos);
 +            }
 +
 +            case GridPortableMarshaller.COL: {
 +                int size = readInt();
 +                byte colType = arr[pos++];
 +
 +                switch (colType) {
 +                    case GridPortableMarshaller.USER_COL:
 +                    case GridPortableMarshaller.ARR_LIST:
 +                        return new PortableLazyArrayList(this, size);
 +
 +                    case GridPortableMarshaller.LINKED_LIST:
 +                        return new PortableLazyLinkedList(this, size);
 +
 +                    case GridPortableMarshaller.HASH_SET:
 +                    case GridPortableMarshaller.LINKED_HASH_SET:
 +                        return new PortableLazySet(this, size);
 +                }
 +
 +                throw new BinaryObjectException("Unknown collection type: " + colType);
 +            }
 +
 +            case GridPortableMarshaller.MAP:
 +                return PortableLazyMap.parseMap(this);
 +
 +            case GridPortableMarshaller.ENUM:
 +                return new PortableBuilderEnum(this);
 +
 +            case GridPortableMarshaller.ENUM_ARR:
 +                return new PortableEnumArrayLazyValue(this);
 +
 +            case GridPortableMarshaller.PORTABLE_OBJ: {
 +                int size = readInt();
 +
 +                pos += size;
 +
 +                int start = readInt();
 +
 +                BinaryObjectImpl portableObj = new BinaryObjectImpl(ctx, arr,
 +                    pos - 4 - size + start);
 +
 +                return new PortablePlainPortableObject(portableObj);
 +            }
 +
 +            default:
 +                throw new BinaryObjectException("Invalid flag value: " + type);
 +        }
 +
 +        PortableAbstractLazyValue res;
 +
 +        if (modifiableLazyVal)
 +            res = new PortableModifiableLazyValue(this, valPos, 1 + plainLazyValLen);
 +        else
 +            res = new PortablePlainLazyValue(this, valPos, 1 + plainLazyValLen);
 +
 +        pos += plainLazyValLen;
 +
 +        return res;
 +    }
 +
 +    /**
 +     * @return Array.
 +     */
 +    public byte[] array() {
 +        return arr;
 +    }
 +
 +    /**
 +     * @return Position of reader.
 +     */
 +    public int position() {
 +        return pos;
 +    }
 +
 +    /**
 +     * @param pos New pos.
 +     */
 +    public void position(int pos) {
 +        this.pos = pos;
 +    }
 +
 +    /**
 +     * @param n Number of bytes to skip.
 +     */
 +    public void skip(int n) {
 +        pos += n;
 +    }
 +
 +    /**
 +     * @return Reader.
 +     */
 +    BinaryReaderExImpl reader() {
 +        return reader;
 +    }
 +
 +    /**
 +     *
 +     */
 +    private class LazyCollection implements PortableLazyValue {
 +        /** */
 +        private final int valOff;
 +
 +        /** */
 +        private Object col;
 +
 +        /**
 +         * @param valOff Value.
 +         */
 +        protected LazyCollection(int valOff) {
 +            this.valOff = valOff;
 +        }
 +
 +        /**
 +         * @return Object.
 +         */
 +        private Object wrappedCollection() {
 +            if (col == null) {
 +                position(valOff);
 +
 +                col = parseValue();
 +            }
 +
 +            return col;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public void writeTo(BinaryWriterExImpl writer, PortableBuilderSerializer ctx) {
 +            ctx.writeValue(writer, wrappedCollection());
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public Object value() {
 +            return PortableUtils.unwrapLazy(wrappedCollection());
 +        }
 +    }
 +}