Repository: ignite Updated Branches: refs/heads/ignite-1.5 c12d17e2a -> d2008c53d
IGNITE-2098 - Added test for java Proxy - Fixes #301. Signed-off-by: Alexey Goncharuk <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/d2008c53 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/d2008c53 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/d2008c53 Branch: refs/heads/ignite-1.5 Commit: d2008c53d2d3ab25ba19b018081f88798140a274 Parents: c12d17e Author: Alexey Goncharuk <[email protected]> Authored: Thu Dec 10 12:51:16 2015 +0300 Committer: Alexey Goncharuk <[email protected]> Committed: Thu Dec 10 12:51:16 2015 +0300 ---------------------------------------------------------------------- .../portable/PortableClassDescriptor.java | 14 +- .../portable/BinaryMarshallerSelfTest.java | 198 +++++++++++++++++++ 2 files changed, 207 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/d2008c53/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java index 2dda9eb..9a65da1 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java @@ -42,10 +42,12 @@ import org.apache.ignite.binary.BinaryObjectException; import org.apache.ignite.binary.BinarySerializer; import org.apache.ignite.binary.Binarylizable; import org.apache.ignite.internal.processors.cache.CacheObjectImpl; +import org.apache.ignite.internal.util.GridUnsafe; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.marshaller.MarshallerExclusions; import org.apache.ignite.marshaller.optimized.OptimizedMarshaller; import org.jetbrains.annotations.Nullable; +import sun.misc.Unsafe; import static java.lang.reflect.Modifier.isStatic; import static java.lang.reflect.Modifier.isTransient; @@ -55,6 +57,9 @@ import static java.lang.reflect.Modifier.isTransient; */ public class PortableClassDescriptor { /** */ + public static final Unsafe UNSAFE = GridUnsafe.unsafe(); + + /** */ private final PortableContext ctx; /** */ @@ -228,7 +233,8 @@ public class PortableClassDescriptor { break; case OBJECT: - ctor = constructor(cls); + // Must not use constructor to honor transient fields semantics. + ctor = null; ArrayList<BinaryFieldAccessor> fields0 = new ArrayList<>(); stableFieldsMeta = metaDataEnabled ? new HashMap<String, Integer>() : null; @@ -748,10 +754,8 @@ public class PortableClassDescriptor { * @throws BinaryObjectException In case of error. */ private Object newInstance() throws BinaryObjectException { - assert ctor != null; - try { - return ctor.newInstance(); + return ctor != null ? ctor.newInstance() : UNSAFE.allocateInstance(cls); } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) { throw new BinaryObjectException("Failed to instantiate instance: " + cls, e); @@ -799,7 +803,7 @@ public class PortableClassDescriptor { writeObj.getReturnType() == void.class && readObj.getReturnType() == void.class) return true; } - catch (NoSuchMethodException e) { + catch (NoSuchMethodException ignored) { // No-op. } } http://git-wip-us.apache.org/repos/asf/ignite/blob/d2008c53/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java index 037adf9..9277a77 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java @@ -23,8 +23,10 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetSocketAddress; @@ -75,9 +77,11 @@ import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.marshaller.MarshallerContextTestImpl; +import org.apache.ignite.marshaller.optimized.OptimizedMarshaller; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jsr166.ConcurrentHashMap8; import sun.misc.Unsafe; @@ -2329,6 +2333,200 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest { } /** + * @throws Exception If failed. + */ + public void testProxy() throws Exception { + BinaryMarshaller marsh = binaryMarshaller(); + + SomeItf inItf = (SomeItf)Proxy.newProxyInstance( + BinaryMarshallerSelfTest.class.getClassLoader(), new Class[] {SomeItf.class}, + new InvocationHandler() { + private NonSerializable obj = new NonSerializable(null); + + @Override public Object invoke(Object proxy, Method mtd, Object[] args) throws Throwable { + if ("hashCode".equals(mtd.getName())) + return obj.hashCode(); + + obj.checkAfterUnmarshalled(); + + return 17; + } + } + ); + + SomeItf outItf = marsh.unmarshal(marsh.marshal(inItf), null); + + assertEquals(outItf.checkAfterUnmarshalled(), 17); + } + + /** + * + */ + private static interface SomeItf { + /** + * @return Check result. + */ + int checkAfterUnmarshalled(); + } + + /** + * Some non-serializable class. + */ + @SuppressWarnings( {"PublicField","TransientFieldInNonSerializableClass","FieldMayBeStatic"}) + private static class NonSerializableA { + /** */ + private final long longVal = 0x33445566778899AAL; + + /** */ + protected Short shortVal = (short)0xAABB; + + /** */ + public String[] strArr = {"AA","BB"}; + + /** */ + public boolean flag1 = true; + + /** */ + public boolean flag2; + + /** */ + public Boolean flag3; + + /** */ + public Boolean flag4 = true; + + /** */ + public Boolean flag5 = false; + + /** */ + private transient int intVal = 0xAABBCCDD; + + /** + * @param strArr Array. + * @param shortVal Short value. + */ + @SuppressWarnings( {"UnusedDeclaration"}) + private NonSerializableA(@Nullable String[] strArr, @Nullable Short shortVal) { + // No-op. + } + + /** + * Checks correctness of the state after unmarshalling. + */ + void checkAfterUnmarshalled() { + assertEquals(longVal, 0x33445566778899AAL); + + assertEquals(shortVal.shortValue(), (short)0xAABB); + + assertTrue(Arrays.equals(strArr, new String[] {"AA","BB"})); + + assertEquals(0, intVal); + + assertTrue(flag1); + assertFalse(flag2); + assertNull(flag3); + assertTrue(flag4); + assertFalse(flag5); + } + } + + /** + * Some non-serializable class. + */ + @SuppressWarnings( {"PublicField","TransientFieldInNonSerializableClass","PackageVisibleInnerClass"}) + static class NonSerializableB extends NonSerializableA { + /** */ + public Short shortValue = 0x1122; + + /** */ + public long longValue = 0x8877665544332211L; + + /** */ + private transient NonSerializableA[] aArr = { + new NonSerializableA(null, null), + new NonSerializableA(null, null), + new NonSerializableA(null, null) + }; + + /** */ + protected Double doubleVal = 123.456; + + /** + * Just to eliminate the default constructor. + */ + private NonSerializableB() { + super(null, null); + } + + /** + * Checks correctness of the state after unmarshalling. + */ + @Override void checkAfterUnmarshalled() { + super.checkAfterUnmarshalled(); + + assertEquals(shortValue.shortValue(), 0x1122); + + assertEquals(longValue, 0x8877665544332211L); + + assertNull(aArr); + + assertEquals(doubleVal, 123.456); + } + } + + /** + * Some non-serializable class. + */ + @SuppressWarnings( {"TransientFieldInNonSerializableClass","PublicField"}) + private static class NonSerializable extends NonSerializableB { + /** */ + private int idVal = -17; + + /** */ + private final NonSerializableA aVal = new NonSerializableB(); + + /** */ + private transient NonSerializableB bVal = new NonSerializableB(); + + /** */ + private NonSerializableA[] bArr = new NonSerializableA[] { + new NonSerializableB(), + new NonSerializableA(null, null) + }; + + /** */ + public float floatVal = 567.89F; + + /** + * Just to eliminate the default constructor. + * + * @param aVal Unused. + */ + @SuppressWarnings( {"UnusedDeclaration"}) + private NonSerializable(NonSerializableA aVal) { + } + + /** + * Checks correctness of the state after unmarshalling. + */ + @Override void checkAfterUnmarshalled() { + super.checkAfterUnmarshalled(); + + assertEquals(idVal, -17); + + aVal.checkAfterUnmarshalled(); + + assertNull(bVal); + + for (NonSerializableA a : bArr) { + a.checkAfterUnmarshalled(); + } + + assertEquals(floatVal, 567.89F); + } + } + + /** * Object with class fields. */ private static class ObjectWithClassFields {
