#ignite-gg-9924: add fix for marshalling from 6.6.4
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/75ea4a3d Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/75ea4a3d Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/75ea4a3d Branch: refs/heads/ignite-443 Commit: 75ea4a3d6f8bd680a3ffd4a8a4d1b2b6489ed1c6 Parents: 448e9c3 Author: ivasilinets <ivasilin...@gridgain.com> Authored: Thu Mar 19 20:31:49 2015 +0300 Committer: ivasilinets <ivasilin...@gridgain.com> Committed: Thu Mar 19 20:31:49 2015 +0300 ---------------------------------------------------------------------- .../optimized/OptimizedClassDescriptor.java | 268 ++++++++++++------- .../optimized/OptimizedObjectInputStream.java | 91 ++++--- .../optimized/OptimizedObjectOutputStream.java | 64 ++--- ...arshallerSerialPersistentFieldsSelfTest.java | 107 ++++++++ .../IgniteMarshallerSelfTestSuite.java | 1 + 5 files changed, 367 insertions(+), 164 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/75ea4a3d/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java index 9eaf7af..05ef534 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java @@ -18,8 +18,7 @@ package org.apache.ignite.marshaller.optimized; import org.apache.ignite.internal.util.*; -import org.apache.ignite.internal.util.typedef.*; -import org.apache.ignite.lang.*; +import org.apache.ignite.internal.util.typedef.internal.*; import org.apache.ignite.marshaller.*; import sun.misc.*; @@ -337,10 +336,7 @@ class OptimizedClassDescriptor { writeObjMtds = new ArrayList<>(); readObjMtds = new ArrayList<>(); - List<List<Field>> fields = new ArrayList<>(); - List<List<T2<OptimizedFieldType, Long>>> fieldOffs = new ArrayList<>(); - List<Map<String, IgniteBiTuple<Integer, OptimizedFieldType>>> fieldInfoMaps = new ArrayList<>(); - List<List<IgniteBiTuple<Integer, OptimizedFieldType>>> fieldInfoLists = new ArrayList<>(); + List<ClassFields> fields = new ArrayList<>(); for (c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) { Method mtd; @@ -381,33 +377,14 @@ class OptimizedClassDescriptor { Field[] clsFields0 = c.getDeclaredFields(); - Arrays.sort(clsFields0, new Comparator<Field>() { - @Override public int compare(Field f1, Field f2) { - return f1.getName().compareTo(f2.getName()); - } - }); - - List<Field> clsFields = new ArrayList<>(clsFields0.length); - List<T2<OptimizedFieldType, Long>> clsFieldOffs = - new ArrayList<>(clsFields0.length); - - for (int i = 0; i < clsFields0.length; i++) { - Field f = clsFields0[i]; - - int mod = f.getModifiers(); - - if (!isStatic(mod) && !isTransient(mod)) { - OptimizedFieldType type = fieldType(f.getType()); + Map<String, Field> fieldNames = new HashMap<>(); - clsFields.add(f); - clsFieldOffs.add(new T2<>(type, UNSAFE.objectFieldOffset(f))); - } - } + for (Field f : clsFields0) + fieldNames.put(f.getName(), f); - fields.add(clsFields); - fieldOffs.add(clsFieldOffs); + List<FieldInfo> clsFields = new ArrayList<>(clsFields0.length); - Map<String, IgniteBiTuple<Integer, OptimizedFieldType>> fieldInfoMap = null; + boolean hasSerialPersistentFields = false; try { Field serFieldsDesc = c.getDeclaredField("serialPersistentFields"); @@ -416,16 +393,33 @@ class OptimizedClassDescriptor { if (serFieldsDesc.getType() == ObjectStreamField[].class && isPrivate(mod) && isStatic(mod) && isFinal(mod)) { - serFieldsDesc.setAccessible(true); + hasSerialPersistentFields = true; - ObjectStreamField[] serFields = (ObjectStreamField[])serFieldsDesc.get(null); + serFieldsDesc.setAccessible(true); - fieldInfoMap = new HashMap<>(); + ObjectStreamField[] serFields = (ObjectStreamField[]) serFieldsDesc.get(null); for (int i = 0; i < serFields.length; i++) { ObjectStreamField serField = serFields[i]; - fieldInfoMap.put(serField.getName(), F.t(i, fieldType(serField.getType()))); + FieldInfo fieldInfo; + + if (!fieldNames.containsKey(serField.getName())) { + fieldInfo = new FieldInfo(null, + serField.getName(), + -1, + fieldType(serField.getType())); + } + else { + Field f = fieldNames.get(serField.getName()); + + fieldInfo = new FieldInfo(f, + serField.getName(), + UNSAFE.objectFieldOffset(f), + fieldType(serField.getType())); + } + + clsFields.add(fieldInfo); } } } @@ -437,39 +431,35 @@ class OptimizedClassDescriptor { cls.getName(), e); } - if (fieldInfoMap == null) { - fieldInfoMap = new HashMap<>(); + if (!hasSerialPersistentFields) { + for (int i = 0; i < clsFields0.length; i++) { + Field f = clsFields0[i]; + + int mod = f.getModifiers(); - for (int i = 0; i < clsFields.size(); i++) { - Field f = clsFields.get(i); + if (!isStatic(mod) && !isTransient(mod)) { + FieldInfo fieldInfo = new FieldInfo(f, f.getName(), + UNSAFE.objectFieldOffset(f), fieldType(f.getType())); - fieldInfoMap.put(f.getName(), F.t(i, fieldType(f.getType()))); + clsFields.add(fieldInfo); + } } } - fieldInfoMaps.add(fieldInfoMap); - - List<IgniteBiTuple<Integer, OptimizedFieldType>> fieldInfoList = - new ArrayList<>(fieldInfoMap.values()); - - Collections.sort(fieldInfoList, new Comparator<IgniteBiTuple<Integer, OptimizedFieldType>>() { - @Override public int compare(IgniteBiTuple<Integer, OptimizedFieldType> t1, - IgniteBiTuple<Integer, OptimizedFieldType> t2) { - return t1.get1().compareTo(t2.get1()); + Collections.sort(clsFields, new Comparator<FieldInfo>() { + @Override public int compare(FieldInfo t1, FieldInfo t2) { + return t1.name().compareTo(t2.name()); } }); - fieldInfoLists.add(fieldInfoList); + fields.add(new ClassFields(clsFields)); } Collections.reverse(writeObjMtds); Collections.reverse(readObjMtds); Collections.reverse(fields); - Collections.reverse(fieldOffs); - Collections.reverse(fieldInfoMaps); - Collections.reverse(fieldInfoLists); - this.fields = new Fields(fields, fieldOffs, fieldInfoLists, fieldInfoMaps); + this.fields = new Fields(fields); } } } @@ -810,76 +800,166 @@ class OptimizedClassDescriptor { } /** - * Encapsulates data about class fields. + * Information about one field. */ @SuppressWarnings("PackageVisibleInnerClass") - static class Fields { - /** Fields. */ - private final List<List<Field>> fields; + static class FieldInfo { + /** Field. */ + private final Field field; - /** Fields offsets. */ - private final List<List<T2<OptimizedFieldType, Long>>> fieldOffs; + /** Field offset. */ + private final long fieldOffs; - /** Fields details lists. */ - private final List<List<IgniteBiTuple<Integer, OptimizedFieldType>>> fieldInfoLists; + /** Field type. */ + private final OptimizedFieldType fieldType; - /** Fields details maps. */ - private final List<Map<String, IgniteBiTuple<Integer, OptimizedFieldType>>> fieldInfoMaps; + /** Field name. */ + private final String fieldName; /** - * Creates new instance. - * - * @param fields Fields. - * @param fieldOffs Field offsets. - * @param fieldInfoLists List of field details sequences for each type in the object's class hierarchy. - * @param fieldInfoMaps List of field details maps for each type in the object's class hierarchy. + * @param field Field. + * @param name Field name. + * @param offset Field offset. + * @param type Grid optimized field type. + */ + FieldInfo(Field field, String name, long offset, OptimizedFieldType type) { + this.field = field; + fieldOffs = offset; + fieldType = type; + fieldName = name; + } + + /** + * @return Returns field. + */ + Field field() { + return field; + } + + /** + * @return Offset. + */ + long offset() { + return fieldOffs; + } + + /** + * @return Type. + */ + OptimizedFieldType type() { + return fieldType; + } + + /** + * @return Name. + */ + String name() { + return fieldName; + } + } + + /** + * Information about one class. + */ + static class ClassFields { + /** Fields. */ + private final List<FieldInfo> fields; + + private final Map<String, Integer> nameToIndex; + + /** + * @param fields Field infos. */ - Fields(List<List<Field>> fields, List<List<T2<OptimizedFieldType, Long>>> fieldOffs, - List<List<IgniteBiTuple<Integer, OptimizedFieldType>>> fieldInfoLists, - List<Map<String, IgniteBiTuple<Integer, OptimizedFieldType>>> fieldInfoMaps) { + ClassFields(List<FieldInfo> fields) { this.fields = fields; - this.fieldOffs = fieldOffs; - this.fieldInfoLists = fieldInfoLists; - this.fieldInfoMaps = fieldInfoMaps; + + nameToIndex = U.newHashMap(fields.size()); + + for (int i = 0; i < fields.size(); ++i) + nameToIndex.put(fields.get(i).name(), i); } /** - * Returns class's own fields (excluding inherited). - * - * @return List of fields or {@code null} if fields list is empty. + * @return Class fields. */ - List<Field> ownFields() { - return fields.isEmpty() ? null : fields.get(fields.size() - 1); + List<FieldInfo> fields() { + return fields; } /** - * Returns field types and their offsets. + * @return Fields count. + */ + int size() { + return fields.size(); + } + + /** + * @param i Field's index. + * @return FieldInfo. + */ + FieldInfo get(int i) { + return fields.get(i); + } + + /** + * @param name Field's name. + * @return Field's index. + */ + int getIndex(String name) { + assert nameToIndex.containsKey(name); + + return nameToIndex.get(name); + } + } + + /** + * Encapsulates data about class fields. + */ + @SuppressWarnings("PackageVisibleInnerClass") + static class Fields { + /** Fields. */ + private final List<ClassFields> fields; + + /** Own fields (excluding inherited). */ + private final List<Field> ownFields; + + /** + * Creates new instance. * - * @param i hierarchy level where 0 corresponds to top level. - * @return list of pairs where first value is field type and second value is its offset. + * @param fields Fields. */ - List<T2<OptimizedFieldType, Long>> fieldOffs(int i) { - return fieldOffs.get(i); + Fields(List<ClassFields> fields) { + this.fields = fields; + + if (fields.isEmpty()) + ownFields = null; + else { + ownFields = new ArrayList<>(fields.size()); + + for (FieldInfo f : fields.get(fields.size() - 1).fields()) { + if (f.field() != null) + ownFields.add(f.field); + } + } } /** - * Returns field sequence numbers and their types as list. + * Returns class's own fields (excluding inherited). * - * @param i hierarchy level where 0 corresponds to top level. - * @return list of pairs (field number, field type) for the given hierarchy level. + * @return List of fields or {@code null} if fields list is empty. */ - List<IgniteBiTuple<Integer, OptimizedFieldType>> fieldInfoList(int i) { - return fieldInfoLists.get(i); + List<Field> ownFields() { + return ownFields; } /** - * Returns field sequence numbers and their types as map where key is a field name, + * Returns field types and their offsets. * * @param i hierarchy level where 0 corresponds to top level. - * @return map of field names and their details. + * @return list of pairs where first value is field type and second value is its offset. */ - Map<String, IgniteBiTuple<Integer, OptimizedFieldType>> fieldInfoMap(int i) { - return fieldInfoMaps.get(i); + ClassFields fields(int i) { + return fields.get(i); } } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/75ea4a3d/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java index f8c6e46..6d02eeb 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java @@ -20,9 +20,7 @@ package org.apache.ignite.marshaller.optimized; import org.apache.ignite.*; import org.apache.ignite.internal.util.*; import org.apache.ignite.internal.util.io.*; -import org.apache.ignite.internal.util.typedef.*; import org.apache.ignite.internal.util.typedef.internal.*; -import org.apache.ignite.lang.*; import org.apache.ignite.marshaller.*; import sun.misc.*; @@ -62,13 +60,7 @@ class OptimizedObjectInputStream extends ObjectInputStream { private Object curObj; /** */ - private List<T2<OptimizedFieldType, Long>> curFields; - - /** */ - private List<IgniteBiTuple<Integer, OptimizedFieldType>> curFieldInfoList; - - /** */ - private Map<String, IgniteBiTuple<Integer, OptimizedFieldType>> curFieldInfoMap; + private OptimizedClassDescriptor.ClassFields curFields; /** */ private Class<?> curCls; @@ -133,16 +125,12 @@ class OptimizedObjectInputStream extends ObjectInputStream { curObj = null; curFields = null; - curFieldInfoList = null; - curFieldInfoMap = null; } /** {@inheritDoc} */ @Override public Object readObjectOverride() throws ClassNotFoundException, IOException { curObj = null; curFields = null; - curFieldInfoList = null; - curFieldInfoMap = null; byte ref = in.readByte(); @@ -357,54 +345,81 @@ class OptimizedObjectInputStream extends ObjectInputStream { * @throws IOException In case of error. */ @SuppressWarnings("ForLoopReplaceableByForEach") - void readFields(Object obj, List<T2<OptimizedFieldType, Long>> fieldOffs) throws ClassNotFoundException, + void readFields(Object obj, OptimizedClassDescriptor.ClassFields fieldOffs) throws ClassNotFoundException, IOException { for (int i = 0; i < fieldOffs.size(); i++) { - T2<OptimizedFieldType, Long> t = fieldOffs.get(i); + OptimizedClassDescriptor.FieldInfo t = fieldOffs.get(i); - switch ((t.get1())) { + switch ((t.type())) { case BYTE: - setByte(obj, t.get2(), readByte()); + byte resByte = readByte(); + + if (t.field() != null) + setByte(obj, t.offset(), resByte); break; case SHORT: - setShort(obj, t.get2(), readShort()); + short resShort = readShort(); + + if (t.field() != null) + setShort(obj, t.offset(), resShort); break; case INT: - setInt(obj, t.get2(), readInt()); + int resInt = readInt(); + + if (t.field() != null) + setInt(obj, t.offset(), resInt); break; case LONG: - setLong(obj, t.get2(), readLong()); + long resLong = readLong(); + + if (t.field() != null) + setLong(obj, t.offset(), resLong); break; case FLOAT: - setFloat(obj, t.get2(), readFloat()); + float resFloat = readFloat(); + + if (t.field() != null) + setFloat(obj, t.offset(), resFloat); break; case DOUBLE: - setDouble(obj, t.get2(), readDouble()); + double resDouble = readDouble(); + + if (t.field() != null) + setDouble(obj, t.offset(), resDouble); break; case CHAR: - setChar(obj, t.get2(), readChar()); + char resChar = readChar(); + + if (t.field() != null) + setChar(obj, t.offset(), resChar); break; case BOOLEAN: - setBoolean(obj, t.get2(), readBoolean()); + boolean resBoolean = readBoolean(); + + if (t.field() != null) + setBoolean(obj, t.offset(), resBoolean); break; case OTHER: - setObject(obj, t.get2(), readObject()); + Object resObject = readObject(); + + if (t.field() != null) + setObject(obj, t.offset(), resObject); } } } @@ -479,9 +494,7 @@ class OptimizedObjectInputStream extends ObjectInputStream { if (mtd != null) { curObj = obj; - curFields = fields.fieldOffs(i); - curFieldInfoList = fields.fieldInfoList(i); - curFieldInfoMap = fields.fieldInfoMap(i); + curFields = fields.fields(i); try { mtd.invoke(obj, this); @@ -491,7 +504,7 @@ class OptimizedObjectInputStream extends ObjectInputStream { } } else - readFields(obj, fields.fieldOffs(i)); + readFields(obj, fields.fields(i)); } if (readResolveMtd != null) { @@ -1008,7 +1021,7 @@ class OptimizedObjectInputStream extends ObjectInputStream { */ private static class GetFieldImpl extends GetField { /** Field info map. */ - private final Map<String, IgniteBiTuple<Integer, OptimizedFieldType>> fieldInfoMap; + private final OptimizedClassDescriptor.ClassFields fieldInfo; /** Values. */ private final Object[] objs; @@ -1020,18 +1033,16 @@ class OptimizedObjectInputStream extends ObjectInputStream { */ @SuppressWarnings("ForLoopReplaceableByForEach") private GetFieldImpl(OptimizedObjectInputStream in) throws IOException, ClassNotFoundException { - fieldInfoMap = in.curFieldInfoMap; - - List<IgniteBiTuple<Integer, OptimizedFieldType>> infos = in.curFieldInfoList; + fieldInfo = in.curFields; - objs = new Object[infos.size()]; + objs = new Object[fieldInfo.size()]; - for (int i = 0; i < infos.size(); i++) { - IgniteBiTuple<Integer, OptimizedFieldType> t = infos.get(i); + for (int i = 0; i < fieldInfo.size(); i++) { + OptimizedClassDescriptor.FieldInfo t = fieldInfo.get(i); Object obj = null; - switch (t.get2()) { + switch (t.type()) { case BYTE: obj = in.readByte(); @@ -1076,7 +1087,7 @@ class OptimizedObjectInputStream extends ObjectInputStream { obj = in.readObject(); } - objs[t.get1()] = obj; + objs[i] = obj; } } @@ -1087,7 +1098,7 @@ class OptimizedObjectInputStream extends ObjectInputStream { /** {@inheritDoc} */ @Override public boolean defaulted(String name) throws IOException { - return objs[fieldInfoMap.get(name).get1()] == null; + return objs[fieldInfo.getIndex(name)] == null; } /** {@inheritDoc} */ @@ -1142,7 +1153,7 @@ class OptimizedObjectInputStream extends ObjectInputStream { */ @SuppressWarnings("unchecked") private <T> T value(String name, T dflt) { - return objs[fieldInfoMap.get(name).get1()] != null ? (T)objs[fieldInfoMap.get(name).get1()] : dflt; + return objs[fieldInfo.getIndex(name)] != null ? (T)objs[fieldInfo.getIndex(name)] : dflt; } } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/75ea4a3d/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java index c5f9f08..82ae129 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java @@ -61,10 +61,7 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { private Object curObj; /** */ - private List<T2<OptimizedFieldType, Long>> curFields; - - /** */ - private Map<String, IgniteBiTuple<Integer, OptimizedFieldType>> curFieldInfoMap; + private OptimizedClassDescriptor.ClassFields curFields; /** */ private PutFieldImpl curPut; @@ -158,7 +155,6 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { curObj = null; curFields = null; curPut = null; - curFieldInfoMap = null; if (obj == null) writeByte(NULL); @@ -309,8 +305,7 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { if (mtd != null) { curObj = obj; - curFields = fields.fieldOffs(i); - curFieldInfoMap = fields.fieldInfoMap(i); + curFields = fields.fields(i); try { mtd.invoke(obj, this); @@ -323,7 +318,7 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { } } else - writeFields(obj, fields.fieldOffs(i)); + writeFields(obj, fields.fields(i)); } } @@ -452,57 +447,66 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { * Writes all non-static and non-transient field values to this stream. * * @param obj Object. - * @param fieldOffs Field offsets. + * @param fields Fields. * @throws IOException In case of error. */ @SuppressWarnings("ForLoopReplaceableByForEach") - private void writeFields(Object obj, List<T2<OptimizedFieldType, Long>> fieldOffs) throws IOException { - for (int i = 0; i < fieldOffs.size(); i++) { - T2<OptimizedFieldType, Long> t = fieldOffs.get(i); + private void writeFields(Object obj, OptimizedClassDescriptor.ClassFields fields) throws IOException { + for (int i = 0; i < fields.size(); i++) { + OptimizedClassDescriptor.FieldInfo t = fields.get(i); - switch (t.get1()) { + switch (t.type()) { case BYTE: - writeByte(getByte(obj, t.get2())); + if (t.field() != null) + writeByte(getByte(obj, t.offset())); break; case SHORT: - writeShort(getShort(obj, t.get2())); + if (t.field() != null) + writeShort(getShort(obj, t.offset())); break; case INT: - writeInt(getInt(obj, t.get2())); + if (t.field() != null) + writeInt(getInt(obj, t.offset())); break; case LONG: - writeLong(getLong(obj, t.get2())); + if (t.field() != null) + writeLong(getLong(obj, t.offset())); break; case FLOAT: - writeFloat(getFloat(obj, t.get2())); + if (t.field() != null) + writeFloat(getFloat(obj, t.offset())); break; case DOUBLE: - writeDouble(getDouble(obj, t.get2())); + if (t.field() != null) + writeDouble(getDouble(obj, t.offset())); break; case CHAR: - writeChar(getChar(obj, t.get2())); + if (t.field() != null) + writeChar(getChar(obj, t.offset())); break; case BOOLEAN: - writeBoolean(getBoolean(obj, t.get2())); + if (t.field() != null) + writeBoolean(getBoolean(obj, t.offset())); break; case OTHER: - writeObject0(getObject(obj, t.get2())); + if (t.field() != null) + writeObject0(getObject(obj, t.offset())); } } } @@ -750,7 +754,6 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { curObj = null; curFields = null; curPut = null; - curFieldInfoMap = null; } /** {@inheritDoc} */ @@ -780,9 +783,8 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { /** Stream. */ private final OptimizedObjectOutputStream out; - /** Field info map. */ - private final Map<String, IgniteBiTuple<Integer, OptimizedFieldType>> fieldInfoMap; - + /** Fields info. */ + private final OptimizedClassDescriptor.ClassFields curFields; /** Values. */ private final IgniteBiTuple<OptimizedFieldType, Object>[] objs; @@ -793,9 +795,9 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { private PutFieldImpl(OptimizedObjectOutputStream out) { this.out = out; - fieldInfoMap = out.curFieldInfoMap; + curFields = out.curFields; - objs = new IgniteBiTuple[fieldInfoMap.size()]; + objs = new IgniteBiTuple[curFields.size()]; } /** {@inheritDoc} */ @@ -856,9 +858,11 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { * @param val Value. */ private void value(String name, Object val) { - IgniteBiTuple<Integer, OptimizedFieldType> info = fieldInfoMap.get(name); + int i = curFields.getIndex(name); + + OptimizedClassDescriptor.FieldInfo info = curFields.get(i); - objs[info.get1()] = F.t(info.get2(), val); + objs[i] = F.t(info.type(), val); } } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/75ea4a3d/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerSerialPersistentFieldsSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerSerialPersistentFieldsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerSerialPersistentFieldsSelfTest.java new file mode 100644 index 0000000..3dbbd4c --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerSerialPersistentFieldsSelfTest.java @@ -0,0 +1,107 @@ +/* + * 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.marshaller.optimized; + +import org.apache.ignite.testframework.junits.common.*; + +import java.io.*; + +/** + * Test that Optimized Marshaller works with classes with serialPersistentFields. + */ +public class OptimizedMarshallerSerialPersistentFieldsSelfTest extends GridCommonAbstractTest { + /** + * @throws Exception If failed. + */ + public void testOptimizedMarshaller() throws Exception { + OptimizedMarshaller m = new OptimizedMarshaller(); + + m.unmarshal(m.marshal(new TestClass()), TestClass.class.getClassLoader()); + + TestClass2 val = m.unmarshal(m.marshal(new TestClass2()), TestClass2.class.getClassLoader()); + + assertNull(val.field3); + } + + /** + * Test class with serialPersistentFields fields. + */ + private static class TestClass implements Serializable { + private static final long serialVersionUID = 0L; + + /** For serialization compatibility. */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("field1", Integer.TYPE), + new ObjectStreamField("field2", Integer.TYPE) + }; + + /** + * @param s Object output stream. + */ + private void writeObject(ObjectOutputStream s) throws IOException { + s.putFields().put("field1", 1); + s.putFields().put("field2", 2); + s.writeFields(); + + s.writeObject(null); + } + + /** + * @param s Object input stream. + */ + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); + + s.readObject(); + } + } + + /** + * Test class with serialPersistentFields fields. + */ + private static class TestClass2 implements Serializable { + private static final long serialVersionUID = 0L; + + private Integer field3 = 1; + + /** For serialization compatibility. */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("field1", Integer.TYPE), + new ObjectStreamField("field2", Integer.TYPE) + }; + + /** + * @param s Object output stream. + */ + private void writeObject(ObjectOutputStream s) throws IOException { + s.putFields().put("field1", 1); + s.putFields().put("field2", 2); + s.writeFields(); + + s.writeObject(null); + } + + /** + * @param s Object input stream. + */ + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); + + s.readObject(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/75ea4a3d/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteMarshallerSelfTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteMarshallerSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteMarshallerSelfTestSuite.java index 1d7f196..10afe10 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteMarshallerSelfTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteMarshallerSelfTestSuite.java @@ -40,6 +40,7 @@ public class IgniteMarshallerSelfTestSuite extends TestSuite { suite.addTest(new TestSuite(OptimizedObjectStreamSelfTest.class)); suite.addTest(new TestSuite(GridUnsafeDataOutputArraySizingSelfTest.class)); suite.addTest(new TestSuite(OptimizedMarshallerNodeFailoverTest.class)); + suite.addTest(new TestSuite(OptimizedMarshallerSerialPersistentFieldsSelfTest.class)); return suite; }