You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sd...@apache.org on 2022/01/17 08:16:58 UTC
[ignite-3] branch main updated: IGNITE-16254 - Optimize (un)marshalling of primitives in object fields
This is an automated email from the ASF dual-hosted git repository.
sdanilov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 40841cd IGNITE-16254 - Optimize (un)marshalling of primitives in object fields
40841cd is described below
commit 40841cd94a44b45b00f963e0588e79cee9f135a1
Author: Roman Puchkovskiy <ro...@gmail.com>
AuthorDate: Thu Jan 13 14:29:22 2022 +0400
IGNITE-16254 - Optimize (un)marshalling of primitives in object fields
---
.../network/message/ClassDescriptorMessage.java | 13 +-
.../{BuiltinType.java => BuiltInType.java} | 27 +--
...izedStreamCommands.java => BuiltInTypeIds.java} | 21 +--
.../network/serialization/ClassDescriptor.java | 30 +++-
.../serialization/ClassDescriptorFactory.java | 43 +++--
.../ClassDescriptorFactoryContext.java | 33 +---
.../network/serialization/FieldAccessor.java | 136 ++++++++++++++-
.../network/serialization/FieldAccessorImpl.java | 83 ---------
.../network/serialization/FieldDescriptor.java | 24 +--
.../serialization/IdIndexedDescriptors.java | 9 +
.../PerSessionSerializationService.java | 6 +-
.../network/serialization/Serialization.java | 38 ++--
.../network/serialization/SerializationType.java | 2 +-
.../SpecialSerializationMethodsImpl.java | 4 +-
.../network/serialization/UnsafeFieldAccessor.java | 192 +++++++++++++++++++++
.../marshal/DefaultUserObjectMarshaller.java | 11 +-
.../marshal/StructuredObjectMarshaller.java | 98 ++++++++++-
.../serialization/ClassDescriptorFactoryTest.java | 60 ++++++-
.../serialization/DefaultDescriptorsTest.java | 90 +++++-----
...erObjectMarshallerWithArbitraryObjectsTest.java | 78 ++++++++-
...efaultUserObjectMarshallerWithBuiltinsTest.java | 112 ++++++------
...shallerWithSerializableOverrideStreamsTest.java | 2 -
...ltUserObjectMarshallerWithSerializableTest.java | 28 +++
23 files changed, 817 insertions(+), 323 deletions(-)
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/message/ClassDescriptorMessage.java b/modules/network/src/main/java/org/apache/ignite/internal/network/message/ClassDescriptorMessage.java
index 1bf857b..c79d5c6 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/message/ClassDescriptorMessage.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/message/ClassDescriptorMessage.java
@@ -73,11 +73,18 @@ public interface ClassDescriptorMessage extends NetworkMessage {
int serializationType();
/**
- * Has serialization override.
+ * Has writeObject().
*
- * @see Serialization#hasSerializationOverride()
+ * @see Serialization#hasWriteObject()
*/
- boolean hasSerializationOverride();
+ boolean hasWriteObject();
+
+ /**
+ * Has readObject().
+ *
+ * @see Serialization#hasReadObject()
+ */
+ boolean hasReadObject();
/**
* Has readObjectNoData().
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltinType.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltInType.java
similarity index 87%
rename from modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltinType.java
rename to modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltInType.java
index c27c595..56f6f2b 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltinType.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltInType.java
@@ -31,23 +31,21 @@ import org.apache.ignite.lang.IgniteUuid;
/**
* Built-in types.
- *
- * <p>They share ID space with commands defined in {@link SerializedStreamCommands}.
*/
-public enum BuiltinType {
- BYTE(0, byte.class),
+public enum BuiltInType {
+ BYTE(BuiltInTypeIds.BYTE, byte.class),
BYTE_BOXED(1, Byte.class),
- SHORT(2, short.class),
+ SHORT(BuiltInTypeIds.SHORT, short.class),
SHORT_BOXED(3, Short.class),
- INT(4, int.class),
+ INT(BuiltInTypeIds.INT, int.class),
INT_BOXED(5, Integer.class),
- FLOAT(6, float.class),
+ FLOAT(BuiltInTypeIds.FLOAT, float.class),
FLOAT_BOXED(7, Float.class),
- LONG(8, long.class),
+ LONG(BuiltInTypeIds.LONG, long.class),
LONG_BOXED(9, Long.class),
- DOUBLE(10, double.class),
+ DOUBLE(BuiltInTypeIds.DOUBLE, double.class),
DOUBLE_BOXED(11, Double.class),
- BOOLEAN(12, boolean.class),
+ BOOLEAN(BuiltInTypeIds.BOOLEAN, boolean.class),
BOOLEAN_BOXED(13, Boolean.class),
CHAR(14, char.class),
CHAR_BOXED(15, Character.class),
@@ -80,8 +78,8 @@ public enum BuiltinType {
HASH_MAP(40, HashMap.class),
LINKED_HASH_MAP(41, LinkedHashMap.class),
BIT_SET(42, BitSet.class),
- NULL(43, Null.class)
- // 44 is REFERENCE command, see SerializedStreamCommands#REFERENCE
+ NULL(43, Null.class),
+ REFERENCE(44, DummyPlaceholder.class)
;
/**
@@ -100,7 +98,7 @@ public enum BuiltinType {
* @param descriptorId Descriptor id.
* @param clazz Type.
*/
- BuiltinType(int descriptorId, Class<?> clazz) {
+ BuiltInType(int descriptorId, Class<?> clazz) {
this.descriptorId = descriptorId;
this.clazz = clazz;
}
@@ -137,4 +135,7 @@ public enum BuiltinType {
new Serialization(SerializationType.BUILTIN)
);
}
+
+ private static class DummyPlaceholder {
+ }
}
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SerializedStreamCommands.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltInTypeIds.java
similarity index 61%
rename from modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SerializedStreamCommands.java
rename to modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltInTypeIds.java
index b5f1af3..fe1380b 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SerializedStreamCommands.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/BuiltInTypeIds.java
@@ -18,15 +18,16 @@
package org.apache.ignite.internal.network.serialization;
/**
- * Lists commands used in the serialized stream.
- * Command IDs share space with IDs of {@link ClassDescriptor}s (most importantly, those that are defined in {@link BuiltinType}.
+ * IDs of built-in descriptors. Only defines part of IDs which are needed directly in constant expressions (like switch);
+ * most of them are defined directly on enum members in {@link BuiltInType}.
*/
-public class SerializedStreamCommands {
- /**
- * Reference: an object that was already seen in the graph, so we relate to it by its ID instead of serializing it again.
- */
- public static final int REFERENCE = 44;
-
- private SerializedStreamCommands() {
- }
+public class BuiltInTypeIds {
+ public static final int BYTE = 0;
+ public static final int SHORT = 2;
+ public static final int INT = 4;
+ public static final int FLOAT = 6;
+ public static final int LONG = 8;
+ public static final int DOUBLE = 10;
+ public static final int BOOLEAN = 12;
+ public static final int CHAR = 14;
}
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptor.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptor.java
index 322ffcf..247bf09 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptor.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptor.java
@@ -206,12 +206,30 @@ public class ClassDescriptor {
}
/**
- * Returns {@code true} if the described class has writeObject() and readObject() methods.
+ * Returns {@code true} if the described class has writeObject() method.
*
- * @return {@code true} if the described class has writeObject() and readObject() methods
+ * @return {@code true} if the described class has writeObject() method
*/
- public boolean hasSerializationOverride() {
- return serialization.hasSerializationOverride();
+ public boolean hasWriteObject() {
+ return serialization.hasWriteObject();
+ }
+
+ /**
+ * Returns {@code true} if the described class has readObject() method.
+ *
+ * @return {@code true} if the described class has readObject() method
+ */
+ public boolean hasReadObject() {
+ return serialization.hasReadObject();
+ }
+
+ /**
+ * Returns {@code true} if the described class has readObjectNoData() method.
+ *
+ * @return {@code true} if the described class has readObjectNoData() method
+ */
+ public boolean hasReadObjectNoData() {
+ return serialization.hasReadObjectNoData();
}
/**
@@ -238,7 +256,7 @@ public class ClassDescriptor {
* @return {@code true} if this is the descriptor of {@code null} values
*/
public boolean isNull() {
- return descriptorId == BuiltinType.NULL.descriptorId();
+ return descriptorId == BuiltInType.NULL.descriptorId();
}
/**
@@ -247,7 +265,7 @@ public class ClassDescriptor {
* @return {@code true} if this is the descriptor of {@link java.util.Collections#singletonList(Object)} type
*/
public boolean isSingletonList() {
- return descriptorId == BuiltinType.SINGLETON_LIST.descriptorId();
+ return descriptorId == BuiltInType.SINGLETON_LIST.descriptorId();
}
/**
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactory.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactory.java
index 966a7ff..600ec6e 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactory.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactory.java
@@ -40,8 +40,10 @@ import org.jetbrains.annotations.Nullable;
* Class descriptor factory for the user object serialization.
*/
public class ClassDescriptorFactory {
- /** Means that no serialization override is present; used for readability instead of {@code false}. */
- private static final boolean NO_SERIALIZATION_OVERRIDE = false;
+ /** Means that no writeObject() method is present; used for readability instead of {@code false}. */
+ private static final boolean NO_WRITE_OBJECT = false;
+ /** Means that no readObject() method is present; used for readability instead of {@code false}. */
+ private static final boolean NO_READ_OBJECT = false;
/** Means that no readObjectNoData() method is present; used for readability instead of {@code false}. */
private static final boolean NO_READ_OBJECT_NO_DATA = false;
@@ -133,7 +135,8 @@ public class ClassDescriptorFactory {
Collections.emptyList(),
new Serialization(
SerializationType.EXTERNALIZABLE,
- NO_SERIALIZATION_OVERRIDE,
+ NO_WRITE_OBJECT,
+ NO_READ_OBJECT,
NO_READ_OBJECT_NO_DATA,
hasWriteReplace(clazz),
hasReadResolve(clazz)
@@ -201,7 +204,8 @@ public class ClassDescriptorFactory {
fields(clazz),
new Serialization(
SerializationType.SERIALIZABLE,
- hasOverrideSerialization(clazz),
+ hasWriteObject(clazz),
+ hasReadObject(clazz),
hasReadObjectNoData(clazz),
hasWriteReplace(clazz),
hasReadResolve(clazz)
@@ -217,10 +221,6 @@ public class ClassDescriptorFactory {
return getWriteReplace(clazz) != null;
}
- private boolean hasOverrideSerialization(Class<? extends Serializable> clazz) {
- return hasWriteObject(clazz) && hasReadObject(clazz);
- }
-
private boolean hasReadObject(Class<? extends Serializable> clazz) {
return getReadObject(clazz) != null;
}
@@ -312,13 +312,16 @@ public class ClassDescriptorFactory {
@Nullable
private static Method getWriteObject(Class<? extends Serializable> clazz) {
try {
- Method writeObject = clazz.getDeclaredMethod("writeObject", ObjectOutputStream.class);
+ Method method = clazz.getDeclaredMethod("writeObject", ObjectOutputStream.class);
- if (!Modifier.isPrivate(writeObject.getModifiers())) {
+ if (!Modifier.isPrivate(method.getModifiers())) {
+ return null;
+ }
+ if (method.getReturnType() != void.class) {
return null;
}
- return writeObject;
+ return method;
} catch (NoSuchMethodException e) {
return null;
}
@@ -335,13 +338,16 @@ public class ClassDescriptorFactory {
@Nullable
private static Method getReadObject(Class<? extends Serializable> clazz) {
try {
- Method writeObject = clazz.getDeclaredMethod("readObject", ObjectInputStream.class);
+ Method method = clazz.getDeclaredMethod("readObject", ObjectInputStream.class);
- if (!Modifier.isPrivate(writeObject.getModifiers())) {
+ if (!Modifier.isPrivate(method.getModifiers())) {
+ return null;
+ }
+ if (method.getReturnType() != void.class) {
return null;
}
- return writeObject;
+ return method;
} catch (NoSuchMethodException e) {
return null;
}
@@ -357,13 +363,16 @@ public class ClassDescriptorFactory {
@Nullable
private static Method getReadObjectNoData(Class<? extends Serializable> clazz) {
try {
- Method writeObject = clazz.getDeclaredMethod("readObjectNoData");
+ Method method = clazz.getDeclaredMethod("readObjectNoData");
- if (!Modifier.isPrivate(writeObject.getModifiers())) {
+ if (!Modifier.isPrivate(method.getModifiers())) {
+ return null;
+ }
+ if (method.getReturnType() != void.class) {
return null;
}
- return writeObject;
+ return method;
} catch (NoSuchMethodException e) {
return null;
}
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactoryContext.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactoryContext.java
index 47cba73..473404c 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactoryContext.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactoryContext.java
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Class descriptor factory context.
*/
-public class ClassDescriptorFactoryContext implements ClassIndexedDescriptors {
+public class ClassDescriptorFactoryContext implements IdIndexedDescriptors, ClassIndexedDescriptors {
/** Quantity of descriptor ids reserved for the default descriptors. */
private static final int DEFAULT_DESCRIPTORS_OFFSET_COUNT = 1000;
@@ -42,7 +42,7 @@ public class ClassDescriptorFactoryContext implements ClassIndexedDescriptors {
* Constructor.
*/
public ClassDescriptorFactoryContext() {
- for (BuiltinType value : BuiltinType.values()) {
+ for (BuiltInType value : BuiltInType.values()) {
addPredefinedDescriptor(value.clazz(), value.asClassDescriptor());
}
}
@@ -81,6 +81,7 @@ public class ClassDescriptorFactoryContext implements ClassIndexedDescriptors {
* @param descriptorId Descriptor id.
* @return Descriptor.
*/
+ @Override
@Nullable
public ClassDescriptor getDescriptor(int descriptorId) {
return descriptorMap.get(descriptorId);
@@ -109,37 +110,11 @@ public class ClassDescriptorFactoryContext implements ClassIndexedDescriptors {
*
* @param builtinType built-in type for lookup
*/
- public ClassDescriptor getBuiltInDescriptor(BuiltinType builtinType) {
+ public ClassDescriptor getBuiltInDescriptor(BuiltInType builtinType) {
return getRequiredDescriptor(builtinType.descriptorId());
}
/**
- * Returns a descriptor by ID or throws an exception if no such descriptor is known.
- *
- * @param descriptorId ID of the descriptor
- * @return descriptor by ID
- */
- public ClassDescriptor getRequiredDescriptor(int descriptorId) {
- ClassDescriptor descriptor = getDescriptor(descriptorId);
-
- if (descriptor == null) {
- throw new IllegalStateException("Did not find a descriptor with ID=" + descriptorId);
- }
-
- return descriptor;
- }
-
- /**
- * Returns {@code true} if there is a descriptor for the id.
- *
- * @param descriptorId Descriptor id.
- * @return {@code true} if there is a descriptor for the id.
- */
- public boolean hasDescriptor(int descriptorId) {
- return getDescriptor(descriptorId) != null;
- }
-
- /**
* Returns a descriptor for {@code null} value.
*
* @return a descriptor for {@code null} value
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldAccessor.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldAccessor.java
index 34c4806..81b3b88 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldAccessor.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldAccessor.java
@@ -22,18 +22,146 @@ package org.apache.ignite.internal.network.serialization;
*/
public interface FieldAccessor {
/**
- * Returns the bound field value of the given object.
+ * Returns the bound object field value of the given object.
*
* @param target target object
* @return the bound field value of the given object
*/
- Object get(Object target);
+ Object getObject(Object target);
/**
- * Sets the bound field value on the given object.
+ * Sets the bound object field value on the given object.
*
* @param target target object
* @param fieldValue value to set
*/
- void set(Object target, Object fieldValue);
+ void setObject(Object target, Object fieldValue);
+
+ /**
+ * Returns the bound byte field value of the given object.
+ *
+ * @param target target object
+ * @return the bound byte field value of the given object
+ */
+ byte getByte(Object target);
+
+ /**
+ * Sets the bound byte field value on the given object.
+ *
+ * @param target target object
+ * @param fieldValue value to set
+ */
+ void setByte(Object target, byte fieldValue);
+
+ /**
+ * Returns the bound short field value of the given object.
+ *
+ * @param target target object
+ * @return the bound byte field value of the given object
+ */
+ short getShort(Object target);
+
+ /**
+ * Sets the bound short field value on the given object.
+ *
+ * @param target target object
+ * @param fieldValue value to set
+ */
+ void setShort(Object target, short fieldValue);
+
+ /**
+ * Returns the bound int field value of the given object.
+ *
+ * @param target target object
+ * @return the bound int field value of the given object
+ */
+ int getInt(Object target);
+
+ /**
+ * Sets the bound int field value on the given object.
+ *
+ * @param target target object
+ * @param fieldValue value to set
+ */
+ void setInt(Object target, int fieldValue);
+
+ /**
+ * Returns the bound long field value of the given object.
+ *
+ * @param target target object
+ * @return the bound byte field value of the given object
+ */
+ long getLong(Object target);
+
+ /**
+ * Sets the bound long field value on the given object.
+ *
+ * @param target target object
+ * @param fieldValue value to set
+ */
+ void setLong(Object target, long fieldValue);
+
+ /**
+ * Returns the bound float field value of the given object.
+ *
+ * @param target target object
+ * @return the bound byte field value of the given object
+ */
+ float getFloat(Object target);
+
+ /**
+ * Sets the bound float field value on the given object.
+ *
+ * @param target target object
+ * @param fieldValue value to set
+ */
+ void setFloat(Object target, float fieldValue);
+
+ /**
+ * Returns the bound double field value of the given object.
+ *
+ * @param target target object
+ * @return the bound byte field value of the given object
+ */
+ double getDouble(Object target);
+
+ /**
+ * Sets the bound double field value on the given object.
+ *
+ * @param target target object
+ * @param fieldValue value to set
+ */
+ void setDouble(Object target, double fieldValue);
+
+ /**
+ * Returns the bound char field value of the given object.
+ *
+ * @param target target object
+ * @return the bound byte field value of the given object
+ */
+ char getChar(Object target);
+
+ /**
+ * Sets the bound char field value on the given object.
+ *
+ * @param target target object
+ * @param fieldValue value to set
+ */
+ void setChar(Object target, char fieldValue);
+
+ /**
+ * Returns the bound boolean field value of the given object.
+ *
+ * @param target target object
+ * @return the bound byte field value of the given object
+ */
+ boolean getBoolean(Object target);
+
+ /**
+ * Sets the bound boolean field value on the given object.
+ *
+ * @param target target object
+ * @param fieldValue value to set
+ */
+ void setBoolean(Object target, boolean fieldValue);
}
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldAccessorImpl.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldAccessorImpl.java
deleted file mode 100644
index 1346397..0000000
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldAccessorImpl.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.network.serialization;
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-
-/**
- * {@link FieldAccessor} implementation.
- */
-class FieldAccessorImpl implements FieldAccessor {
- private final Field field;
- private final VarHandle varHandle;
-
- FieldAccessorImpl(FieldDescriptor descriptor) {
- field = findField(descriptor);
- field.setAccessible(true);
-
- varHandle = varHandleFrom(field);
- }
-
- private static Field findField(FieldDescriptor fieldDescriptor) {
- try {
- return fieldDescriptor.declaringClass().getDeclaredField(fieldDescriptor.name());
- } catch (NoSuchFieldException e) {
- throw new ReflectionException("Cannot find field", e);
- }
- }
-
- private static VarHandle varHandleFrom(Field field) {
- try {
- MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(field.getDeclaringClass(), MethodHandles.lookup());
- return lookup.unreflectVarHandle(field);
- } catch (ReflectiveOperationException e) {
- throw new ReflectionException("Cannot get a field VarHandle", e);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public Object get(Object target) {
- return varHandle.get(target);
- }
-
- /** {@inheritDoc} */
- @Override
- public void set(Object target, Object fieldValue) {
- if (isFieldFinal()) {
- setViaField(target, fieldValue);
- } else {
- varHandle.set(target, fieldValue);
- }
- }
-
- private boolean isFieldFinal() {
- return Modifier.isFinal(field.getModifiers());
- }
-
- private void setViaField(Object target, Object fieldValue) {
- try {
- field.set(target, fieldValue);
- } catch (IllegalAccessException e) {
- throw new ReflectionException("Cannot set a value", e);
- }
- }
-}
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldDescriptor.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldDescriptor.java
index fe86f24..e3e4687 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldDescriptor.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/FieldDescriptor.java
@@ -40,11 +40,6 @@ public class FieldDescriptor {
private final int typeDescriptorId;
/**
- * The class in which the field is declared.
- */
- private final Class<?> declaringClass;
-
- /**
* Accessor for accessing this field.
*/
private final FieldAccessor accessor;
@@ -53,7 +48,7 @@ public class FieldDescriptor {
* Constructor.
*/
public FieldDescriptor(Field field, int typeDescriptorId) {
- this(field.getName(), field.getType(), typeDescriptorId, field.getDeclaringClass());
+ this(field.getName(), field.getType(), typeDescriptorId, new UnsafeFieldAccessor(field));
}
/**
@@ -65,12 +60,14 @@ public class FieldDescriptor {
* @param declaringClass the class in which the field if declared
*/
public FieldDescriptor(String fieldName, Class<?> fieldClazz, int typeDescriptorId, Class<?> declaringClass) {
+ this(fieldName, fieldClazz, typeDescriptorId, new UnsafeFieldAccessor(fieldName, declaringClass));
+ }
+
+ private FieldDescriptor(String fieldName, Class<?> fieldClazz, int typeDescriptorId, FieldAccessor accessor) {
this.name = fieldName;
this.clazz = fieldClazz;
this.typeDescriptorId = typeDescriptorId;
- this.declaringClass = declaringClass;
-
- accessor = new FieldAccessorImpl(this);
+ this.accessor = accessor;
}
/**
@@ -103,15 +100,6 @@ public class FieldDescriptor {
}
/**
- * Returns the class in which the field is declared.
- *
- * @return the class in which the field is declared
- */
- public Class<?> declaringClass() {
- return declaringClass;
- }
-
- /**
* Returns {@link FieldAccessor} for this field.
*
* @return {@link FieldAccessor} for this field
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/IdIndexedDescriptors.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/IdIndexedDescriptors.java
index b5938a8..0881bb6 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/IdIndexedDescriptors.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/IdIndexedDescriptors.java
@@ -48,4 +48,13 @@ public interface IdIndexedDescriptors {
return descriptor;
}
+ /**
+ * Returns {@code true} if there is a descriptor for the id.
+ *
+ * @param descriptorId Descriptor id.
+ * @return {@code true} if there is a descriptor for the id.
+ */
+ default boolean hasDescriptor(int descriptorId) {
+ return getDescriptor(descriptorId) != null;
+ }
}
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/PerSessionSerializationService.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/PerSessionSerializationService.java
index fb92bd0..167649e 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/PerSessionSerializationService.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/PerSessionSerializationService.java
@@ -128,7 +128,8 @@ public class PerSessionSerializationService {
.fields(fields)
.isFinal(descriptor.isFinal())
.serializationType(serialization.type().value())
- .hasSerializationOverride(serialization.hasSerializationOverride())
+ .hasWriteObject(serialization.hasWriteObject())
+ .hasReadObject(serialization.hasReadObject())
.hasReadObjectNoData(serialization.hasReadObjectNoData())
.hasWriteReplace(serialization.hasWriteReplace())
.hasReadResolve(serialization.hasReadResolve())
@@ -187,7 +188,8 @@ public class PerSessionSerializationService {
var serialization = new Serialization(
serializationType,
- clsMsg.hasSerializationOverride(),
+ clsMsg.hasWriteObject(),
+ clsMsg.hasReadObject(),
clsMsg.hasReadObjectNoData(),
clsMsg.hasWriteReplace(),
clsMsg.hasReadResolve()
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/Serialization.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/Serialization.java
index 19e247a..feff989 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/Serialization.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/Serialization.java
@@ -24,8 +24,10 @@ public class Serialization {
/** Serialization type. */
private final SerializationType type;
- /** Whether a Serializable has writeObject() + readObject() methods. */
- private final boolean hasSerializationOverride;
+ /** Whether a Serializable has writeObject() method. */
+ private final boolean hasWriteObject;
+ /** Whether a Serializable has readObject() method. */
+ private final boolean hasReadObject;
/** Whether a Serializable has readObjectNoData() method. */
private final boolean hasReadObjectNoData;
/** Whether a Serializable/Externalizable has writeReplace() method. */
@@ -37,24 +39,27 @@ public class Serialization {
* Creates a new Serialization.
*
* @param type type
- * @param hasSerializationOverride whether a Serializable has writeObject() + readObject() methods
+ * @param hasWriteObject whether a Serializable has writeObject() method
+ * @param hasReadObject whether a Serializable has readObject() method
* @param hasReadObjectNoData whether a Serializable has readObjectNoData() method
* @param hasWriteReplace whether a Serializable/Externalizable has writeReplace() method
* @param hasReadResolve whether a Serializable/Externalizable has readResolve() method
*/
public Serialization(
SerializationType type,
- boolean hasSerializationOverride,
+ boolean hasWriteObject,
+ boolean hasReadObject,
boolean hasReadObjectNoData,
boolean hasWriteReplace,
boolean hasReadResolve
) {
assert type == SerializationType.SERIALIZABLE
- || (type == SerializationType.EXTERNALIZABLE && !hasSerializationOverride && !hasReadObjectNoData)
- || (!hasSerializationOverride && !hasWriteReplace && !hasReadResolve);
+ || (type == SerializationType.EXTERNALIZABLE && !hasWriteObject && !hasReadObject && !hasReadObjectNoData)
+ || (!hasWriteObject && !hasReadObject && !hasWriteReplace && !hasReadResolve);
this.type = type;
- this.hasSerializationOverride = hasSerializationOverride;
+ this.hasWriteObject = hasWriteObject;
+ this.hasReadObject = hasReadObject;
this.hasReadObjectNoData = hasReadObjectNoData;
this.hasWriteReplace = hasWriteReplace;
this.hasReadResolve = hasReadResolve;
@@ -66,7 +71,7 @@ public class Serialization {
* @param type serialization type
*/
public Serialization(SerializationType type) {
- this(type, false, false, false, false);
+ this(type, false, false, false, false, false);
}
/**
@@ -79,12 +84,21 @@ public class Serialization {
}
/**
- * Returns whether serialization override (writeObject() + readObject()) is present.
+ * Returns whether writeObject() method is present.
*
- * @return whether serialization override (writeObject() + readObject()) is present
+ * @return whether writeObject() method is present
*/
- public boolean hasSerializationOverride() {
- return hasSerializationOverride;
+ public boolean hasWriteObject() {
+ return hasWriteObject;
+ }
+
+ /**
+ * Returns whether readObject() method is present.
+ *
+ * @return whether readObject() method is present
+ */
+ public boolean hasReadObject() {
+ return hasReadObject;
}
/**
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SerializationType.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SerializationType.java
index 8f8b3dd..4a55f0d 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SerializationType.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SerializationType.java
@@ -23,7 +23,7 @@ import org.apache.ignite.lang.IgniteInternalException;
* Serialization type.
*/
public enum SerializationType {
- /** Used for predefined descriptors like primitive (or boxed int). See {@link BuiltinType}. */
+ /** Used for predefined descriptors like primitive (or boxed int). See {@link BuiltInType}. */
BUILTIN(0),
/** Type for classes that are neither serializable nor externalizable. */
ARBITRARY(1),
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SpecialSerializationMethodsImpl.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SpecialSerializationMethodsImpl.java
index def5ff4..84e7caa 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SpecialSerializationMethodsImpl.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/SpecialSerializationMethodsImpl.java
@@ -53,8 +53,8 @@ class SpecialSerializationMethodsImpl implements SpecialSerializationMethods {
public SpecialSerializationMethodsImpl(ClassDescriptor descriptor) {
writeReplaceHandle = descriptor.hasWriteReplace() ? writeReplaceHandle(descriptor) : null;
readResolveHandle = descriptor.hasReadResolve() ? readResolveHandle(descriptor) : null;
- writeObjectHandle = descriptor.hasSerializationOverride() ? writeObjectHandle(descriptor) : null;
- readObjectHandle = descriptor.hasSerializationOverride() ? readObjectHandle(descriptor) : null;
+ writeObjectHandle = descriptor.hasWriteObject() ? writeObjectHandle(descriptor) : null;
+ readObjectHandle = descriptor.hasReadObject() ? readObjectHandle(descriptor) : null;
}
private static MethodHandle writeReplaceHandle(ClassDescriptor descriptor) {
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/UnsafeFieldAccessor.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/UnsafeFieldAccessor.java
new file mode 100644
index 0000000..f002fcf
--- /dev/null
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/UnsafeFieldAccessor.java
@@ -0,0 +1,192 @@
+/*
+ * 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.network.serialization;
+
+import java.lang.reflect.Field;
+import org.apache.ignite.internal.util.GridUnsafe;
+
+/**
+ * {@link FieldAccessor} implementation.
+ */
+class UnsafeFieldAccessor implements FieldAccessor {
+ private final Field field;
+ private final Class<?> fieldType;
+ private final long fieldOffset;
+
+ UnsafeFieldAccessor(String fieldName, Class<?> declaringClass) {
+ this(findField(fieldName, declaringClass));
+ }
+
+ UnsafeFieldAccessor(Field field) {
+ this.field = field;
+ fieldType = field.getType();
+ fieldOffset = GridUnsafe.objectFieldOffset(field);
+ }
+
+ private static Field findField(String fieldName, Class<?> declaringClass) {
+ try {
+ return declaringClass.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException e) {
+ throw new ReflectionException("Cannot find field", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Object getObject(Object target) {
+ assert !fieldType.isPrimitive() : field.getDeclaringClass() + "#" + field.getName() + " is primitive!";
+
+ return GridUnsafe.getObjectField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setObject(Object target, Object fieldValue) {
+ assert !fieldType.isPrimitive() : field.getDeclaringClass() + "#" + field.getName() + " is primitive!";
+
+ GridUnsafe.putObjectField(target, fieldOffset, fieldValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public byte getByte(Object target) {
+ assert fieldType == byte.class : field.getDeclaringClass() + "#" + field.getName() + " is not byte";
+
+ return GridUnsafe.getByteField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setByte(Object target, byte fieldValue) {
+ assert fieldType == byte.class : field.getDeclaringClass() + "#" + field.getName() + " is not byte";
+
+ GridUnsafe.putByteField(target, fieldOffset, fieldValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public short getShort(Object target) {
+ assert fieldType == short.class : field.getDeclaringClass() + "#" + field.getName() + " is not short";
+
+ return GridUnsafe.getShortField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setShort(Object target, short fieldValue) {
+ assert fieldType == short.class : field.getDeclaringClass() + "#" + field.getName() + " is not short";
+
+ GridUnsafe.putShortField(target, fieldOffset, fieldValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int getInt(Object target) {
+ assert fieldType == int.class : field.getDeclaringClass() + "#" + field.getName() + " is not int";
+
+ return GridUnsafe.getIntField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setInt(Object target, int fieldValue) {
+ assert fieldType == int.class : field.getDeclaringClass() + "#" + field.getName() + " is not int";
+
+ GridUnsafe.putIntField(target, fieldOffset, fieldValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public long getLong(Object target) {
+ assert fieldType == long.class : field.getDeclaringClass() + "#" + field.getName() + " is not long";
+
+ return GridUnsafe.getLongField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setLong(Object target, long fieldValue) {
+ assert fieldType == long.class : field.getDeclaringClass() + "#" + field.getName() + " is not long";
+
+ GridUnsafe.putLongField(target, fieldOffset, fieldValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public float getFloat(Object target) {
+ assert fieldType == float.class : field.getDeclaringClass() + "#" + field.getName() + " is not float";
+
+ return GridUnsafe.getFloatField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setFloat(Object target, float fieldValue) {
+ assert fieldType == float.class : field.getDeclaringClass() + "#" + field.getName() + " is not float";
+
+ GridUnsafe.putFloatField(target, fieldOffset, fieldValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getDouble(Object target) {
+ assert fieldType == double.class : field.getDeclaringClass() + "#" + field.getName() + " is not double";
+
+ return GridUnsafe.getDoubleField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setDouble(Object target, double fieldValue) {
+ assert fieldType == double.class : field.getDeclaringClass() + "#" + field.getName() + " is not double";
+
+ GridUnsafe.putDoubleField(target, fieldOffset, fieldValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public char getChar(Object target) {
+ assert fieldType == char.class : field.getDeclaringClass() + "#" + field.getName() + " is not char";
+
+ return GridUnsafe.getCharField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setChar(Object target, char fieldValue) {
+ assert fieldType == char.class : field.getDeclaringClass() + "#" + field.getName() + " is not char";
+
+ GridUnsafe.putCharField(target, fieldOffset, fieldValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean getBoolean(Object target) {
+ assert fieldType == boolean.class : field.getDeclaringClass() + "#" + field.getName() + " is not boolean";
+
+ return GridUnsafe.getBooleanField(target, fieldOffset);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setBoolean(Object target, boolean fieldValue) {
+ assert fieldType == boolean.class : field.getDeclaringClass() + "#" + field.getName() + " is not boolean";
+
+ GridUnsafe.putBooleanField(target, fieldOffset, fieldValue);
+ }
+}
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshaller.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshaller.java
index 7842f91..4589e49 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshaller.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshaller.java
@@ -31,12 +31,11 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Map;
-import org.apache.ignite.internal.network.serialization.BuiltinType;
+import org.apache.ignite.internal.network.serialization.BuiltInType;
import org.apache.ignite.internal.network.serialization.ClassDescriptor;
import org.apache.ignite.internal.network.serialization.ClassDescriptorFactory;
import org.apache.ignite.internal.network.serialization.ClassDescriptorFactoryContext;
import org.apache.ignite.internal.network.serialization.IdIndexedDescriptors;
-import org.apache.ignite.internal.network.serialization.SerializedStreamCommands;
import org.apache.ignite.internal.network.serialization.SpecialMethodInvocationException;
import org.jetbrains.annotations.Nullable;
@@ -64,7 +63,7 @@ public class DefaultUserObjectMarshaller implements UserObjectMarshaller {
this.localDescriptors = localDescriptors;
this.descriptorFactory = descriptorFactory;
- structuredObjectMarshaller = new StructuredObjectMarshaller(this::marshalToOutput, this::unmarshalFromInput);
+ structuredObjectMarshaller = new StructuredObjectMarshaller(localDescriptors, this::marshalToOutput, this::unmarshalFromInput);
externalizableMarshaller = new ExternalizableMarshaller(
this::unmarshalFromInput,
@@ -227,7 +226,7 @@ public class DefaultUserObjectMarshaller implements UserObjectMarshaller {
} else {
// This is some custom class (not a built-in). If it's a non-built-in array, we need to handle it as a generic container.
if (objectClass.isArray()) {
- return localDescriptors.getBuiltInDescriptor(BuiltinType.OBJECT_ARRAY);
+ return localDescriptors.getBuiltInDescriptor(BuiltInType.OBJECT_ARRAY);
}
return descriptorFactory.create(objectClass);
@@ -239,7 +238,7 @@ public class DefaultUserObjectMarshaller implements UserObjectMarshaller {
}
private void writeReference(int objectId, DataOutput output) throws IOException {
- ProtocolMarshalling.writeDescriptorOrCommandId(SerializedStreamCommands.REFERENCE, output);
+ ProtocolMarshalling.writeDescriptorOrCommandId(BuiltInType.REFERENCE.descriptorId(), output);
ProtocolMarshalling.writeObjectId(objectId, output);
}
@@ -314,7 +313,7 @@ public class DefaultUserObjectMarshaller implements UserObjectMarshaller {
private <T> T unmarshalFromInput(DataInputStream input, UnmarshallingContext context) throws IOException, UnmarshalException {
int commandOrDescriptorId = ProtocolMarshalling.readDescriptorOrCommandId(input);
- if (commandOrDescriptorId == SerializedStreamCommands.REFERENCE) {
+ if (commandOrDescriptorId == BuiltInType.REFERENCE.descriptorId()) {
return unmarshalReference(input, context);
}
diff --git a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/StructuredObjectMarshaller.java b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/StructuredObjectMarshaller.java
index 71d8d89..2e6278a 100644
--- a/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/StructuredObjectMarshaller.java
+++ b/modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/StructuredObjectMarshaller.java
@@ -24,8 +24,11 @@ import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.apache.ignite.internal.network.serialization.BuiltInTypeIds;
import org.apache.ignite.internal.network.serialization.ClassDescriptor;
+import org.apache.ignite.internal.network.serialization.FieldAccessor;
import org.apache.ignite.internal.network.serialization.FieldDescriptor;
+import org.apache.ignite.internal.network.serialization.IdIndexedDescriptors;
import org.apache.ignite.internal.network.serialization.SpecialMethodInvocationException;
/**
@@ -33,12 +36,14 @@ import org.apache.ignite.internal.network.serialization.SpecialMethodInvocationE
* (which are not {@link java.io.Externalizable}s) and arbitrary (non-serializable, non-externalizable) objects.
*/
class StructuredObjectMarshaller implements DefaultFieldsReaderWriter {
+ private final IdIndexedDescriptors descriptors;
private final TypedValueWriter valueWriter;
private final ValueReader<Object> valueReader;
private final Instantiation instantiation;
- StructuredObjectMarshaller(TypedValueWriter valueWriter, ValueReader<Object> valueReader) {
+ StructuredObjectMarshaller(IdIndexedDescriptors descriptors, TypedValueWriter valueWriter, ValueReader<Object> valueReader) {
+ this.descriptors = descriptors;
this.valueWriter = valueWriter;
this.valueReader = valueReader;
@@ -77,7 +82,7 @@ class StructuredObjectMarshaller implements DefaultFieldsReaderWriter {
private void writeStructuredObjectLayer(Object object, ClassDescriptor layer, DataOutputStream output, MarshallingContext context)
throws IOException, MarshalException {
- if (layer.hasSerializationOverride()) {
+ if (layer.hasWriteObject()) {
writeWithWriteObject(object, layer, output, context);
} else {
defaultWriteFields(object, layer, output, context);
@@ -113,9 +118,47 @@ class StructuredObjectMarshaller implements DefaultFieldsReaderWriter {
private void writeField(Object object, FieldDescriptor fieldDescriptor, DataOutputStream output, MarshallingContext context)
throws MarshalException, IOException {
- Object fieldValue = fieldDescriptor.accessor().get(object);
+ if (fieldDescriptor.clazz().isPrimitive()) {
+ writePrimitiveFieldValue(object, fieldDescriptor, output);
- valueWriter.write(fieldValue, fieldDescriptor.clazz(), output, context);
+ context.addUsedDescriptor(descriptors.getRequiredDescriptor(fieldDescriptor.typeDescriptorId()));
+ } else {
+ Object fieldValue = fieldDescriptor.accessor().getObject(object);
+ valueWriter.write(fieldValue, fieldDescriptor.clazz(), output, context);
+ }
+ }
+
+ private void writePrimitiveFieldValue(Object object, FieldDescriptor fieldDescriptor, DataOutputStream output) throws IOException {
+ FieldAccessor fieldAccessor = fieldDescriptor.accessor();
+
+ switch (fieldDescriptor.typeDescriptorId()) {
+ case BuiltInTypeIds.BYTE:
+ output.writeByte(fieldAccessor.getByte(object));
+ break;
+ case BuiltInTypeIds.SHORT:
+ output.writeShort(fieldAccessor.getShort(object));
+ break;
+ case BuiltInTypeIds.INT:
+ output.writeInt(fieldAccessor.getInt(object));
+ break;
+ case BuiltInTypeIds.LONG:
+ output.writeLong(fieldAccessor.getLong(object));
+ break;
+ case BuiltInTypeIds.FLOAT:
+ output.writeFloat(fieldAccessor.getFloat(object));
+ break;
+ case BuiltInTypeIds.DOUBLE:
+ output.writeDouble(fieldAccessor.getDouble(object));
+ break;
+ case BuiltInTypeIds.CHAR:
+ output.writeChar(fieldAccessor.getChar(object));
+ break;
+ case BuiltInTypeIds.BOOLEAN:
+ output.writeBoolean(fieldAccessor.getBoolean(object));
+ break;
+ default:
+ throw new IllegalStateException(fieldDescriptor.clazz() + " is primitive but not covered");
+ }
}
Object preInstantiateStructuredObject(ClassDescriptor descriptor) throws UnmarshalException {
@@ -135,7 +178,7 @@ class StructuredObjectMarshaller implements DefaultFieldsReaderWriter {
private void fillStructuredObjectLayerFrom(DataInputStream input, ClassDescriptor layer, Object object, UnmarshallingContext context)
throws IOException, UnmarshalException {
- if (layer.hasSerializationOverride()) {
+ if (layer.hasReadObject()) {
fillObjectWithReadObjectFrom(input, object, layer, context);
} else {
defaultFillFieldsFrom(input, object, layer, context);
@@ -166,13 +209,50 @@ class StructuredObjectMarshaller implements DefaultFieldsReaderWriter {
public void defaultFillFieldsFrom(DataInputStream input, Object object, ClassDescriptor descriptor, UnmarshallingContext context)
throws IOException, UnmarshalException {
for (FieldDescriptor fieldDescriptor : descriptor.fields()) {
- Object fieldValue = valueReader.read(input, context);
- setFieldValue(object, fieldDescriptor, fieldValue);
+ fillFieldFrom(input, object, context, fieldDescriptor);
}
}
- private void setFieldValue(Object target, FieldDescriptor fieldDescriptor, Object value) {
- fieldDescriptor.accessor().set(target, value);
+ private void fillFieldFrom(DataInputStream input, Object object, UnmarshallingContext context, FieldDescriptor fieldDescriptor)
+ throws IOException, UnmarshalException {
+ if (fieldDescriptor.clazz().isPrimitive()) {
+ fillPrimitiveFieldFrom(input, object, fieldDescriptor);
+ } else {
+ Object fieldValue = valueReader.read(input, context);
+ fieldDescriptor.accessor().setObject(object, fieldValue);
+ }
}
+ private void fillPrimitiveFieldFrom(DataInputStream input, Object object, FieldDescriptor fieldDescriptor) throws IOException {
+ FieldAccessor fieldAccessor = fieldDescriptor.accessor();
+
+ switch (fieldDescriptor.typeDescriptorId()) {
+ case BuiltInTypeIds.BYTE:
+ fieldAccessor.setByte(object, input.readByte());
+ break;
+ case BuiltInTypeIds.SHORT:
+ fieldAccessor.setShort(object, input.readShort());
+ break;
+ case BuiltInTypeIds.INT:
+ fieldAccessor.setInt(object, input.readInt());
+ break;
+ case BuiltInTypeIds.LONG:
+ fieldAccessor.setLong(object, input.readLong());
+ break;
+ case BuiltInTypeIds.FLOAT:
+ fieldAccessor.setFloat(object, input.readFloat());
+ break;
+ case BuiltInTypeIds.DOUBLE:
+ fieldAccessor.setDouble(object, input.readDouble());
+ break;
+ case BuiltInTypeIds.CHAR:
+ fieldAccessor.setChar(object, input.readChar());
+ break;
+ case BuiltInTypeIds.BOOLEAN:
+ fieldAccessor.setBoolean(object, input.readBoolean());
+ break;
+ default:
+ throw new IllegalStateException(fieldDescriptor.clazz() + " is primitive but not covered");
+ }
+ }
}
diff --git a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactoryTest.java b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactoryTest.java
index d9adb3d..5bb4d62 100644
--- a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactoryTest.java
+++ b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/ClassDescriptorFactoryTest.java
@@ -331,7 +331,7 @@ public class ClassDescriptorFactoryTest {
ClassDescriptor arbitraryDescriptor = context.getDescriptor(ArbitraryClass.class);
assertNotNull(arbitraryDescriptor);
- ClassDescriptor intDescriptor = context.getDescriptor(BuiltinType.INT.descriptorId());
+ ClassDescriptor intDescriptor = context.getDescriptor(BuiltInType.INT.descriptorId());
assertNotNull(intDescriptor);
List<FieldDescriptor> fields = holderDescriptor.fields();
@@ -398,6 +398,27 @@ public class ClassDescriptorFactoryTest {
checkSerializable(descriptor.serialization(), true, true, true);
}
+ @Test
+ void writeObjectMethodWithNonVoidReturnTypeIsIgnored() {
+ ClassDescriptor descriptor = factory.create(WithWriteObjectWithNonVoidReturnType.class);
+
+ assertFalse(descriptor.hasWriteObject());
+ }
+
+ @Test
+ void readObjectMethodWithNonVoidReturnTypeIsIgnored() {
+ ClassDescriptor descriptor = factory.create(WithReadObjectWithNonVoidReturnType.class);
+
+ assertFalse(descriptor.hasReadObject());
+ }
+
+ @Test
+ void readObjectNoDataMethodWithNonVoidReturnTypeIsIgnored() {
+ ClassDescriptor descriptor = factory.create(WithReadObjectNoDataWithNonVoidReturnType.class);
+
+ assertFalse(descriptor.hasReadObjectNoData());
+ }
+
/**
* Checks that serialization type is {@link SerializationType#ARBITRARY}.
*
@@ -405,7 +426,11 @@ public class ClassDescriptorFactoryTest {
*/
private void checkArbitraryType(Serialization serialization) {
assertEquals(ARBITRARY, serialization.type());
- assertFalse(serialization.hasSerializationOverride());
+
+ assertFalse(serialization.hasWriteObject());
+ assertFalse(serialization.hasReadObject());
+ assertFalse(serialization.hasReadObjectNoData());
+
assertFalse(serialization.hasWriteReplace());
assertFalse(serialization.hasReadResolve());
}
@@ -426,7 +451,11 @@ public class ClassDescriptorFactoryTest {
*/
private void checkSimpleExternalizable(Serialization serialization) {
assertEquals(EXTERNALIZABLE, serialization.type());
- assertFalse(serialization.hasSerializationOverride());
+
+ assertFalse(serialization.hasWriteObject());
+ assertFalse(serialization.hasReadObject());
+ assertFalse(serialization.hasReadObjectNoData());
+
assertFalse(serialization.hasWriteReplace());
assertFalse(serialization.hasReadResolve());
}
@@ -442,7 +471,9 @@ public class ClassDescriptorFactoryTest {
private void checkSerializable(Serialization serialization, boolean override, boolean writeReplace, boolean readResolve) {
assertEquals(SERIALIZABLE, serialization.type());
- assertEquals(override, serialization.hasSerializationOverride());
+ assertEquals(override, serialization.hasWriteObject());
+ assertEquals(override, serialization.hasReadObject());
+
assertEquals(writeReplace, serialization.hasWriteReplace());
assertEquals(readResolve, serialization.hasReadResolve());
}
@@ -512,4 +543,25 @@ public class ClassDescriptorFactoryTest {
private static class ExtendsObject {
}
+
+ private static class WithWriteObjectWithNonVoidReturnType implements Serializable {
+ @SuppressWarnings("unused")
+ private Object writeObject(ObjectOutputStream stream) {
+ return null;
+ }
+ }
+
+ private static class WithReadObjectWithNonVoidReturnType implements Serializable {
+ @SuppressWarnings("unused")
+ private Object readObject(ObjectInputStream stream) {
+ return null;
+ }
+ }
+
+ private static class WithReadObjectNoDataWithNonVoidReturnType implements Serializable {
+ @SuppressWarnings("unused")
+ private Object readObjectNoData(ObjectInputStream stream) {
+ return null;
+ }
+ }
}
diff --git a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/DefaultDescriptorsTest.java b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/DefaultDescriptorsTest.java
index 1faf851..0a29655 100644
--- a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/DefaultDescriptorsTest.java
+++ b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/DefaultDescriptorsTest.java
@@ -17,50 +17,51 @@
package org.apache.ignite.internal.network.serialization;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.ARRAY_LIST;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.BARE_OBJECT;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.BIT_SET;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.BOOLEAN;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.BOOLEAN_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.BOOLEAN_BOXED;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.BYTE;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.BYTE_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.BYTE_BOXED;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.CHAR;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.CHAR_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.CHAR_BOXED;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.DATE;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.DECIMAL;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.DECIMAL_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.DOUBLE;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.DOUBLE_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.DOUBLE_BOXED;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.ENUM;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.ENUM_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.FLOAT;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.FLOAT_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.FLOAT_BOXED;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.HASH_MAP;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.HASH_SET;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.IGNITE_UUID;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.INT;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.INT_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.INT_BOXED;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.LINKED_HASH_MAP;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.LINKED_HASH_SET;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.LINKED_LIST;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.LONG;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.LONG_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.LONG_BOXED;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.NULL;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.OBJECT_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.SHORT;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.SHORT_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.SHORT_BOXED;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.SINGLETON_LIST;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.STRING;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.STRING_ARRAY;
-import static org.apache.ignite.internal.network.serialization.BuiltinType.UUID;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.ARRAY_LIST;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.BARE_OBJECT;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.BIT_SET;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.BOOLEAN;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.BOOLEAN_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.BOOLEAN_BOXED;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.BYTE;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.BYTE_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.BYTE_BOXED;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.CHAR;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.CHAR_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.CHAR_BOXED;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.DATE;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.DECIMAL;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.DECIMAL_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.DOUBLE;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.DOUBLE_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.DOUBLE_BOXED;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.ENUM;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.ENUM_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.FLOAT;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.FLOAT_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.FLOAT_BOXED;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.HASH_MAP;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.HASH_SET;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.IGNITE_UUID;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.INT;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.INT_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.INT_BOXED;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.LINKED_HASH_MAP;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.LINKED_HASH_SET;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.LINKED_LIST;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.LONG;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.LONG_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.LONG_BOXED;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.NULL;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.OBJECT_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.REFERENCE;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.SHORT;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.SHORT_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.SHORT_BOXED;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.SINGLETON_LIST;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.STRING;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.STRING_ARRAY;
+import static org.apache.ignite.internal.network.serialization.BuiltInType.UUID;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
@@ -118,5 +119,6 @@ public class DefaultDescriptorsTest {
assertEquals(41, LINKED_HASH_MAP.descriptorId());
assertEquals(42, BIT_SET.descriptorId());
assertEquals(43, NULL.descriptorId());
+ assertEquals(44, REFERENCE.descriptorId());
}
}
diff --git a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithArbitraryObjectsTest.java b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithArbitraryObjectsTest.java
index b05ea35..c176151 100644
--- a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithArbitraryObjectsTest.java
+++ b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithArbitraryObjectsTest.java
@@ -26,6 +26,7 @@ import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
@@ -38,11 +39,12 @@ import java.io.DataInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
-import org.apache.ignite.internal.network.serialization.BuiltinType;
+import org.apache.ignite.internal.network.serialization.BuiltInType;
import org.apache.ignite.internal.network.serialization.ClassDescriptorFactory;
import org.apache.ignite.internal.network.serialization.ClassDescriptorFactoryContext;
import org.apache.ignite.internal.network.serialization.IdIndexedDescriptors;
@@ -91,7 +93,7 @@ class DefaultUserObjectMarshallerWithArbitraryObjectsTest {
assertThat(marshalled.usedDescriptors(), equalTo(Set.of(
descriptorRegistry.getRequiredDescriptor(Simple.class),
- descriptorRegistry.getBuiltInDescriptor(BuiltinType.INT)
+ descriptorRegistry.getBuiltInDescriptor(BuiltInType.INT)
)));
}
@@ -410,6 +412,56 @@ class DefaultUserObjectMarshallerWithArbitraryObjectsTest {
assertThat(unmarshalled.value, is(EnumWithAnonClassesForMembers.FIRST));
}
+ @Test
+ void marshalsAndUnmarshalsPrimitivesInFieldsCorrectly() throws Exception {
+ WithPrimitives unmarshalled = marshalAndUnmarshalNonNull(new WithPrimitives());
+
+ assertThat(unmarshalled.byteVal, is((byte) 1));
+ assertThat(unmarshalled.shortVal, is((short) 2));
+ assertThat(unmarshalled.intVal, is(3));
+ assertThat(unmarshalled.longVal, is(4L));
+ assertThat(unmarshalled.floatVal, is(5.0f));
+ assertThat(unmarshalled.doubleVal, is(6.0));
+ assertThat(unmarshalled.charVal, is('a'));
+ assertThat(unmarshalled.booleanVal, is(true));
+ }
+
+ @Test
+ void marshalsAndUnmarshalsPrimitiveWrappersInFieldsCorrectly() throws Exception {
+ WithPrimitiveWrappers unmarshalled = marshalAndUnmarshalNonNull(new WithPrimitiveWrappers());
+
+ assertThat(unmarshalled.byteVal, is((byte) 1));
+ assertThat(unmarshalled.shortVal, is((short) 2));
+ assertThat(unmarshalled.integerVal, is(3));
+ assertThat(unmarshalled.longVal, is(4L));
+ assertThat(unmarshalled.floatVal, is(5.0f));
+ assertThat(unmarshalled.doubleVal, is(6.0));
+ assertThat(unmarshalled.characterVal, is('a'));
+ assertThat(unmarshalled.booleanVal, is(true));
+ }
+
+ @Test
+ void unmarshalsReferencesToSameObjectOfNonBuiltInTypeToSameObject() throws Exception {
+ Simple obj = new Simple(42);
+ List<?> list = new ArrayList<>(Arrays.asList(obj, obj));
+
+ List<?> unmarshalled = marshalAndUnmarshalNonNull(list);
+
+ assertThat(unmarshalled.get(0), sameInstance(unmarshalled.get(1)));
+ }
+
+ @Test
+ void unmarshalsDifferentButEqualObjectsToDifferentObjects() throws Exception {
+ long longValue = 1_000_000;
+ String obj1 = String.valueOf(longValue);
+ String obj2 = String.valueOf(longValue);
+ List<?> list = new ArrayList<>(Arrays.asList(obj1, obj2));
+
+ List<?> unmarshalled = marshalAndUnmarshalNonNull(list);
+
+ assertThat(unmarshalled.get(0), not(sameInstance(unmarshalled.get(1))));
+ }
+
private static class Simple {
private int value;
@@ -566,4 +618,26 @@ class DefaultUserObjectMarshallerWithArbitraryObjectsTest {
this.value = value;
}
}
+
+ private static class WithPrimitives {
+ private final byte byteVal = 1;
+ private final short shortVal = 2;
+ private final int intVal = 3;
+ private final long longVal = 4L;
+ private final float floatVal = 5.0f;
+ private final double doubleVal = 6.0;
+ private final char charVal = 'a';
+ private final boolean booleanVal = true;
+ }
+
+ private static class WithPrimitiveWrappers {
+ private final Byte byteVal = 1;
+ private final Short shortVal = 2;
+ private final Integer integerVal = 3;
+ private final Long longVal = 4L;
+ private final Float floatVal = 5.0f;
+ private final Double doubleVal = 6.0;
+ private final Character characterVal = 'a';
+ private final Boolean booleanVal = true;
+ }
}
diff --git a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithBuiltinsTest.java b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithBuiltinsTest.java
index 3c25458..a388f0a 100644
--- a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithBuiltinsTest.java
+++ b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithBuiltinsTest.java
@@ -47,7 +47,7 @@ import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
-import org.apache.ignite.internal.network.serialization.BuiltinType;
+import org.apache.ignite.internal.network.serialization.BuiltInType;
import org.apache.ignite.internal.network.serialization.ClassDescriptor;
import org.apache.ignite.internal.network.serialization.ClassDescriptorFactory;
import org.apache.ignite.internal.network.serialization.ClassDescriptorFactoryContext;
@@ -97,7 +97,7 @@ class DefaultUserObjectMarshallerWithBuiltinsTest {
void marshalsBareObjectWithCorrectDescriptorIdInMarshalledRepresentation() throws Exception {
MarshalledObject marshalled = marshaller.marshal(new Object());
- assertThat(readDescriptorId(marshalled), is(BuiltinType.BARE_OBJECT.descriptorId()));
+ assertThat(readDescriptorId(marshalled), is(BuiltInType.BARE_OBJECT.descriptorId()));
}
private int readDescriptorId(MarshalledObject marshalled) throws IOException {
@@ -141,7 +141,7 @@ class DefaultUserObjectMarshallerWithBuiltinsTest {
Object unmarshalled = marshaller.unmarshal(marshalled.bytes(), descriptors);
assertThat(unmarshalled, is(equalTo(typeValue.value)));
- if (typeValue.builtinType != BuiltinType.NULL && typeValue.value.getClass().isArray()) {
+ if (typeValue.builtinType != BuiltInType.NULL && typeValue.value.getClass().isArray()) {
assertThat(unmarshalled, is(notNullValue()));
assertThat(unmarshalled.getClass().getComponentType(), is(typeValue.value.getClass().getComponentType()));
}
@@ -152,7 +152,7 @@ class DefaultUserObjectMarshallerWithBuiltinsTest {
void marshalsUsingOnlyCorrespondingDescriptorForBuiltInNonCollectionTypes(BuiltInTypeValue typeValue) {
// #marshalsObjectArrayUsingExactlyDescriptorsOfObjectArrayAndComponents() checks the same for OBJECT_ARRAY
- assumingThat(typeValue.builtinType != BuiltinType.OBJECT_ARRAY, () -> {
+ assumingThat(typeValue.builtinType != BuiltInType.OBJECT_ARRAY, () -> {
MarshalledObject marshalled = marshaller.marshal(typeValue.value, typeValue.valueClass);
ClassDescriptor expectedDescriptor = descriptorRegistry.getBuiltInDescriptor(typeValue.builtinType);
@@ -162,56 +162,56 @@ class DefaultUserObjectMarshallerWithBuiltinsTest {
static Stream<Arguments> builtInNonCollectionTypes() {
return Stream.of(
- builtInTypeValue((byte) 42, byte.class, BuiltinType.BYTE),
- builtInTypeValue((byte) 42, Byte.class, BuiltinType.BYTE_BOXED),
- builtInTypeValue((short) 42, short.class, BuiltinType.SHORT),
- builtInTypeValue((short) 42, Short.class, BuiltinType.SHORT_BOXED),
- builtInTypeValue(42, int.class, BuiltinType.INT),
- builtInTypeValue(42, Integer.class, BuiltinType.INT_BOXED),
- builtInTypeValue(42.0f, float.class, BuiltinType.FLOAT),
- builtInTypeValue(42.0f, Float.class, BuiltinType.FLOAT_BOXED),
- builtInTypeValue((long) 42, long.class, BuiltinType.LONG),
- builtInTypeValue((long) 42, Long.class, BuiltinType.LONG_BOXED),
- builtInTypeValue(42.0, double.class, BuiltinType.DOUBLE),
- builtInTypeValue(42.0, Double.class, BuiltinType.DOUBLE_BOXED),
- builtInTypeValue(true, boolean.class, BuiltinType.BOOLEAN),
- builtInTypeValue(true, Boolean.class, BuiltinType.BOOLEAN_BOXED),
- builtInTypeValue('a', char.class, BuiltinType.CHAR),
- builtInTypeValue('a', Character.class, BuiltinType.CHAR_BOXED),
+ builtInTypeValue((byte) 42, byte.class, BuiltInType.BYTE),
+ builtInTypeValue((byte) 42, Byte.class, BuiltInType.BYTE_BOXED),
+ builtInTypeValue((short) 42, short.class, BuiltInType.SHORT),
+ builtInTypeValue((short) 42, Short.class, BuiltInType.SHORT_BOXED),
+ builtInTypeValue(42, int.class, BuiltInType.INT),
+ builtInTypeValue(42, Integer.class, BuiltInType.INT_BOXED),
+ builtInTypeValue(42.0f, float.class, BuiltInType.FLOAT),
+ builtInTypeValue(42.0f, Float.class, BuiltInType.FLOAT_BOXED),
+ builtInTypeValue((long) 42, long.class, BuiltInType.LONG),
+ builtInTypeValue((long) 42, Long.class, BuiltInType.LONG_BOXED),
+ builtInTypeValue(42.0, double.class, BuiltInType.DOUBLE),
+ builtInTypeValue(42.0, Double.class, BuiltInType.DOUBLE_BOXED),
+ builtInTypeValue(true, boolean.class, BuiltInType.BOOLEAN),
+ builtInTypeValue(true, Boolean.class, BuiltInType.BOOLEAN_BOXED),
+ builtInTypeValue('a', char.class, BuiltInType.CHAR),
+ builtInTypeValue('a', Character.class, BuiltInType.CHAR_BOXED),
// BARE_OBJECT is handled separately
- builtInTypeValue("abc", String.class, BuiltinType.STRING),
- builtInTypeValue(UUID.fromString("c6f57d4a-619f-11ec-add6-73bc97c3c49e"), UUID.class, BuiltinType.UUID),
+ builtInTypeValue("abc", String.class, BuiltInType.STRING),
+ builtInTypeValue(UUID.fromString("c6f57d4a-619f-11ec-add6-73bc97c3c49e"), UUID.class, BuiltInType.UUID),
builtInTypeValue(IgniteUuid.fromString("1234-c6f57d4a-619f-11ec-add6-73bc97c3c49e"), IgniteUuid.class,
- BuiltinType.IGNITE_UUID),
- builtInTypeValue(new Date(42), Date.class, BuiltinType.DATE),
- builtInTypeValue(new byte[]{1, 2, 3}, byte[].class, BuiltinType.BYTE_ARRAY),
- builtInTypeValue(new short[]{1, 2, 3}, short[].class, BuiltinType.SHORT_ARRAY),
- builtInTypeValue(new int[]{1, 2, 3}, int[].class, BuiltinType.INT_ARRAY),
- builtInTypeValue(new float[]{1.0f, 2.0f, 3.0f}, float[].class, BuiltinType.FLOAT_ARRAY),
- builtInTypeValue(new long[]{1, 2, 3}, long[].class, BuiltinType.LONG_ARRAY),
- builtInTypeValue(new double[]{1.0, 2.0, 3.0}, double[].class, BuiltinType.DOUBLE_ARRAY),
- builtInTypeValue(new boolean[]{true, false}, boolean[].class, BuiltinType.BOOLEAN_ARRAY),
- builtInTypeValue(new char[]{'a', 'b'}, char[].class, BuiltinType.CHAR_ARRAY),
- builtInTypeValue(new Object[]{42, "123", null}, Object[].class, BuiltinType.OBJECT_ARRAY),
+ BuiltInType.IGNITE_UUID),
+ builtInTypeValue(new Date(42), Date.class, BuiltInType.DATE),
+ builtInTypeValue(new byte[]{1, 2, 3}, byte[].class, BuiltInType.BYTE_ARRAY),
+ builtInTypeValue(new short[]{1, 2, 3}, short[].class, BuiltInType.SHORT_ARRAY),
+ builtInTypeValue(new int[]{1, 2, 3}, int[].class, BuiltInType.INT_ARRAY),
+ builtInTypeValue(new float[]{1.0f, 2.0f, 3.0f}, float[].class, BuiltInType.FLOAT_ARRAY),
+ builtInTypeValue(new long[]{1, 2, 3}, long[].class, BuiltInType.LONG_ARRAY),
+ builtInTypeValue(new double[]{1.0, 2.0, 3.0}, double[].class, BuiltInType.DOUBLE_ARRAY),
+ builtInTypeValue(new boolean[]{true, false}, boolean[].class, BuiltInType.BOOLEAN_ARRAY),
+ builtInTypeValue(new char[]{'a', 'b'}, char[].class, BuiltInType.CHAR_ARRAY),
+ builtInTypeValue(new Object[]{42, "123", null}, Object[].class, BuiltInType.OBJECT_ARRAY),
builtInTypeValue(new BitSet[]{BitSet.valueOf(new long[]{42, 43}), BitSet.valueOf(new long[]{1, 2}), null},
- BitSet[].class, BuiltinType.OBJECT_ARRAY),
- builtInTypeValue(new String[]{"Ignite", "rulez"}, String[].class, BuiltinType.STRING_ARRAY),
- builtInTypeValue(new BigDecimal(42), BigDecimal.class, BuiltinType.DECIMAL),
+ BitSet[].class, BuiltInType.OBJECT_ARRAY),
+ builtInTypeValue(new String[]{"Ignite", "rulez"}, String[].class, BuiltInType.STRING_ARRAY),
+ builtInTypeValue(new BigDecimal(42), BigDecimal.class, BuiltInType.DECIMAL),
builtInTypeValue(new BigDecimal[]{new BigDecimal(42), new BigDecimal(43)}, BigDecimal[].class,
- BuiltinType.DECIMAL_ARRAY),
- builtInTypeValue(SimpleEnum.FIRST, SimpleEnum.class, BuiltinType.ENUM),
- builtInTypeValue(new Enum[]{SimpleEnum.FIRST, SimpleEnum.SECOND}, Enum[].class, BuiltinType.ENUM_ARRAY),
- builtInTypeValue(new SimpleEnum[]{SimpleEnum.FIRST, SimpleEnum.SECOND}, SimpleEnum[].class, BuiltinType.ENUM_ARRAY),
- builtInTypeValue(EnumWithAnonClassesForMembers.FIRST, EnumWithAnonClassesForMembers.class, BuiltinType.ENUM),
+ BuiltInType.DECIMAL_ARRAY),
+ builtInTypeValue(SimpleEnum.FIRST, SimpleEnum.class, BuiltInType.ENUM),
+ builtInTypeValue(new Enum[]{SimpleEnum.FIRST, SimpleEnum.SECOND}, Enum[].class, BuiltInType.ENUM_ARRAY),
+ builtInTypeValue(new SimpleEnum[]{SimpleEnum.FIRST, SimpleEnum.SECOND}, SimpleEnum[].class, BuiltInType.ENUM_ARRAY),
+ builtInTypeValue(EnumWithAnonClassesForMembers.FIRST, EnumWithAnonClassesForMembers.class, BuiltInType.ENUM),
builtInTypeValue(new Enum[]{EnumWithAnonClassesForMembers.FIRST, EnumWithAnonClassesForMembers.SECOND}, Enum[].class,
- BuiltinType.ENUM_ARRAY),
+ BuiltInType.ENUM_ARRAY),
builtInTypeValue(
new EnumWithAnonClassesForMembers[]{EnumWithAnonClassesForMembers.FIRST, EnumWithAnonClassesForMembers.SECOND},
EnumWithAnonClassesForMembers[].class,
- BuiltinType.ENUM_ARRAY
+ BuiltInType.ENUM_ARRAY
),
- builtInTypeValue(BitSet.valueOf(new long[]{42, 43}), BitSet.class, BuiltinType.BIT_SET),
- builtInTypeValue(null, Null.class, BuiltinType.NULL)
+ builtInTypeValue(BitSet.valueOf(new long[]{42, 43}), BitSet.class, BuiltInType.BIT_SET),
+ builtInTypeValue(null, Null.class, BuiltInType.NULL)
).map(Arguments::of);
}
@@ -242,19 +242,19 @@ class DefaultUserObjectMarshallerWithBuiltinsTest {
assertThat(marshalled.usedDescriptors(), containsInAnyOrder(
descriptorRegistry.getBuiltInDescriptor(typeValue.builtinType),
- descriptorRegistry.getBuiltInDescriptor(BuiltinType.INT_BOXED)
+ descriptorRegistry.getBuiltInDescriptor(BuiltInType.INT_BOXED)
));
}
static Stream<Arguments> builtInCollectionTypes() {
return Stream.of(
- builtInTypeValue(new ArrayList<>(List.of(42, 43)), ArrayList.class, BuiltinType.ARRAY_LIST),
- builtInTypeValue(new LinkedList<>(List.of(42, 43)), LinkedList.class, BuiltinType.LINKED_LIST),
- builtInTypeValue(new HashSet<>(Set.of(42, 43)), HashSet.class, BuiltinType.HASH_SET),
- builtInTypeValue(new LinkedHashSet<>(Set.of(42, 43)), LinkedHashSet.class, BuiltinType.LINKED_HASH_SET),
- builtInTypeValue(singletonList(42), BuiltinType.SINGLETON_LIST.clazz(), BuiltinType.SINGLETON_LIST),
- builtInTypeValue(new HashMap<>(Map.of(42, 43)), HashMap.class, BuiltinType.HASH_MAP),
- builtInTypeValue(new LinkedHashMap<>(Map.of(42, 43)), LinkedHashMap.class, BuiltinType.LINKED_HASH_MAP)
+ builtInTypeValue(new ArrayList<>(List.of(42, 43)), ArrayList.class, BuiltInType.ARRAY_LIST),
+ builtInTypeValue(new LinkedList<>(List.of(42, 43)), LinkedList.class, BuiltInType.LINKED_LIST),
+ builtInTypeValue(new HashSet<>(Set.of(42, 43)), HashSet.class, BuiltInType.HASH_SET),
+ builtInTypeValue(new LinkedHashSet<>(Set.of(42, 43)), LinkedHashSet.class, BuiltInType.LINKED_HASH_SET),
+ builtInTypeValue(singletonList(42), BuiltInType.SINGLETON_LIST.clazz(), BuiltInType.SINGLETON_LIST),
+ builtInTypeValue(new HashMap<>(Map.of(42, 43)), HashMap.class, BuiltInType.HASH_MAP),
+ builtInTypeValue(new LinkedHashMap<>(Map.of(42, 43)), LinkedHashMap.class, BuiltInType.LINKED_HASH_MAP)
).map(Arguments::of);
}
@@ -270,7 +270,7 @@ class DefaultUserObjectMarshallerWithBuiltinsTest {
return Stream.concat(builtInNonCollectionTypes(), builtInCollectionTypes());
}
- private static BuiltInTypeValue builtInTypeValue(Object value, Class<?> valueClass, BuiltinType type) {
+ private static BuiltInTypeValue builtInTypeValue(Object value, Class<?> valueClass, BuiltInType type) {
return new BuiltInTypeValue(value, valueClass, type);
}
@@ -333,9 +333,9 @@ class DefaultUserObjectMarshallerWithBuiltinsTest {
private static class BuiltInTypeValue {
private final Object value;
private final Class<?> valueClass;
- private final BuiltinType builtinType;
+ private final BuiltInType builtinType;
- private BuiltInTypeValue(Object value, Class<?> valueClass, BuiltinType builtinType) {
+ private BuiltInTypeValue(Object value, Class<?> valueClass, BuiltInType builtinType) {
this.value = value;
this.valueClass = valueClass;
this.builtinType = builtinType;
diff --git a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithSerializableOverrideStreamsTest.java b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithSerializableOverrideStreamsTest.java
index 74aee61..d8f91f9 100644
--- a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithSerializableOverrideStreamsTest.java
+++ b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithSerializableOverrideStreamsTest.java
@@ -37,7 +37,6 @@ import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Objects;
import java.util.stream.Stream;
-import org.apache.ignite.internal.network.serialization.BuiltinType;
import org.apache.ignite.internal.network.serialization.ClassDescriptorFactory;
import org.apache.ignite.internal.network.serialization.ClassDescriptorFactoryContext;
import org.apache.ignite.internal.network.serialization.IdIndexedDescriptors;
@@ -332,7 +331,6 @@ class DefaultUserObjectMarshallerWithSerializableOverrideStreamsTest {
byte[] overrideBytes = readOverrideBytes(marshalled);
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(overrideBytes));
- assertThat(ProtocolMarshalling.readDescriptorOrCommandId(dis), is(BuiltinType.INT.descriptorId()));
assertThat(dis.readInt(), is(42));
assertThatDrained(dis);
}
diff --git a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithSerializableTest.java b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithSerializableTest.java
index b1cbc8e..898ac81 100644
--- a/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithSerializableTest.java
+++ b/modules/network/src/test/java/org/apache/ignite/internal/network/serialization/marshal/DefaultUserObjectMarshallerWithSerializableTest.java
@@ -63,6 +63,8 @@ class DefaultUserObjectMarshallerWithSerializableTest {
private static boolean nonSerializableParentConstructorCalled;
private static boolean constructorCalled;
+ private static boolean writeObjectCalled;
+ private static boolean readObjectCalled;
@Test
void marshalsAndUnmarshalsSerializable() throws Exception {
@@ -239,6 +241,20 @@ class DefaultUserObjectMarshallerWithSerializableTest {
assertThat(deserialized.ref.ref, is(not(sameInstance(deserialized))));
}
+ @Test
+ void invokesWriteObjectEvenWhenThereIsNoReadObject() throws Exception {
+ marshalAndUnmarshalNonNull(new WithWriteObjectButNoReadObject());
+
+ assertTrue(writeObjectCalled);
+ }
+
+ @Test
+ void invokesReadObjectEvenWhenThereIsNoWriteObject() throws Exception {
+ marshalAndUnmarshalNonNull(new WithReadObjectButNoWriteObject());
+
+ assertTrue(readObjectCalled);
+ }
+
/**
* An {@link Serializable} that does not have {@code writeReplace()}/{@code readResolve()} methods or other customizations.
*/
@@ -482,4 +498,16 @@ class DefaultUserObjectMarshallerWithSerializableTest {
return new IndirectSelfRefWithResolveToSelf(value + READ_RESOLVE_INCREMENT, ref);
}
}
+
+ private static class WithWriteObjectButNoReadObject implements Serializable {
+ private void writeObject(ObjectOutputStream stream) {
+ writeObjectCalled = true;
+ }
+ }
+
+ private static class WithReadObjectButNoWriteObject implements Serializable {
+ private void readObject(ObjectInputStream stream) {
+ readObjectCalled = true;
+ }
+ }
}