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 2014/12/05 00:24:10 UTC
[18/53] [abbrv] incubator-ignite git commit: # gg-9470-rename
# gg-9470-rename
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/a50fccdd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/a50fccdd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/a50fccdd
Branch: refs/heads/master
Commit: a50fccdda8e1c9fb8831182e097a1a917058c8b9
Parents: 580b2aa
Author: sboikov <sb...@gridgain.com>
Authored: Thu Dec 4 21:53:27 2014 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Thu Dec 4 21:53:32 2014 +0300
----------------------------------------------------------------------
examples/config/example-cache.xml | 2 +-
examples/config/example-compute.xml | 2 +-
examples/config/example-streamer.xml | 2 +-
examples/config/filesystem/example-ggfs.xml | 2 +-
.../MemcacheRestExampleNodeStartup.java | 2 +-
.../examples/misc/springbean/spring-bean.xml | 2 +-
.../GridOptimizedMarshallerAopTest.java | 1 +
.../java/org/apache/ignite/IgniteCompute.java | 3 +-
.../configuration/IgniteConfiguration.java | 3 +-
.../java/org/apache/ignite/lang/IgniteUuid.java | 2 +-
.../ignite/marshaller/GridMarshaller.java | 3 +-
.../marshaller/jdk/GridJdkMarshaller.java | 3 +-
.../optimized/GridOptimizedClassDescriptor.java | 1032 +++++++++++++++++
.../optimized/GridOptimizedClassResolver.java | 469 ++++++++
.../optimized/GridOptimizedFieldType.java | 42 +
.../optimized/GridOptimizedMarshallable.java | 57 +
.../optimized/GridOptimizedMarshaller.java | 408 +++++++
.../optimized/GridOptimizedMarshallerUtils.java | 450 ++++++++
.../GridOptimizedObjectInputStream.java | 1008 +++++++++++++++++
.../GridOptimizedObjectOutputStream.java | 831 ++++++++++++++
.../GridOptimizedObjectStreamRegistry.java | 215 ++++
.../GridClientOptimizedMarshaller.java | 4 +-
.../GridCacheRendezvousAffinityFunction.java | 2 +-
.../org/gridgain/grid/kernal/GridGainEx.java | 2 +-
.../org/gridgain/grid/kernal/GridKernal.java | 2 +-
.../org/gridgain/grid/kernal/GridTopic.java | 2 +-
.../deployment/GridDeploymentLocalStore.java | 2 +-
.../GridDeploymentPerLoaderStore.java | 2 +-
.../GridDeploymentPerVersionStore.java | 2 +-
.../affinity/GridAffinityMessage.java | 2 +-
.../processors/cache/GridCacheReturn.java | 2 +-
.../processors/cache/GridCacheTxEntry.java | 2 +-
.../processors/cache/GridCacheVersion.java | 2 +-
.../jdbc/GridCacheQueryJdbcMetadataTask.java | 2 +-
.../query/jdbc/GridCacheQueryJdbcTask.java | 2 +-
.../streamer/GridStreamerExecutionBatch.java | 2 +-
.../optimized/GridOptimizedClassDescriptor.java | 1035 ------------------
.../optimized/GridOptimizedClassResolver.java | 471 --------
.../optimized/GridOptimizedFieldType.java | 42 -
.../optimized/GridOptimizedMarshallable.java | 57 -
.../optimized/GridOptimizedMarshaller.java | 410 -------
.../optimized/GridOptimizedMarshallerUtils.java | 450 --------
.../GridOptimizedObjectInputStream.java | 1008 -----------------
.../GridOptimizedObjectOutputStream.java | 831 --------------
.../GridOptimizedObjectStreamRegistry.java | 215 ----
modules/core/src/test/config/example-cache.xml | 2 +-
modules/core/src/test/config/ggfs-loopback.xml | 2 +-
.../core/src/test/config/ggfs-no-endpoint.xml | 2 +-
modules/core/src/test/config/ggfs-shmem.xml | 2 +-
.../src/test/config/io-manager-benchmark.xml | 2 +-
modules/core/src/test/config/jobs-load-base.xml | 2 +-
.../core/src/test/config/load/dsi-load-base.xml | 2 +-
.../src/test/config/spring-start-nodes-attr.xml | 2 +-
.../core/src/test/config/spring-start-nodes.xml | 2 +-
.../grid/GridExternalizableAbstractTest.java | 2 +-
.../grid/ggfs/GridGgfsPathSelfTest.java | 2 +-
.../GridFailoverTaskWithPredicateSelfTest.java | 2 +-
.../kernal/GridJobMasterLeaveAwareSelfTest.java | 2 +-
.../grid/kernal/GridJobStealingSelfTest.java | 2 +-
.../grid/kernal/GridLifecycleAwareSelfTest.java | 2 +-
...ectionLocalJobMultipleArgumentsSelfTest.java | 2 +-
.../GridTaskExecutionContextSelfTest.java | 2 +-
.../managers/GridManagerStopSelfTest.java | 2 +-
.../cache/GridCacheAbstractSelfTest.java | 2 +-
.../cache/GridCacheAffinityRoutingSelfTest.java | 2 +-
.../cache/GridCacheDeploymentSelfTest.java | 2 +-
.../cache/GridCacheEntryMemorySizeSelfTest.java | 2 +-
.../cache/GridCacheMemoryModeSelfTest.java | 2 +-
.../cache/GridCacheOffHeapSelfTest.java | 2 +-
.../GridCacheReferenceCleanupSelfTest.java | 2 +-
.../GridCacheAbstractJobExecutionTest.java | 2 +-
.../GridCachePreloadLifecycleAbstractTest.java | 2 +-
.../near/GridCacheNearEvictionSelfTest.java | 2 +-
.../GridCacheSwapScanQueryAbstractSelfTest.java | 2 +-
...ridCacheContinuousQueryAbstractSelfTest.java | 2 +-
...dCacheAbstractReduceFieldsQuerySelfTest.java | 2 +-
.../closure/GridClosureProcessorSelfTest.java | 2 +-
.../continuous/GridEventConsumeSelfTest.java | 2 +-
.../dataload/GridDataLoaderImplSelfTest.java | 2 +-
.../GridDataLoaderProcessorSelfTest.java | 2 +-
.../ggfs/GridGgfsFileInfoSelfTest.java | 2 +-
.../streamer/GridStreamerEvictionSelfTest.java | 2 +-
.../streamer/GridStreamerSelfTest.java | 2 +-
.../marshaller/GridMarshallerAbstractTest.java | 2 +-
.../GridMarshallerPerformanceTest.java | 2 +-
.../GridOptimizedMarshallerEnumSelfTest.java | 1 +
.../GridOptimizedMarshallerSelfTest.java | 1 +
.../optimized/GridOptimizedMarshallerTest.java | 1 +
.../GridOptimizedObjectStreamSelfTest.java | 1 +
.../grid/messaging/GridMessagingSelfTest.java | 2 +-
.../grid/spi/GridTcpSpiForwardingSelfTest.java | 2 +-
...GridTcpDiscoveryMarshallerCheckSelfTest.java | 2 +-
.../util/future/GridFinishedFutureSelfTest.java | 2 +-
.../testframework/junits/GridAbstractTest.java | 2 +-
.../testframework/junits/GridTestResources.java | 2 +-
.../core/src/test/webapp/META-INF/gg-config.xml | 2 +-
.../child/GridHadoopExternalProcessStarter.java | 2 +-
...GridHadoopExternalCommunicationSelfTest.java | 2 +-
.../GridCacheAbstractFieldsQuerySelfTest.java | 2 +-
.../cache/GridCacheAbstractQuerySelfTest.java | 2 +-
.../cache/GridCacheCrossCacheQuerySelfTest.java | 2 +-
.../GridCacheQueryMultiThreadedSelfTest.java | 2 +-
...idCacheReduceQueryMultithreadedSelfTest.java | 2 +-
.../processors/cache/GridCacheSwapSelfTest.java | 2 +-
.../h2/opt/GridLuceneIndexLoadTest.java | 2 +-
.../h2indexing/GridH2IndexingSpiLoadTest.java | 2 +-
.../test/resources/spring-ping-pong-partner.xml | 2 +-
.../GridSpringBeanSerializationSelfTest.java | 2 +-
108 files changed, 4603 insertions(+), 4609 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/examples/config/example-cache.xml
----------------------------------------------------------------------
diff --git a/examples/config/example-cache.xml b/examples/config/example-cache.xml
index b9e95e2..f7024c0 100644
--- a/examples/config/example-cache.xml
+++ b/examples/config/example-cache.xml
@@ -36,7 +36,7 @@
<property name="peerClassLoadingEnabled" value="true"/>
<property name="marshaller">
- <bean class="org.gridgain.grid.marshaller.optimized.GridOptimizedMarshaller">
+ <bean class="org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller">
<!-- Set to false to allow non-serializable objects in examples, default is true. -->
<property name="requireSerializable" value="false"/>
</bean>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/examples/config/example-compute.xml
----------------------------------------------------------------------
diff --git a/examples/config/example-compute.xml b/examples/config/example-compute.xml
index 6173a46..ffd6b04 100644
--- a/examples/config/example-compute.xml
+++ b/examples/config/example-compute.xml
@@ -30,7 +30,7 @@
<property name="peerClassLoadingEnabled" value="true"/>
<property name="marshaller">
- <bean class="org.gridgain.grid.marshaller.optimized.GridOptimizedMarshaller">
+ <bean class="org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller">
<!-- Set to false to allow non-serializable objects in examples, default is true. -->
<property name="requireSerializable" value="false"/>
</bean>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/examples/config/example-streamer.xml
----------------------------------------------------------------------
diff --git a/examples/config/example-streamer.xml b/examples/config/example-streamer.xml
index eb86834..1c01e14 100644
--- a/examples/config/example-streamer.xml
+++ b/examples/config/example-streamer.xml
@@ -44,7 +44,7 @@
<property name="localHost" value="127.0.0.1"/>
<property name="marshaller">
- <bean class="org.gridgain.grid.marshaller.optimized.GridOptimizedMarshaller">
+ <bean class="org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller">
<!-- Set to false to allow non-serializable objects in examples, default is true. -->
<property name="requireSerializable" value="false"/>
</bean>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/examples/config/filesystem/example-ggfs.xml
----------------------------------------------------------------------
diff --git a/examples/config/filesystem/example-ggfs.xml b/examples/config/filesystem/example-ggfs.xml
index a709b9a..c33c806 100644
--- a/examples/config/filesystem/example-ggfs.xml
+++ b/examples/config/filesystem/example-ggfs.xml
@@ -54,7 +54,7 @@
<property name="peerClassLoadingEnabled" value="true"/>
<property name="marshaller">
- <bean class="org.gridgain.grid.marshaller.optimized.GridOptimizedMarshaller">
+ <bean class="org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller">
<!-- Set to false to allow non-serializable objects in examples, default is true. -->
<property name="requireSerializable" value="false"/>
</bean>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java b/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java
index ac3842a..8322759 100644
--- a/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java
+++ b/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java
@@ -11,9 +11,9 @@ package org.gridgain.examples.misc.client.memcache;
import org.apache.ignite.*;
import org.apache.ignite.configuration.*;
+import org.apache.ignite.marshaller.optimized.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
-import org.gridgain.grid.marshaller.optimized.*;
import org.gridgain.grid.spi.discovery.tcp.*;
import org.gridgain.grid.spi.discovery.tcp.ipfinder.vm.*;
import org.gridgain.grid.spi.indexing.h2.*;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/examples/src/main/java/org/gridgain/examples/misc/springbean/spring-bean.xml
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/gridgain/examples/misc/springbean/spring-bean.xml b/examples/src/main/java/org/gridgain/examples/misc/springbean/spring-bean.xml
index eba9308..23c562e 100644
--- a/examples/src/main/java/org/gridgain/examples/misc/springbean/spring-bean.xml
+++ b/examples/src/main/java/org/gridgain/examples/misc/springbean/spring-bean.xml
@@ -33,7 +33,7 @@
<property name="peerClassLoadingEnabled" value="true"/>
<property name="marshaller">
- <bean class="org.gridgain.grid.marshaller.optimized.GridOptimizedMarshaller">
+ <bean class="org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller">
<!-- Set to false to allow non-serializable objects in examples, default is true. -->
<property name="requireSerializable" value="false"/>
</bean>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/aop/src/test/java/org/gridgain/grid/marshaller/optimized/GridOptimizedMarshallerAopTest.java
----------------------------------------------------------------------
diff --git a/modules/aop/src/test/java/org/gridgain/grid/marshaller/optimized/GridOptimizedMarshallerAopTest.java b/modules/aop/src/test/java/org/gridgain/grid/marshaller/optimized/GridOptimizedMarshallerAopTest.java
index e63a929..80c596f 100644
--- a/modules/aop/src/test/java/org/gridgain/grid/marshaller/optimized/GridOptimizedMarshallerAopTest.java
+++ b/modules/aop/src/test/java/org/gridgain/grid/marshaller/optimized/GridOptimizedMarshallerAopTest.java
@@ -13,6 +13,7 @@ import org.apache.ignite.compute.gridify.*;
import org.apache.ignite.configuration.*;
import org.apache.ignite.events.*;
import org.apache.ignite.lang.*;
+import org.apache.ignite.marshaller.optimized.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.testframework.junits.common.*;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java b/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java
index 01d3800..4ea1d8a 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java
@@ -13,7 +13,6 @@ import org.apache.ignite.cluster.*;
import org.apache.ignite.compute.*;
import org.apache.ignite.lang.*;
import org.gridgain.grid.*;
-import org.gridgain.grid.marshaller.optimized.*;
import org.gridgain.grid.spi.failover.*;
import org.gridgain.grid.spi.loadbalancing.*;
import org.jetbrains.annotations.*;
@@ -47,7 +46,7 @@ import java.util.concurrent.*;
* not have any alive nodes), then {@link GridEmptyProjectionException} will be thrown out of result future.
* <h1 class="header">Serializable</h1>
* Also note that {@link Runnable} and {@link Callable} implementations must support serialization as required
- * by the configured marshaller. For example, {@link GridOptimizedMarshaller} requires {@link Serializable}
+ * by the configured marshaller. For example, {@link org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller} requires {@link Serializable}
* objects by default, but can be configured not to. Generally speaking objects that implement {@link Serializable}
* or {@link Externalizable} will perform better. For {@link Runnable} and {@link Callable} interfaces
* GridGain provides analogous {@link org.apache.ignite.lang.IgniteRunnable} and {@link org.apache.ignite.lang.IgniteCallable} classes which are
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index d7dc2c1..2254ffb 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -25,7 +25,6 @@ import org.gridgain.grid.dr.hub.sender.*;
import org.gridgain.grid.ggfs.*;
import org.gridgain.grid.hadoop.*;
import org.gridgain.grid.kernal.managers.eventstorage.*;
-import org.gridgain.grid.marshaller.optimized.*;
import org.gridgain.grid.portables.*;
import org.gridgain.grid.security.*;
import org.gridgain.grid.segmentation.*;
@@ -1455,7 +1454,7 @@ public class IgniteConfiguration {
/**
* Should return an instance of marshaller to use in grid. If not provided,
- * {@link GridOptimizedMarshaller} will be used on Java HotSpot VM, and
+ * {@link org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller} will be used on Java HotSpot VM, and
* {@link org.apache.ignite.marshaller.jdk.GridJdkMarshaller} will be used on other VMs.
*
* @return Marshaller to use in grid.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/lang/IgniteUuid.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/IgniteUuid.java b/modules/core/src/main/java/org/apache/ignite/lang/IgniteUuid.java
index 604ad36..5f02da9 100644
--- a/modules/core/src/main/java/org/apache/ignite/lang/IgniteUuid.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/IgniteUuid.java
@@ -9,7 +9,7 @@
package org.apache.ignite.lang;
-import org.gridgain.grid.marshaller.optimized.*;
+import org.apache.ignite.marshaller.optimized.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
import org.gridgain.grid.util.lang.*;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/marshaller/GridMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/GridMarshaller.java b/modules/core/src/main/java/org/apache/ignite/marshaller/GridMarshaller.java
index 9c8685f..d0b8826 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/GridMarshaller.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/GridMarshaller.java
@@ -10,7 +10,6 @@
package org.apache.ignite.marshaller;
import org.gridgain.grid.*;
-import org.gridgain.grid.marshaller.optimized.*;
import org.jetbrains.annotations.*;
import java.io.*;
@@ -22,7 +21,7 @@ import java.io.*;
* <p>
* Gridgain provides the following {@code GridMarshaller} implementations:
* <ul>
- * <li>{@link GridOptimizedMarshaller} - default</li>
+ * <li>{@link org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller} - default</li>
* <li>{@link org.apache.ignite.marshaller.jdk.GridJdkMarshaller}</li>
* </ul>
* <p>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/marshaller/jdk/GridJdkMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/jdk/GridJdkMarshaller.java b/modules/core/src/main/java/org/apache/ignite/marshaller/jdk/GridJdkMarshaller.java
index da75a2e..d0c3246 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/jdk/GridJdkMarshaller.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/jdk/GridJdkMarshaller.java
@@ -11,7 +11,6 @@ package org.apache.ignite.marshaller.jdk;
import org.apache.ignite.marshaller.*;
import org.gridgain.grid.*;
-import org.gridgain.grid.marshaller.optimized.*;
import org.gridgain.grid.util.typedef.internal.*;
import org.jetbrains.annotations.*;
@@ -24,7 +23,7 @@ import java.io.*;
* <h2 class="header">Mandatory</h2>
* This marshaller has no mandatory configuration parameters.
* <h2 class="header">Java Example</h2>
- * {@code GridJdkMarshaller} needs to be explicitly configured to override default {@link GridOptimizedMarshaller}.
+ * {@code GridJdkMarshaller} needs to be explicitly configured to override default {@link org.apache.ignite.marshaller.optimized.GridOptimizedMarshaller}.
* <pre name="code" class="java">
* GridJdkMarshaller marshaller = new GridJdkMarshaller();
*
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedClassDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedClassDescriptor.java
new file mode 100644
index 0000000..6384e3b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedClassDescriptor.java
@@ -0,0 +1,1032 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.marshaller.optimized;
+
+import org.apache.ignite.lang.*;
+import org.apache.ignite.marshaller.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.typedef.*;
+import sun.misc.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import static java.lang.reflect.Modifier.*;
+
+/**
+ * Class descriptor.
+ */
+class GridOptimizedClassDescriptor {
+ /** Unsafe. */
+ private static final Unsafe UNSAFE = GridUnsafe.unsafe();
+
+ /** */
+ private static final int TYPE_BYTE = 1;
+
+ /** */
+ private static final int TYPE_SHORT = 2;
+
+ /** */
+ private static final int TYPE_INT = 3;
+
+ /** */
+ private static final int TYPE_LONG = 4;
+
+ /** */
+ private static final int TYPE_FLOAT = 5;
+
+ /** */
+ private static final int TYPE_DOUBLE = 6;
+
+ /** */
+ private static final int TYPE_CHAR = 7;
+
+ /** */
+ private static final int TYPE_BOOLEAN = 8;
+
+ /** */
+ private static final int TYPE_BYTE_ARR = 9;
+
+ /** */
+ private static final int TYPE_SHORT_ARR = 10;
+
+ /** */
+ private static final int TYPE_INT_ARR = 11;
+
+ /** */
+ private static final int TYPE_LONG_ARR = 12;
+
+ /** */
+ private static final int TYPE_FLOAT_ARR = 13;
+
+ /** */
+ private static final int TYPE_DOUBLE_ARR = 14;
+
+ /** */
+ private static final int TYPE_CHAR_ARR = 15;
+
+ /** */
+ private static final int TYPE_BOOLEAN_ARR = 16;
+
+ /** */
+ private static final int TYPE_OBJ_ARR = 17;
+
+ /** */
+ private static final int TYPE_STR = 18;
+
+ /** */
+ private static final int TYPE_ENUM = 19;
+
+ /** */
+ private static final int TYPE_UUID = 20;
+
+ /** */
+ private static final int TYPE_PROPS = 21;
+
+ /** */
+ private static final int TYPE_ARRAY_LIST = 22;
+
+ /** */
+ private static final int TYPE_HASH_MAP = 23;
+
+ /** */
+ private static final int TYPE_HASH_SET = 24;
+
+ /** */
+ private static final int TYPE_LINKED_LIST = 25;
+
+ /** */
+ private static final int TYPE_LINKED_HASH_MAP = 26;
+
+ /** */
+ private static final int TYPE_LINKED_HASH_SET = 27;
+
+ /** */
+ private static final int TYPE_DATE = 28;
+
+ /** */
+ private static final int TYPE_CLS = 29;
+
+ /** */
+ private static final int TYPE_EXTERNALIZABLE = 50;
+
+ /** */
+ private static final int TYPE_SERIALIZABLE = 51;
+
+ /** Class. */
+ private Class<?> cls;
+
+ /** Header. */
+ private Integer hdr;
+
+ /** ID. */
+ private Integer id;
+
+ /** Short ID. */
+ private Short shortId;
+
+ /** Class name. */
+ private String name;
+
+ /** Class type. */
+ private int type;
+
+ /** Primitive flag. */
+ private boolean isPrimitive;
+
+ /** Enum flag. */
+ private boolean isEnum;
+
+ /** Serializable flag. */
+ private boolean isSerial;
+
+ /** Excluded flag. */
+ private final boolean excluded;
+
+ /** {@code True} if descriptor is for {@link Class}. */
+ private boolean isCls;
+
+ /** Array component type. */
+ private Class<?> arrCompType;
+
+ /** Enumeration values. */
+ private Object[] enumVals;
+
+ /** Constructor. */
+ private Constructor<?> constructor;
+
+ /** Fields. */
+ private Fields fields;
+
+ /** {@code writeObject} methods. */
+ private List<Method> writeObjMtds;
+
+ /** {@code writeReplace} method. */
+ private Method writeReplaceMtd;
+
+ /** {@code readObject} methods. */
+ private List<Method> readObjMtds;
+
+ /** {@code readResolve} method. */
+ private Method readResolveMtd;
+
+ /** Defaults field offset. */
+ private long dfltsFieldOff;
+
+ /** Load factor field offset. */
+ private long loadFactorFieldOff;
+
+ /** Map field offset. */
+ private long mapFieldOff;
+
+ /** Access order field offset. */
+ private long accessOrderFieldOff;
+
+ /**
+ * Creates descriptor for class.
+ *
+ * @param cls Class.
+ * @throws IOException In case of error.
+ */
+ @SuppressWarnings({"ForLoopReplaceableByForEach", "MapReplaceableByEnumMap"})
+ GridOptimizedClassDescriptor(Class<?> cls) throws IOException {
+ this.cls = cls;
+
+ excluded = GridMarshallerExclusions.isExcluded(cls);
+
+ T2<Integer, Integer> t = GridOptimizedClassResolver.writeClassData(cls);
+
+ hdr = t.get1();
+ id = t.get2();
+ name = cls.getName();
+
+ if (!excluded) {
+ Class<?> parent;
+
+ if (cls == byte.class || cls == Byte.class) {
+ type = TYPE_BYTE;
+
+ isPrimitive = true;
+ }
+ else if (cls == short.class || cls == Short.class) {
+ type = TYPE_SHORT;
+
+ isPrimitive = true;
+ }
+ else if (cls == int.class || cls == Integer.class) {
+ type = TYPE_INT;
+
+ isPrimitive = true;
+ }
+ else if (cls == long.class || cls == Long.class) {
+ type = TYPE_LONG;
+
+ isPrimitive = true;
+ }
+ else if (cls == float.class || cls == Float.class) {
+ type = TYPE_FLOAT;
+
+ isPrimitive = true;
+ }
+ else if (cls == double.class || cls == Double.class) {
+ type = TYPE_DOUBLE;
+
+ isPrimitive = true;
+ }
+ else if (cls == char.class || cls == Character.class) {
+ type = TYPE_CHAR;
+
+ isPrimitive = true;
+ }
+ else if (cls == boolean.class || cls == Boolean.class) {
+ type = TYPE_BOOLEAN;
+
+ isPrimitive = true;
+ }
+ else if (cls == byte[].class)
+ type = TYPE_BYTE_ARR;
+ else if (cls == short[].class)
+ type = TYPE_SHORT_ARR;
+ else if (cls == int[].class)
+ type = TYPE_INT_ARR;
+ else if (cls == long[].class)
+ type = TYPE_LONG_ARR;
+ else if (cls == float[].class)
+ type = TYPE_FLOAT_ARR;
+ else if (cls == double[].class)
+ type = TYPE_DOUBLE_ARR;
+ else if (cls == char[].class)
+ type = TYPE_CHAR_ARR;
+ else if (cls == boolean[].class)
+ type = TYPE_BOOLEAN_ARR;
+ else if (cls.isArray()) {
+ type = TYPE_OBJ_ARR;
+
+ arrCompType = cls.getComponentType();
+ }
+ else if (cls == String.class)
+ type = TYPE_STR;
+ else if (cls.isEnum()) {
+ type = TYPE_ENUM;
+
+ isEnum = true;
+ enumVals = cls.getEnumConstants();
+ }
+ // Support for enum constants, based on anonymous children classes.
+ else if ((parent = cls.getSuperclass()) != null && parent.isEnum()) {
+ type = TYPE_ENUM;
+
+ isEnum = true;
+ enumVals = parent.getEnumConstants();
+ }
+ else if (cls == UUID.class)
+ type = TYPE_UUID;
+ else if (cls == Properties.class) {
+ type = TYPE_PROPS;
+
+ try {
+ dfltsFieldOff = UNSAFE.objectFieldOffset(Properties.class.getDeclaredField("defaults"));
+ }
+ catch (NoSuchFieldException e) {
+ throw new IOException(e);
+ }
+ }
+ else if (cls == ArrayList.class)
+ type = TYPE_ARRAY_LIST;
+ else if (cls == HashMap.class) {
+ type = TYPE_HASH_MAP;
+
+ try {
+ loadFactorFieldOff = UNSAFE.objectFieldOffset(HashMap.class.getDeclaredField("loadFactor"));
+ }
+ catch (NoSuchFieldException e) {
+ throw new IOException(e);
+ }
+ }
+ else if (cls == HashSet.class) {
+ type = TYPE_HASH_SET;
+
+ try {
+ loadFactorFieldOff = UNSAFE.objectFieldOffset(HashMap.class.getDeclaredField("loadFactor"));
+ mapFieldOff = UNSAFE.objectFieldOffset(HashSet.class.getDeclaredField("map"));
+ }
+ catch (NoSuchFieldException e) {
+ throw new IOException(e);
+ }
+ }
+ else if (cls == LinkedList.class)
+ type = TYPE_LINKED_LIST;
+ else if (cls == LinkedHashMap.class) {
+ type = TYPE_LINKED_HASH_MAP;
+
+ try {
+ loadFactorFieldOff = UNSAFE.objectFieldOffset(HashMap.class.getDeclaredField("loadFactor"));
+ accessOrderFieldOff = UNSAFE.objectFieldOffset(LinkedHashMap.class.getDeclaredField("accessOrder"));
+ }
+ catch (NoSuchFieldException e) {
+ throw new IOException(e);
+ }
+ }
+ else if (cls == LinkedHashSet.class) {
+ type = TYPE_LINKED_HASH_SET;
+
+ try {
+ loadFactorFieldOff = UNSAFE.objectFieldOffset(HashMap.class.getDeclaredField("loadFactor"));
+ mapFieldOff = UNSAFE.objectFieldOffset(HashSet.class.getDeclaredField("map"));
+ }
+ catch (NoSuchFieldException e) {
+ throw new IOException(e);
+ }
+ }
+ else if (cls == Date.class)
+ type = TYPE_DATE;
+ else if (cls == Class.class) {
+ type = TYPE_CLS;
+
+ isCls = true;
+ }
+ else {
+ Class<?> c = cls;
+
+ while ((writeReplaceMtd == null || readResolveMtd == null) && c != null && !c.equals(Object.class)) {
+ if (writeReplaceMtd == null) {
+ try {
+ writeReplaceMtd = c.getDeclaredMethod("writeReplace");
+
+ if (!isStatic(writeReplaceMtd.getModifiers()) &&
+ !(isPrivate(writeReplaceMtd.getModifiers()) && c != cls) &&
+ writeReplaceMtd.getReturnType().equals(Object.class))
+ writeReplaceMtd.setAccessible(true);
+ else
+ // Set method back to null if it has incorrect signature.
+ writeReplaceMtd = null;
+ }
+ catch (NoSuchMethodException ignored) {
+ // No-op.
+ }
+ }
+
+ if (readResolveMtd == null) {
+ try {
+ readResolveMtd = c.getDeclaredMethod("readResolve");
+
+ if (!isStatic(readResolveMtd.getModifiers()) &&
+ !(isPrivate(readResolveMtd.getModifiers()) && c != cls) &&
+ readResolveMtd.getReturnType().equals(Object.class))
+ readResolveMtd.setAccessible(true);
+ else
+ // Set method back to null if it has incorrect signature.
+ readResolveMtd = null;
+ }
+ catch (NoSuchMethodException ignored) {
+ // No-op.
+ }
+ }
+
+ c = c.getSuperclass();
+ }
+
+ if (Externalizable.class.isAssignableFrom(cls)) {
+ type = TYPE_EXTERNALIZABLE;
+
+ try {
+ constructor = cls.getDeclaredConstructor();
+
+ constructor.setAccessible(true);
+ }
+ catch (NoSuchMethodException e) {
+ throw new IOException("Externalizable class doesn't have default constructor: " + cls, e);
+ }
+ }
+ else {
+ type = TYPE_SERIALIZABLE;
+
+ isSerial = Serializable.class.isAssignableFrom(cls);
+
+ writeObjMtds = new ArrayList<>();
+ readObjMtds = new ArrayList<>();
+ List<List<Field>> fields = new ArrayList<>();
+ List<List<T2<GridOptimizedFieldType, Long>>> fieldOffs = new ArrayList<>();
+ List<Map<String, IgniteBiTuple<Integer, GridOptimizedFieldType>>> fieldInfoMaps = new ArrayList<>();
+ List<List<IgniteBiTuple<Integer, GridOptimizedFieldType>>> fieldInfoLists = new ArrayList<>();
+
+ for (c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) {
+ Method mtd;
+
+ try {
+ mtd = c.getDeclaredMethod("writeObject", ObjectOutputStream.class);
+
+ int mod = mtd.getModifiers();
+
+ if (!isStatic(mod) && isPrivate(mod) && mtd.getReturnType() == Void.TYPE)
+ mtd.setAccessible(true);
+ else
+ // Set method back to null if it has incorrect signature.
+ mtd = null;
+ }
+ catch (NoSuchMethodException ignored) {
+ mtd = null;
+ }
+
+ writeObjMtds.add(mtd);
+
+ try {
+ mtd = c.getDeclaredMethod("readObject", ObjectInputStream.class);
+
+ int mod = mtd.getModifiers();
+
+ if (!isStatic(mod) && isPrivate(mod) && mtd.getReturnType() == Void.TYPE)
+ mtd.setAccessible(true);
+ else
+ // Set method back to null if it has incorrect signature.
+ mtd = null;
+ }
+ catch (NoSuchMethodException ignored) {
+ mtd = null;
+ }
+
+ readObjMtds.add(mtd);
+
+ Field[] clsFields0 = c.getDeclaredFields();
+
+ Arrays.sort(clsFields0, new Comparator<Field>() {
+ @Override public int compare(Field f1, Field f2) {
+ return f1.getName().compareTo(f2.getName());
+ }
+ });
+
+ List<Field> clsFields = new ArrayList<>(clsFields0.length);
+ List<T2<GridOptimizedFieldType, Long>> clsFieldOffs =
+ new ArrayList<>(clsFields0.length);
+
+ for (int i = 0; i < clsFields0.length; i++) {
+ Field f = clsFields0[i];
+
+ int mod = f.getModifiers();
+
+ if (!isStatic(mod) && !isTransient(mod)) {
+ GridOptimizedFieldType type = fieldType(f.getType());
+
+ clsFields.add(f);
+ clsFieldOffs.add(new T2<>(type, UNSAFE.objectFieldOffset(f)));
+ }
+ }
+
+ fields.add(clsFields);
+ fieldOffs.add(clsFieldOffs);
+
+ Map<String, IgniteBiTuple<Integer, GridOptimizedFieldType>> fieldInfoMap = null;
+
+ try {
+ Field serFieldsDesc = c.getDeclaredField("serialPersistentFields");
+
+ int mod = serFieldsDesc.getModifiers();
+
+ if (serFieldsDesc.getType() == ObjectStreamField[].class &&
+ isPrivate(mod) && isStatic(mod) && isFinal(mod)) {
+ serFieldsDesc.setAccessible(true);
+
+ ObjectStreamField[] serFields = (ObjectStreamField[])serFieldsDesc.get(null);
+
+ fieldInfoMap = new HashMap<>();
+
+ for (int i = 0; i < serFields.length; i++) {
+ ObjectStreamField serField = serFields[i];
+
+ fieldInfoMap.put(serField.getName(), F.t(i, fieldType(serField.getType())));
+ }
+ }
+ }
+ catch (NoSuchFieldException ignored) {
+ // No-op.
+ }
+ catch (IllegalAccessException e) {
+ throw new IOException("Failed to get value of 'serialPersistentFields' field in class: " +
+ cls.getName(), e);
+ }
+
+ if (fieldInfoMap == null) {
+ fieldInfoMap = new HashMap<>();
+
+ for (int i = 0; i < clsFields.size(); i++) {
+ Field f = clsFields.get(i);
+
+ fieldInfoMap.put(f.getName(), F.t(i, fieldType(f.getType())));
+ }
+ }
+
+ fieldInfoMaps.add(fieldInfoMap);
+
+ List<IgniteBiTuple<Integer, GridOptimizedFieldType>> fieldInfoList =
+ new ArrayList<>(fieldInfoMap.values());
+
+ Collections.sort(fieldInfoList, new Comparator<IgniteBiTuple<Integer, GridOptimizedFieldType>>() {
+ @Override public int compare(IgniteBiTuple<Integer, GridOptimizedFieldType> t1,
+ IgniteBiTuple<Integer, GridOptimizedFieldType> t2) {
+ return t1.get1().compareTo(t2.get1());
+ }
+ });
+
+ fieldInfoLists.add(fieldInfoList);
+ }
+
+ Collections.reverse(writeObjMtds);
+ Collections.reverse(readObjMtds);
+ Collections.reverse(fields);
+ Collections.reverse(fieldOffs);
+ Collections.reverse(fieldInfoMaps);
+ Collections.reverse(fieldInfoLists);
+
+ this.fields = new Fields(fields, fieldOffs, fieldInfoLists, fieldInfoMaps);
+ }
+ }
+ }
+
+ shortId = GridOptimizedMarshallerUtils.computeSerialVersionUid(cls, fields != null ? fields.ownFields() : null).shortValue();
+ }
+
+ /**
+ * @return Excluded flag.
+ */
+ boolean excluded() {
+ return excluded;
+ }
+
+ /**
+ * @return Class.
+ */
+ Class<?> describedClass() {
+ return cls;
+ }
+
+ /**
+ * @return Header.
+ */
+ Integer header() {
+ return hdr;
+ }
+
+ /**
+ * @return ID.
+ */
+ Integer id() {
+ return id;
+ }
+
+ /**
+ * @return Short ID.
+ */
+ Short shortId() {
+ return shortId;
+ }
+
+ /**
+ * @return Class name.
+ */
+ String name() {
+ return name;
+ }
+
+ /**
+ * @return Array component type.
+ */
+ Class<?> componentType() {
+ return arrCompType;
+ }
+
+ /**
+ * @return Primitive flag.
+ */
+ boolean isPrimitive() {
+ return isPrimitive;
+ }
+
+ /**
+ * @return Enum flag.
+ */
+ boolean isEnum() {
+ return isEnum;
+ }
+
+ /**
+ * @return {@code True} if descriptor is for {@link Class}.
+ */
+ boolean isClass() {
+ return isCls;
+ }
+
+ /**
+ * Replaces object.
+ *
+ * @param obj Object.
+ * @return Replaced object or {@code null} if there is no {@code writeReplace} method.
+ * @throws IOException In case of error.
+ */
+ Object replace(Object obj) throws IOException {
+ if (writeReplaceMtd != null) {
+ try {
+ return writeReplaceMtd.invoke(obj);
+ }
+ catch (IllegalAccessException | InvocationTargetException e) {
+ throw new IOException(e);
+ }
+ }
+
+ return obj;
+ }
+
+ /**
+ * Writes object to stream.
+ *
+ * @param out Output stream.
+ * @param obj Object.
+ * @throws IOException In case of error.
+ */
+ @SuppressWarnings("ForLoopReplaceableByForEach")
+ void write(GridOptimizedObjectOutputStream out, Object obj) throws IOException {
+ switch (type) {
+ case TYPE_BYTE:
+ out.writeByte((Byte)obj);
+
+ break;
+
+ case TYPE_SHORT:
+ out.writeShort((Short)obj);
+
+ break;
+
+ case TYPE_INT:
+ out.writeInt((Integer)obj);
+
+ break;
+
+ case TYPE_LONG:
+ out.writeLong((Long)obj);
+
+ break;
+
+ case TYPE_FLOAT:
+ out.writeFloat((Float)obj);
+
+ break;
+
+ case TYPE_DOUBLE:
+ out.writeDouble((Double)obj);
+
+ break;
+
+ case TYPE_CHAR:
+ out.writeChar((Character)obj);
+
+ break;
+
+ case TYPE_BOOLEAN:
+ out.writeBoolean((Boolean)obj);
+
+ break;
+
+ case TYPE_BYTE_ARR:
+ out.writeByteArray((byte[])obj);
+
+ break;
+
+ case TYPE_SHORT_ARR:
+ out.writeShortArray((short[])obj);
+
+ break;
+
+ case TYPE_INT_ARR:
+ out.writeIntArray((int[])obj);
+
+ break;
+
+ case TYPE_LONG_ARR:
+ out.writeLongArray((long[])obj);
+
+ break;
+
+ case TYPE_FLOAT_ARR:
+ out.writeFloatArray((float[])obj);
+
+ break;
+
+ case TYPE_DOUBLE_ARR:
+ out.writeDoubleArray((double[])obj);
+
+ break;
+
+ case TYPE_CHAR_ARR:
+ out.writeCharArray((char[])obj);
+
+ break;
+
+ case TYPE_BOOLEAN_ARR:
+ out.writeBooleanArray((boolean[])obj);
+
+ break;
+
+ case TYPE_OBJ_ARR:
+ out.writeArray((Object[])obj);
+
+ break;
+
+ case TYPE_STR:
+ out.writeString((String)obj);
+
+ break;
+
+ case TYPE_ENUM:
+ out.writeInt(((Enum)obj).ordinal());
+
+ break;
+
+ case TYPE_UUID:
+ out.writeUuid((UUID)obj);
+
+ break;
+
+ case TYPE_PROPS:
+ out.writeProperties((Properties)obj, dfltsFieldOff);
+
+ break;
+
+ case TYPE_ARRAY_LIST:
+ out.writeArrayList((ArrayList<?>)obj);
+
+ break;
+
+ case TYPE_HASH_MAP:
+ out.writeHashMap((HashMap<?, ?>)obj, loadFactorFieldOff, false);
+
+ break;
+
+ case TYPE_HASH_SET:
+ out.writeHashSet((HashSet<?>)obj, mapFieldOff, loadFactorFieldOff);
+
+ break;
+
+ case TYPE_LINKED_LIST:
+ out.writeLinkedList((LinkedList<?>)obj);
+
+ break;
+
+ case TYPE_LINKED_HASH_MAP:
+ out.writeLinkedHashMap((LinkedHashMap<?, ?>)obj, loadFactorFieldOff, accessOrderFieldOff, false);
+
+ break;
+
+ case TYPE_LINKED_HASH_SET:
+ out.writeLinkedHashSet((LinkedHashSet<?>)obj, mapFieldOff, loadFactorFieldOff);
+
+ break;
+
+ case TYPE_DATE:
+ out.writeDate((Date)obj);
+
+ break;
+
+ case TYPE_CLS:
+ GridOptimizedClassResolver.writeClass(out, GridOptimizedMarshallerUtils.classDescriptor((Class<?>) obj, obj));
+
+ break;
+
+ case TYPE_EXTERNALIZABLE:
+ out.writeExternalizable(obj);
+
+ break;
+
+ case TYPE_SERIALIZABLE:
+ if (out.requireSerializable() && !isSerial)
+ throw new NotSerializableException("Must implement java.io.Serializable or " +
+ "set GridOptimizedMarshaller.setRequireSerializable() to false " +
+ "(note that performance may degrade if object is not Serializable): " + name);
+
+ out.writeSerializable(obj, writeObjMtds, fields);
+
+ break;
+
+ default:
+ throw new IllegalStateException("Invalid class type: " + type);
+ }
+ }
+
+ /**
+ * Reads object from stream.
+ *
+ * @param in Input stream.
+ * @return Object.
+ * @throws ClassNotFoundException If class not found.
+ * @throws IOException In case of error.
+ */
+ Object read(GridOptimizedObjectInputStream in) throws ClassNotFoundException, IOException {
+ switch (type) {
+ case TYPE_BYTE:
+ return in.readByte();
+
+ case TYPE_SHORT:
+ return in.readShort();
+
+ case TYPE_INT:
+ return in.readInt();
+
+ case TYPE_LONG:
+ return in.readLong();
+
+ case TYPE_FLOAT:
+ return in.readFloat();
+
+ case TYPE_DOUBLE:
+ return in.readDouble();
+
+ case TYPE_CHAR:
+ return in.readChar();
+
+ case TYPE_BOOLEAN:
+ return in.readBoolean();
+
+ case TYPE_BYTE_ARR:
+ return in.readByteArray();
+
+ case TYPE_SHORT_ARR:
+ return in.readShortArray();
+
+ case TYPE_INT_ARR:
+ return in.readIntArray();
+
+ case TYPE_LONG_ARR:
+ return in.readLongArray();
+
+ case TYPE_FLOAT_ARR:
+ return in.readFloatArray();
+
+ case TYPE_DOUBLE_ARR:
+ return in.readDoubleArray();
+
+ case TYPE_CHAR_ARR:
+ return in.readCharArray();
+
+ case TYPE_BOOLEAN_ARR:
+ return in.readBooleanArray();
+
+ case TYPE_OBJ_ARR:
+ return in.readArray(arrCompType);
+
+ case TYPE_STR:
+ return in.readString();
+
+ case TYPE_ENUM:
+ return enumVals[in.readInt()];
+
+ case TYPE_UUID:
+ return in.readUuid();
+
+ case TYPE_PROPS:
+ return in.readProperties();
+
+ case TYPE_ARRAY_LIST:
+ return in.readArrayList();
+
+ case TYPE_HASH_MAP:
+ return in.readHashMap(false);
+
+ case TYPE_HASH_SET:
+ return in.readHashSet(mapFieldOff);
+
+ case TYPE_LINKED_LIST:
+ return in.readLinkedList();
+
+ case TYPE_LINKED_HASH_MAP:
+ return in.readLinkedHashMap(false);
+
+ case TYPE_LINKED_HASH_SET:
+ return in.readLinkedHashSet(mapFieldOff);
+
+ case TYPE_DATE:
+ return in.readDate();
+
+ case TYPE_CLS:
+ return GridOptimizedClassResolver.readClass(in, in.classLoader()).describedClass();
+
+ case TYPE_EXTERNALIZABLE:
+ return in.readExternalizable(constructor, readResolveMtd);
+
+ case TYPE_SERIALIZABLE:
+ return in.readSerializable(cls, readObjMtds, readResolveMtd, fields);
+
+ default:
+ throw new IllegalStateException("Invalid class type: " + type);
+ }
+ }
+
+ /**
+ * @param cls Class.
+ * @return Type.
+ */
+ @SuppressWarnings("IfMayBeConditional")
+ private GridOptimizedFieldType fieldType(Class<?> cls) {
+ GridOptimizedFieldType type;
+
+ if (cls == byte.class)
+ type = GridOptimizedFieldType.BYTE;
+ else if (cls == short.class)
+ type = GridOptimizedFieldType.SHORT;
+ else if (cls == int.class)
+ type = GridOptimizedFieldType.INT;
+ else if (cls == long.class)
+ type = GridOptimizedFieldType.LONG;
+ else if (cls == float.class)
+ type = GridOptimizedFieldType.FLOAT;
+ else if (cls == double.class)
+ type = GridOptimizedFieldType.DOUBLE;
+ else if (cls == char.class)
+ type = GridOptimizedFieldType.CHAR;
+ else if (cls == boolean.class)
+ type = GridOptimizedFieldType.BOOLEAN;
+ else
+ type = GridOptimizedFieldType.OTHER;
+
+ return type;
+ }
+
+ /**
+ * Encapsulates data about class fields.
+ */
+ @SuppressWarnings("PackageVisibleInnerClass")
+ static class Fields {
+ /** Fields. */
+ private final List<List<Field>> fields;
+
+ /** Fields offsets. */
+ private final List<List<T2<GridOptimizedFieldType, Long>>> fieldOffs;
+
+ /** Fields details lists. */
+ private final List<List<IgniteBiTuple<Integer, GridOptimizedFieldType>>> fieldInfoLists;
+
+ /** Fields details maps. */
+ private final List<Map<String, IgniteBiTuple<Integer, GridOptimizedFieldType>>> fieldInfoMaps;
+
+ /**
+ * Creates new instance.
+ *
+ * @param fields Fields.
+ * @param fieldOffs Field offsets.
+ * @param fieldInfoLists List of field details sequences for each type in the object's class hierarchy.
+ * @param fieldInfoMaps List of field details maps for each type in the object's class hierarchy.
+ */
+ Fields(List<List<Field>> fields, List<List<T2<GridOptimizedFieldType, Long>>> fieldOffs,
+ List<List<IgniteBiTuple<Integer, GridOptimizedFieldType>>> fieldInfoLists,
+ List<Map<String, IgniteBiTuple<Integer, GridOptimizedFieldType>>> fieldInfoMaps) {
+ this.fields = fields;
+ this.fieldOffs = fieldOffs;
+ this.fieldInfoLists = fieldInfoLists;
+ this.fieldInfoMaps = fieldInfoMaps;
+ }
+
+ /**
+ * Returns class's own fields (excluding inherited).
+ *
+ * @return List of fields or {@code null} if fields list is empty.
+ */
+ List<Field> ownFields() {
+ return fields.isEmpty() ? null : fields.get(fields.size() - 1);
+ }
+
+ /**
+ * Returns field types and their offsets.
+ *
+ * @param i hierarchy level where 0 corresponds to top level.
+ * @return list of pairs where first value is field type and second value is its offset.
+ */
+ List<T2<GridOptimizedFieldType, Long>> fieldOffs(int i) {
+ return fieldOffs.get(i);
+ }
+
+ /**
+ * Returns field sequence numbers and their types as list.
+ *
+ * @param i hierarchy level where 0 corresponds to top level.
+ * @return list of pairs (field number, field type) for the given hierarchy level.
+ */
+ List<IgniteBiTuple<Integer, GridOptimizedFieldType>> fieldInfoList(int i) {
+ return fieldInfoLists.get(i);
+ }
+
+ /**
+ * Returns field sequence numbers and their types as map where key is a field name,
+ *
+ * @param i hierarchy level where 0 corresponds to top level.
+ * @return map of field names and their details.
+ */
+ Map<String, IgniteBiTuple<Integer, GridOptimizedFieldType>> fieldInfoMap(int i) {
+ return fieldInfoMaps.get(i);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedClassResolver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedClassResolver.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedClassResolver.java
new file mode 100644
index 0000000..7b21ebe
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedClassResolver.java
@@ -0,0 +1,469 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.marshaller.optimized;
+
+import org.apache.ignite.lang.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.jdk8.backport.*;
+import org.jetbrains.annotations.*;
+
+import java.io.*;
+import java.math.*;
+import java.sql.*;
+import java.util.*;
+import java.util.Date;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.*;
+
+/**
+ * Resolves class names by serialVersionUID.
+ */
+@SuppressWarnings({"UnnecessaryFullyQualifiedName", "unchecked"})
+class GridOptimizedClassResolver {
+ /** File name to generate. */
+ private static final String FILE_NAME = "optimized-classnames.properties";
+
+ /** */
+ private static final Map<String, Integer> ggxName2id = new HashMap<>();
+
+ /** */
+ private static final T2<Class<?>, GridOptimizedClassDescriptor>[] ggxId2name;
+
+ /** */
+ private static final Map<String, Integer> ggName2id = new HashMap<>();
+
+ /** */
+ private static final T3<String, Class<?>, GridOptimizedClassDescriptor>[] ggId2name;
+
+ /** */
+ private static Map<String, Integer> usrName2Id;
+
+ /** */
+ private static T3<String, Class<?>, GridOptimizedClassDescriptor>[] usrId2Name;
+
+ /** */
+ private static final int HEADER_NAME = 255;
+
+ /** */
+ private static final int HEADER_GG_NAME = 254;
+
+ /** */
+ private static final int HEADER_USER_NAME = 253;
+
+ /** */
+ private static final int HEADER_ARRAY = 252;
+
+ /**
+ * Initialize predefined classes to optimize.
+ */
+ static {
+ Class[] superOptCls = new Class[] {
+ // Array types.
+ byte[].class,
+ short[].class,
+ int[].class,
+ long[].class,
+ float[].class,
+ double[].class,
+ boolean[].class,
+ char[].class,
+
+ // Boxed types.
+ Byte.class,
+ Short.class,
+ Integer.class,
+ Long.class,
+ Float.class,
+ Double.class,
+ Boolean.class,
+ Character.class,
+ String.class,
+
+ // Atomic.
+ AtomicBoolean.class,AtomicInteger.class,
+ AtomicLong.class,AtomicReference.class,
+ AtomicMarkableReference.class,
+ AtomicStampedReference.class,
+ AtomicIntegerArray.class,
+ AtomicReferenceArray.class,
+
+ // Concurrent types.
+ ConcurrentHashMap.class,
+ ConcurrentLinkedQueue.class,
+ ConcurrentSkipListMap.class,
+ ConcurrentSkipListSet.class,
+ LinkedBlockingDeque.class,
+ LinkedBlockingQueue.class,
+ PriorityBlockingQueue.class,
+ CopyOnWriteArrayList.class,
+ CopyOnWriteArraySet.class,
+
+ // Locks.
+ ReentrantLock.class,
+ ReentrantReadWriteLock.class,
+ ReentrantReadWriteLock.ReadLock.class,
+ ReentrantReadWriteLock.WriteLock.class,
+
+ // Util types.
+ Date.class,
+ UUID.class,
+ Calendar.class,
+ Random.class,
+ Calendar.class,
+ Currency.class,
+ ArrayList.class,
+ LinkedList.class,
+ Stack.class,
+ Vector.class,
+ HashMap.class,
+ HashSet.class,
+ Hashtable.class,
+ TreeMap.class,
+ TreeSet.class,
+ IdentityHashMap.class,
+ LinkedHashMap.class,
+ LinkedHashSet.class,
+ ArrayDeque.class,
+ BitSet.class,
+ EnumMap.class,
+ EnumSet.class,
+
+ // SQL types.
+ java.sql.Date.class,
+ Time.class,
+ Timestamp.class,
+
+ // Math types.
+ BigDecimal.class,
+ BigInteger.class,
+
+ // GridGain types.
+ IgniteUuid.class,
+ GridBoundedConcurrentOrderedSet.class,
+ GridBoundedLinkedHashSet.class,
+ GridConcurrentHashSet.class,
+ ConcurrentLinkedDeque8.class,
+ GridConcurrentPhantomHashSet.class,
+ GridConcurrentSkipListSet.class,
+ GridConcurrentWeakHashSet.class,
+ GridIdentityHashSet.class,
+ GridLeanSet.class,
+ GridSetWrapper.class
+ };
+
+ // Have to leave a range for special purposes.
+ assert superOptCls.length < 230;
+
+ ggxId2name = new T2[superOptCls.length];
+
+ for (int i = 0; i < superOptCls.length; i++) {
+ Class cls = superOptCls[i];
+
+ ggxName2id.put(cls.getName(), i);
+ ggxId2name[i] = new T2<Class<?>, GridOptimizedClassDescriptor>(cls, null);
+ }
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ GridOptimizedClassResolver.class.getResourceAsStream(FILE_NAME),
+ GridOptimizedMarshallerUtils.UTF_8));
+
+ List<T3<String, Class<?>, GridOptimizedClassDescriptor>> ggId2name0 =
+ new LinkedList<>();
+
+ try {
+ for (int i = 0; ; i++) {
+ String clsName = reader.readLine();
+
+ if (clsName == null)
+ break;
+
+ ggName2id.put(clsName, i);
+ ggId2name0.add(new T3<String, Class<?>, GridOptimizedClassDescriptor>(clsName, null, null));
+ }
+
+ ggId2name = ggId2name0.toArray(new T3[ggId2name0.size()]);
+ }
+ catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ finally {
+ U.close(reader, null);
+ }
+ }
+
+ /**
+ * Ensure singleton.
+ */
+ private GridOptimizedClassResolver() {
+ // No-op.
+ }
+
+ /**
+ * @param usrName2id0 From name to ID.
+ * @param usrId2Name0 From ID to name.
+ */
+ static void userClasses(@Nullable Map<String, Integer> usrName2id0,
+ @Nullable T3<String, Class<?>, GridOptimizedClassDescriptor>[] usrId2Name0) {
+ usrName2Id = usrName2id0;
+ usrId2Name = usrId2Name0;
+ }
+
+ /**
+ * @param in DataInput to read from.
+ * @param clsLdr ClassLoader.
+ * @return Class descriptor.
+ * @throws IOException If serial version UID failed.
+ * @throws ClassNotFoundException If the class cannot be located by the specified class loader.
+ */
+ static GridOptimizedClassDescriptor readClass(DataInput in, ClassLoader clsLdr)
+ throws IOException, ClassNotFoundException {
+ assert in != null;
+ assert clsLdr != null;
+
+ int hdr = in.readByte() & 0xff;
+
+ if (hdr < ggxId2name.length) {
+ T2<Class<?>, GridOptimizedClassDescriptor> ggxT = ggxId2name[hdr];
+
+ GridOptimizedClassDescriptor desc = ggxT.get2();
+
+ if (desc == null) {
+ desc = GridOptimizedMarshallerUtils.classDescriptor(ggxT.get1(), null);
+
+ ggxT.set2(desc);
+ }
+
+ return desc;
+ }
+
+ String name;
+ Class<?> cls;
+ GridOptimizedClassDescriptor desc;
+
+ switch (hdr) {
+ case HEADER_GG_NAME:
+ int ggId = in.readInt();
+
+ T3<String, Class<?>, GridOptimizedClassDescriptor> ggT;
+
+ try {
+ ggT = ggId2name[ggId];
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ throw new ClassNotFoundException("Failed to find optimized class ID " +
+ "(is same GridGain version running on all nodes?): " + ggId, e);
+ }
+
+ name = ggT.get1();
+ cls = ggT.get2();
+ desc = ggT.get3();
+
+ if (desc == null) {
+ if (clsLdr == U.gridClassLoader()) {
+ if (cls == null) {
+ cls = forName(name, clsLdr);
+
+ ggT.set2(cls);
+ }
+
+ desc = GridOptimizedMarshallerUtils.classDescriptor(cls, null);
+
+ ggT.set3(desc);
+ }
+ else {
+ cls = forName(name, clsLdr);
+
+ desc = GridOptimizedMarshallerUtils.classDescriptor(cls, null);
+ }
+ }
+
+ break;
+
+ case HEADER_USER_NAME:
+ int usrId = in.readInt();
+
+ T3<String, Class<?>, GridOptimizedClassDescriptor> usrT;
+
+ try {
+ if (usrId2Name != null)
+ usrT = usrId2Name[usrId];
+ else
+ throw new ClassNotFoundException("Failed to find user defined class ID " +
+ "(make sure to register identical classes on all nodes for optimization): " + usrId);
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ throw new ClassNotFoundException("Failed to find user defined class ID " +
+ "(make sure to register identical classes on all nodes for optimization): " + usrId, e);
+ }
+
+ name = usrT.get1();
+ cls = usrT.get2();
+ desc = usrT.get3();
+
+ if (desc == null) {
+ if (cls == null) {
+ cls = forName(name, clsLdr);
+
+ usrT.set2(cls);
+ }
+
+ desc = GridOptimizedMarshallerUtils.classDescriptor(cls, null);
+
+ usrT.set3(desc);
+ }
+
+ break;
+
+ case HEADER_ARRAY:
+ name = readClass(in, clsLdr).name();
+
+ name = name.charAt(0) == '[' ? "[" + name : "[L" + name + ';';
+
+ cls = forName(name, clsLdr);
+
+ return GridOptimizedMarshallerUtils.classDescriptor(cls, null);
+
+ case HEADER_NAME:
+ name = in.readUTF();
+
+ cls = forName(name, clsLdr);
+
+ desc = GridOptimizedMarshallerUtils.classDescriptor(cls, null);
+
+ break;
+
+ default:
+ throw new IOException("Unexpected optimized stream header: " + hdr);
+ }
+
+ short actual = desc.shortId();
+
+ short exp = in.readShort();
+
+ if (actual != exp)
+ throw new ClassNotFoundException("Optimized stream class checksum mismatch " +
+ "(is same version of marshalled class present on all nodes?) " +
+ "[expected=" + exp + ", actual=" + actual + ", cls=" + cls + ']');
+
+ return desc;
+ }
+
+ /**
+ * @param out Output.
+ * @param desc Class descriptor.
+ * @throws IOException In case of error.
+ */
+ static void writeClass(DataOutput out, GridOptimizedClassDescriptor desc) throws IOException {
+ assert out != null;
+ assert desc != null;
+
+ int hdr = desc.header();
+
+ out.writeByte(hdr);
+
+ switch (hdr) {
+ case HEADER_GG_NAME:
+ case HEADER_USER_NAME:
+ out.writeInt(desc.id());
+ out.writeShort(desc.shortId());
+
+ return;
+
+ case HEADER_ARRAY:
+ writeClass(out, GridOptimizedMarshallerUtils.classDescriptor(desc.componentType(), null));
+
+ return;
+
+ case HEADER_NAME:
+ out.writeUTF(desc.name());
+ out.writeShort(desc.shortId());
+ }
+ }
+
+ /**
+ * @param cls Class to write.
+ * @return Data for {@code writeClass} method.
+ */
+ static T2<Integer, Integer> writeClassData(Class<?> cls) {
+ assert cls != null;
+
+ String name = cls.getName();
+
+ Integer superHdr = ggxName2id.get(name);
+
+ if (superHdr != null)
+ return new T2<>(superHdr, null);
+
+ Integer id;
+
+ if ((id = ggName2id.get(name)) != null)
+ return new T2<>(HEADER_GG_NAME, id);
+
+ if (usrName2Id != null && (id = usrName2Id.get(name)) != null)
+ return new T2<>(HEADER_USER_NAME, id);
+
+ if (cls.isArray())
+ return new T2<>(HEADER_ARRAY, null);
+
+ return new T2<>(HEADER_NAME, null);
+ }
+
+ /**
+ * @param name Class name.
+ * @param ldr Class loader.
+ * @return Class.
+ * @throws ClassNotFoundException If class not found.
+ */
+ private static Class<?> forName(String name, ClassLoader ldr) throws ClassNotFoundException {
+ Class<?> cls = primitive(name);
+
+ if (cls == null)
+ cls = GridOptimizedMarshallerUtils.forName(name, ldr);
+
+ return cls;
+ }
+
+ /**
+ * @param name Name of primitive class.
+ * @return Primitive type class or null.
+ */
+ @SuppressWarnings("TypeMayBeWeakened")
+ @Nullable private static Class<?> primitive(String name) {
+ if (name.length() > 7)
+ return null;
+
+ switch (name.charAt(0)) {
+ case 'b':
+ if ("boolean".equals(name))
+ return boolean.class;
+
+ return "byte".equals(name) ? byte.class : null;
+ case 's':
+ return "short".equals(name) ? short.class : null;
+ case 'i':
+ return "int".equals(name) ? int.class : null;
+ case 'l':
+ return "long".equals(name) ? long.class : null;
+ case 'c':
+ return "char".equals(name) ? char.class : null;
+ case 'f':
+ return "float".equals(name) ? float.class : null;
+ case 'd':
+ return "double".equals(name) ? double.class : null;
+ case 'v':
+ return "void".equals(name) ? void.class : null;
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedFieldType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedFieldType.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedFieldType.java
new file mode 100644
index 0000000..f080a87
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedFieldType.java
@@ -0,0 +1,42 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.marshaller.optimized;
+
+/**
+ * Field type used to calculate {@code Unsafe} offsets into objects.
+ */
+enum GridOptimizedFieldType {
+ /** */
+ BYTE,
+
+ /** */
+ SHORT,
+
+ /** */
+ INT,
+
+ /** */
+ LONG,
+
+ /** */
+ FLOAT,
+
+ /** */
+ DOUBLE,
+
+ /** */
+ CHAR,
+
+ /** */
+ BOOLEAN,
+
+ /** */
+ OTHER
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedMarshallable.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedMarshallable.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedMarshallable.java
new file mode 100644
index 0000000..2851316
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedMarshallable.java
@@ -0,0 +1,57 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.marshaller.optimized;
+
+import java.util.*;
+
+/**
+ * Optional interface which helps make serialization even faster by removing internal
+ * look-ups for classes.
+ * <p>
+ * All implementation must have the following:
+ * <ul>
+ * <li>
+ * Must have static filed (private or public) declared of type {@link Object}
+ * with name {@code GG_CLASS_ID}. GridGain will reflectively initialize this field with
+ * proper class ID during system startup.
+ * </li>
+ * <li>
+ * Must return the value of {@code GG_CLASS_ID} field from {@link #ggClassId} method.
+ * </li>
+ * </ul>
+ * Here is a sample implementation:
+ * <pre name="code" class="java">
+ * // For better performance consider implementing java.io.Externalizable interface.
+ * class ExampleMarshallable implements GridOptimizedMarshallable, Serializable {
+ * // Class ID field required by 'GridOptimizedMarshallable'.
+ * private static Object GG_CLASS_ID;
+ *
+ * ...
+ *
+ * @ public Object ggClassId() {
+ * return GG_CLASS_ID;
+ * }
+ * }
+ * </pre>
+ * <p>
+ * Note that for better performance you should also specify list of classes you
+ * plan to serialize via {@link GridOptimizedMarshaller#setClassNames(List)} method.
+ */
+public interface GridOptimizedMarshallable {
+ /** */
+ public static final String CLS_ID_FIELD_NAME = "GG_CLASS_ID";
+
+ /**
+ * Implementation of this method should simply return value of {@code GG_CLASS_ID} field.
+ *
+ * @return Class ID for optimized marshalling.
+ */
+ public Object ggClassId();
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a50fccdd/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedMarshaller.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedMarshaller.java
new file mode 100644
index 0000000..3a94bb3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/GridOptimizedMarshaller.java
@@ -0,0 +1,408 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.marshaller.optimized;
+
+import org.apache.ignite.marshaller.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.jetbrains.annotations.*;
+import sun.misc.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * Optimized implementation of {@link GridMarshaller}. Unlike {@link org.apache.ignite.marshaller.jdk.GridJdkMarshaller},
+ * which is based on standard {@link ObjectOutputStream}, this marshaller does not
+ * enforce that all serialized objects implement {@link Serializable} interface. It is also
+ * about 20 times faster as it removes lots of serialization overhead that exists in
+ * default JDK implementation.
+ * <p>
+ * {@code GridOptimizedMarshaller} is tested only on Java HotSpot VM on other VMs
+ * it could yield unexpected results. It is the default marshaller on Java HotSpot VMs
+ * and will be used if no other marshaller was explicitly configured.
+ * <p>
+ * <h1 class="header">Configuration</h1>
+ * <h2 class="header">Mandatory</h2>
+ * This marshaller has no mandatory configuration parameters.
+ * <h2 class="header">Java Example</h2>
+ * <pre name="code" class="java">
+ * GridOptimizedMarshaller marshaller = new GridOptimizedMarshaller();
+ *
+ * // Enforce Serializable interface.
+ * marshaller.setRequireSerializable(true);
+ *
+ * GridConfiguration cfg = new GridConfiguration();
+ *
+ * // Override marshaller.
+ * cfg.setMarshaller(marshaller);
+ *
+ * // Starts grid.
+ * G.start(cfg);
+ * </pre>
+ * <h2 class="header">Spring Example</h2>
+ * GridOptimizedMarshaller can be configured from Spring XML configuration file:
+ * <pre name="code" class="xml">
+ * <bean id="grid.custom.cfg" class="org.gridgain.grid.GridConfiguration" singleton="true">
+ * ...
+ * <property name="marshaller">
+ * <bean class="org.gridgain.grid.marshaller.optimized.GridOptimizedMarshaller">
+ * <property name="requireSerializable">true</property>
+ * </bean>
+ * </property>
+ * ...
+ * </bean>
+ * </pre>
+ * <p>
+ * <img src="http://www.gridgain.com/images/spring-small.png">
+ * <br>
+ * For information about Spring framework visit <a href="http://www.springframework.org/">www.springframework.org</a>
+ * <h2 class="header">Injection Example</h2>
+ * GridMarshaller can be injected in users task, job or SPI as following:
+ * <pre name="code" class="java">
+ * public class MyGridJob implements GridComputeJob {
+ * ...
+ * @GridMarshallerResource
+ * private GridMarshaller marshaller;
+ * ...
+ * }
+ * </pre>
+ * or
+ * <pre name="code" class="java">
+ * public class MyGridJob implements GridComputeJob {
+ * ...
+ * private GridMarshaller marshaller;
+ * ...
+ * @GridMarshallerResource
+ * public void setMarshaller(GridMarshaller marshaller) {
+ * this.marshaller = marshaller;
+ * }
+ * ...
+ * }
+ * </pre>
+ */
+public class GridOptimizedMarshaller extends GridAbstractMarshaller {
+ /** Whether or not to require an object to be serializable in order to be marshalled. */
+ private boolean requireSer = true;
+
+ /** Default class loader. */
+ private final ClassLoader dfltClsLdr = getClass().getClassLoader();
+
+ /**
+ * Initializes marshaller not to enforce {@link Serializable} interface.
+ *
+ * @throws GridRuntimeException If this marshaller is not supported on the current JVM.
+ */
+ public GridOptimizedMarshaller() {
+ if (!available())
+ throw new GridRuntimeException("Using GridOptimizedMarshaller on unsupported JVM version (some of " +
+ "JVM-private APIs required for the marshaller to work are missing).");
+ }
+
+ /**
+ * Initializes marshaller with given serialization flag. If {@code true},
+ * then objects will be required to implement {@link Serializable} in order
+ * to be serialize.
+ *
+ * @param requireSer Flag to enforce {@link Serializable} interface or not. If {@code true},
+ * then objects will be required to implement {@link Serializable} in order to be
+ * marshalled, if {@code false}, then such requirement will be relaxed.
+ * @throws GridRuntimeException If this marshaller is not supported on the current JVM.
+ */
+ public GridOptimizedMarshaller(boolean requireSer) {
+ this();
+
+ this.requireSer = requireSer;
+ }
+
+ /**
+ * Initializes marshaller with given serialization flag. If {@code true},
+ * then objects will be required to implement {@link Serializable} in order
+ * to be serialize.
+ *
+ * @param requireSer Flag to enforce {@link Serializable} interface or not. If {@code true},
+ * then objects will be required to implement {@link Serializable} in order to be
+ * marshalled, if {@code false}, then such requirement will be relaxed.
+ * @param clsNames User preregistered class names.
+ * @param clsNamesPath Path to a file with user preregistered class names.
+ * @param poolSize Object streams pool size.
+ * @throws GridException If an I/O error occurs while writing stream header.
+ * @throws GridRuntimeException If this marshaller is not supported on the current JVM.
+ */
+ public GridOptimizedMarshaller(boolean requireSer, @Nullable List<String> clsNames,
+ @Nullable String clsNamesPath, int poolSize) throws GridException {
+ this(requireSer);
+
+ setClassNames(clsNames);
+ setClassNamesPath(clsNamesPath);
+ setPoolSize(poolSize);
+ }
+
+ /**
+ * Adds provided class names for marshalling optimization.
+ * <p>
+ * <b>NOTE</b>: these collections of classes must be identical on all nodes and in the same order.
+ *
+ * @param clsNames User preregistered class names to add.
+ */
+ @SuppressWarnings("unchecked")
+ public void setClassNames(@Nullable List<String> clsNames) {
+ if (clsNames != null && !clsNames.isEmpty()) {
+ String[] clsNamesArr = clsNames.toArray(new String[clsNames.size()]);
+
+ Arrays.sort(clsNamesArr);
+
+ Map<String, Integer> name2id = U.newHashMap(clsNamesArr.length);
+ T3<String, Class<?>, GridOptimizedClassDescriptor>[] id2name = new T3[clsNamesArr.length];
+
+ int i = 0;
+
+ for (String name : clsNamesArr) {
+ name2id.put(name, i);
+ id2name[i++] = new T3<>(name, null, null);
+ }
+
+ GridOptimizedClassResolver.userClasses(name2id, id2name);
+ }
+ }
+
+ /**
+ * Specifies a name of the file which lists all class names to be optimized.
+ * The file path can either be absolute path, relative to {@code GRIDGAIN_HOME},
+ * or specify a resource file on the class path.
+ * <p>
+ * The format of the file is class name per line, like this:
+ * <pre>
+ * ...
+ * com.example.Class1
+ * com.example.Class2
+ * ...
+ * </pre>
+ * <p>
+ * <b>NOTE</b>: this class list must be identical on all nodes and in the same order.
+ *
+ * @param path Path to a file with user preregistered class names.
+ * @throws GridException If an error occurs while writing stream header.
+ */
+ public void setClassNamesPath(@Nullable String path) throws GridException {
+ if (path == null)
+ return;
+
+ URL url = GridUtils.resolveGridGainUrl(path, false);
+
+ if (url == null)
+ throw new GridException("Failed to find resource for name: " + path);
+
+ List<String> clsNames;
+
+ try {
+ clsNames = new LinkedList<>();
+
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), GridOptimizedMarshallerUtils.UTF_8))) {
+ String clsName;
+
+ while ((clsName = reader.readLine()) != null)
+ clsNames.add(clsName);
+ }
+ }
+ catch (IOException e) {
+ throw new GridException("Failed to read class names from path: " + path, e);
+ }
+
+ setClassNames(clsNames);
+ }
+
+ /**
+ * Specifies size of cached object streams used by marshaller. Object streams are cached for
+ * performance reason to avoid costly recreation for every serialization routine. If {@code 0} (default),
+ * pool is not used and each thread has its own cached object stream which it keeps reusing.
+ * <p>
+ * Since each stream has an internal buffer, creating a stream for each thread can lead to
+ * high memory consumption if many large messages are marshalled or unmarshalled concurrently.
+ * Consider using pool in this case. This will limit number of streams that can be created and,
+ * therefore, decrease memory consumption.
+ * <p>
+ * NOTE: Using streams pool can decrease performance since streams will be shared between
+ * different threads which will lead to more frequent context switching.
+ *
+ * @param poolSize Streams pool size. If {@code 0}, pool is not used.
+ */
+ public void setPoolSize(int poolSize) {
+ GridOptimizedObjectStreamRegistry.poolSize(poolSize);
+ }
+
+ /**
+ * @return Whether to enforce {@link Serializable} interface.
+ */
+ public boolean isRequireSerializable() {
+ return requireSer;
+ }
+
+ /**
+ * Sets flag to enforce {@link Serializable} interface or not.
+ *
+ * @param requireSer Flag to enforce {@link Serializable} interface or not. If {@code true},
+ * then objects will be required to implement {@link Serializable} in order to be
+ * marshalled, if {@code false}, then such requirement will be relaxed.
+ */
+ public void setRequireSerializable(boolean requireSer) {
+ this.requireSer = requireSer;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void marshal(@Nullable Object obj, OutputStream out) throws GridException {
+ assert out != null;
+
+ GridOptimizedObjectOutputStream objOut = null;
+
+ try {
+ objOut = GridOptimizedObjectStreamRegistry.out();
+
+ objOut.requireSerializable(requireSer);
+
+ objOut.out().outputStream(out);
+
+ objOut.writeObject(obj);
+ }
+ catch (IOException e) {
+ throw new GridException("Failed to serialize object: " + obj, e);
+ }
+ finally {
+ GridOptimizedObjectStreamRegistry.closeOut(objOut);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] marshal(@Nullable Object obj) throws GridException {
+ GridOptimizedObjectOutputStream objOut = null;
+
+ try {
+ objOut = GridOptimizedObjectStreamRegistry.out();
+
+ objOut.requireSerializable(requireSer);
+
+ objOut.writeObject(obj);
+
+ return objOut.out().array();
+ }
+ catch (IOException e) {
+ throw new GridException("Failed to serialize object: " + obj, e);
+ }
+ finally {
+ GridOptimizedObjectStreamRegistry.closeOut(objOut);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> T unmarshal(InputStream in, @Nullable ClassLoader clsLdr) throws GridException {
+ assert in != null;
+
+ GridOptimizedObjectInputStream objIn = null;
+
+ try {
+ objIn = GridOptimizedObjectStreamRegistry.in();
+
+ objIn.classLoader(clsLdr != null ? clsLdr : dfltClsLdr);
+
+ objIn.in().inputStream(in);
+
+ return (T)objIn.readObject();
+ }
+ catch (IOException e) {
+ throw new GridException("Failed to deserialize object with given class loader: " + clsLdr, e);
+ }
+ catch (ClassNotFoundException e) {
+ throw new GridException("Failed to find class with given class loader for unmarshalling " +
+ "(make sure same versions of all classes are available on all nodes or enable peer-class-loading): " +
+ clsLdr, e);
+ }
+ finally {
+ GridOptimizedObjectStreamRegistry.closeIn(objIn);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> T unmarshal(byte[] arr, @Nullable ClassLoader clsLdr) throws GridException {
+ assert arr != null;
+
+ GridOptimizedObjectInputStream objIn = null;
+
+ try {
+ objIn = GridOptimizedObjectStreamRegistry.in();
+
+ objIn.classLoader(clsLdr != null ? clsLdr : dfltClsLdr);
+
+ objIn.in().bytes(arr, arr.length);
+
+ return (T)objIn.readObject();
+ }
+ catch (IOException e) {
+ throw new GridException("Failed to deserialize object with given class loader: " + clsLdr, e);
+ }
+ catch (ClassNotFoundException e) {
+ throw new GridException("Failed to find class with given class loader for unmarshalling " +
+ "(make sure same version of all classes are available on all nodes or enable peer-class-loading): " +
+ clsLdr, e);
+ }
+ finally {
+ GridOptimizedObjectStreamRegistry.closeIn(objIn);
+ }
+ }
+
+ /**
+ * Checks whether {@code GridOptimizedMarshaller} is able to work on the current JVM.
+ * <p>
+ * As long as {@code GridOptimizedMarshaller} uses JVM-private API, which is not guaranteed
+ * to be available on all JVM, this method should be called to ensure marshaller could work properly.
+ * <p>
+ * Result of this method is automatically checked in constructor.
+ *
+ * @return {@code true} if {@code GridOptimizedMarshaller} can work on the current JVM or
+ * {@code false} if it can't.
+ */
+ @SuppressWarnings({"TypeParameterExtendsFinalClass", "ErrorNotRethrown"})
+ public static boolean available() {
+ try {
+ Unsafe unsafe = GridUnsafe.unsafe();
+
+ Class<? extends Unsafe> unsafeCls = unsafe.getClass();
+
+ unsafeCls.getMethod("allocateInstance", Class.class);
+ unsafeCls.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
+
+ return true;
+ }
+ catch (Exception ignored) {
+ return false;
+ }
+ catch (NoClassDefFoundError ignored) {
+ return false;
+ }
+ }
+
+ /**
+ * Undeployment callback invoked when class loader is being undeployed.
+ *
+ * @param ldr Class loader being undeployed.
+ */
+ public static void onUndeploy(ClassLoader ldr) {
+ GridOptimizedMarshallerUtils.onUndeploy(ldr);
+ }
+
+ /**
+ * Clears internal caches and frees memory. Usually called on system stop.
+ */
+ public static void clearCache() {
+ GridOptimizedMarshallerUtils.clearCache();
+ }
+}