http://git-wip-us.apache.org/repos/asf/ignite/blob/a1b5b8c3/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 deleted file mode 100644 index fd885f2..0000000 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java +++ /dev/null @@ -1,1141 +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.marshaller.optimized; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.NotSerializableException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamField; -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.UUID; -import java.util.concurrent.ConcurrentMap; -import org.apache.ignite.internal.util.GridUnsafe; -import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.lang.IgniteProductVersion; -import org.apache.ignite.marshaller.MarshallerContext; -import org.apache.ignite.marshaller.MarshallerExclusions; -import org.apache.ignite.internal.util.SerializableTransient; -import org.apache.ignite.marshaller.MarshallerUtils; - -import static java.lang.reflect.Modifier.isFinal; -import static java.lang.reflect.Modifier.isPrivate; -import static java.lang.reflect.Modifier.isStatic; -import static java.lang.reflect.Modifier.isTransient; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.ARRAY_LIST; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.BOOLEAN; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.BOOLEAN_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.BYTE; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.BYTE_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.CHAR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.CHAR_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.CLS; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.DATE; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.DOUBLE; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.DOUBLE_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.ENUM; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.EXTERNALIZABLE; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.FLOAT; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.FLOAT_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.HASH_MAP; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.HASH_SET; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.HASH_SET_MAP_OFF; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.INT; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.INT_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.LINKED_HASH_MAP; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.LINKED_HASH_SET; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.LINKED_LIST; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.LONG; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.LONG_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.OBJ_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.PROPS; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.PROXY; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.SERIALIZABLE; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.SHORT; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.SHORT_ARR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.STR; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.UUID; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.classDescriptor; -import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.computeSerialVersionUid; - -/** - * Class descriptor. - */ -class OptimizedClassDescriptor { - /** Class. */ - private final Class<?> cls; - - /** Context. */ - private final MarshallerContext ctx; - - /** */ - private ConcurrentMap<Class, OptimizedClassDescriptor> clsMap; - - /** ID mapper. */ - private final OptimizedMarshallerIdMapper mapper; - - /** Class name. */ - private final String name; - - /** Type ID. */ - private final int typeId; - - /** Short ID. */ - private final short checksum; - - /** Class type. */ - private int type; - - /** Primitive flag. */ - private boolean isPrimitive; - - /** Enum flag. */ - private boolean isEnum; - - /** Serializable flag. */ - private boolean isSerial; - - /** Excluded flag. */ - private boolean excluded; - - /** {@code True} if descriptor is for {@link Class}. */ - private boolean isCls; - - /** Enumeration values. */ - private Object[] enumVals; - - /** Constructor. */ - private Constructor<?> constructor; - - /** Fields. */ - private Fields fields; - - /** {@code writeObject} methods. */ - private List<Method> writeObjMtds; - - /** {@code writeReplace} method. */ - private Method writeReplaceMtd; - - /** {@code readObject} methods. */ - private List<Method> readObjMtds; - - /** {@code readResolve} method. */ - private Method readResolveMtd; - - /** Defaults field offset. */ - private long dfltsFieldOff; - - /** Load factor field offset. */ - private long loadFactorFieldOff; - - /** Access order field offset. */ - private long accessOrderFieldOff; - - /** Proxy interfaces. */ - private Class<?>[] proxyIntfs; - - /** Method returns serializable transient fields. */ - private Method serTransMtd; - - /** - * Creates descriptor for class. - * - * @param typeId Type ID. - * @param clsMap Class descriptors by class map. - * @param cls Class. - * @param ctx Context. - * @param mapper ID mapper. - * @throws IOException In case of error. - */ - @SuppressWarnings("ForLoopReplaceableByForEach") - OptimizedClassDescriptor(Class<?> cls, - int typeId, - ConcurrentMap<Class, OptimizedClassDescriptor> clsMap, - MarshallerContext ctx, - OptimizedMarshallerIdMapper mapper) - throws IOException { - this.cls = cls; - this.typeId = typeId; - this.clsMap = clsMap; - this.ctx = ctx; - this.mapper = mapper; - - name = cls.getName(); - - excluded = MarshallerExclusions.isExcluded(cls); - - if (!excluded) { - Class<?> parent; - - if (cls == byte.class || cls == Byte.class) { - type = BYTE; - - isPrimitive = true; - } - else if (cls == short.class || cls == Short.class) { - type = SHORT; - - isPrimitive = true; - } - else if (cls == int.class || cls == Integer.class) { - type = INT; - - isPrimitive = true; - } - else if (cls == long.class || cls == Long.class) { - type = LONG; - - isPrimitive = true; - } - else if (cls == float.class || cls == Float.class) { - type = FLOAT; - - isPrimitive = true; - } - else if (cls == double.class || cls == Double.class) { - type = DOUBLE; - - isPrimitive = true; - } - else if (cls == char.class || cls == Character.class) { - type = CHAR; - - isPrimitive = true; - } - else if (cls == boolean.class || cls == Boolean.class) { - type = BOOLEAN; - - isPrimitive = true; - } - else if (cls == byte[].class) - type = BYTE_ARR; - else if (cls == short[].class) - type = SHORT_ARR; - else if (cls == int[].class) - type = INT_ARR; - else if (cls == long[].class) - type = LONG_ARR; - else if (cls == float[].class) - type = FLOAT_ARR; - else if (cls == double[].class) - type = DOUBLE_ARR; - else if (cls == char[].class) - type = CHAR_ARR; - else if (cls == boolean[].class) - type = BOOLEAN_ARR; - else if (cls.isArray()) - type = OBJ_ARR; - else if (cls == String.class) - type = STR; - else if (cls.isEnum()) { - type = ENUM; - - isEnum = true; - enumVals = cls.getEnumConstants(); - } - // Support for enum constants, based on anonymous children classes. - else if ((parent = cls.getSuperclass()) != null && parent.isEnum()) { - type = ENUM; - - isEnum = true; - enumVals = parent.getEnumConstants(); - } - else if (cls == UUID.class) - type = UUID; - else if (cls == Properties.class) { - type = PROPS; - - try { - dfltsFieldOff = GridUnsafe.objectFieldOffset(Properties.class.getDeclaredField("defaults")); - } - catch (NoSuchFieldException e) { - throw new IOException(e); - } - } - else if (cls == ArrayList.class) - type = ARRAY_LIST; - else if (cls == HashMap.class) { - type = HASH_MAP; - - try { - loadFactorFieldOff = GridUnsafe.objectFieldOffset(HashMap.class.getDeclaredField("loadFactor")); - } - catch (NoSuchFieldException e) { - throw new IOException(e); - } - } - else if (cls == HashSet.class) { - type = HASH_SET; - - try { - loadFactorFieldOff = GridUnsafe.objectFieldOffset(HashMap.class.getDeclaredField("loadFactor")); - } - catch (NoSuchFieldException e) { - throw new IOException(e); - } - } - else if (cls == LinkedList.class) - type = LINKED_LIST; - else if (cls == LinkedHashMap.class) { - type = LINKED_HASH_MAP; - - try { - loadFactorFieldOff = - GridUnsafe.objectFieldOffset(HashMap.class.getDeclaredField("loadFactor")); - accessOrderFieldOff = - GridUnsafe.objectFieldOffset(LinkedHashMap.class.getDeclaredField("accessOrder")); - } - catch (NoSuchFieldException e) { - throw new IOException(e); - } - } - else if (cls == LinkedHashSet.class) { - type = LINKED_HASH_SET; - - try { - loadFactorFieldOff = GridUnsafe.objectFieldOffset(HashMap.class.getDeclaredField("loadFactor")); - } - catch (NoSuchFieldException e) { - throw new IOException(e); - } - } - else if (cls == Date.class) - type = DATE; - else if (cls == Class.class) { - type = CLS; - - isCls = true; - } - else if (Proxy.class.isAssignableFrom(cls)) { - type = PROXY; - - proxyIntfs = cls.getInterfaces(); - } - else { - Class<?> c = cls; - - while ((writeReplaceMtd == null || readResolveMtd == null) && c != null && !c.equals(Object.class)) { - if (writeReplaceMtd == null) { - try { - writeReplaceMtd = c.getDeclaredMethod("writeReplace"); - - if (!isStatic(writeReplaceMtd.getModifiers()) && - !(isPrivate(writeReplaceMtd.getModifiers()) && c != cls) && - writeReplaceMtd.getReturnType().equals(Object.class)) - writeReplaceMtd.setAccessible(true); - else - // Set method back to null if it has incorrect signature. - writeReplaceMtd = null; - } - catch (NoSuchMethodException ignored) { - // No-op. - } - } - - if (readResolveMtd == null) { - try { - readResolveMtd = c.getDeclaredMethod("readResolve"); - - if (!isStatic(readResolveMtd.getModifiers()) && - !(isPrivate(readResolveMtd.getModifiers()) && c != cls) && - readResolveMtd.getReturnType().equals(Object.class)) - readResolveMtd.setAccessible(true); - else - // Set method back to null if it has incorrect signature. - readResolveMtd = null; - } - catch (NoSuchMethodException ignored) { - // No-op. - } - } - - c = c.getSuperclass(); - } - - if (Externalizable.class.isAssignableFrom(cls)) { - type = EXTERNALIZABLE; - - try { - constructor = !Modifier.isStatic(cls.getModifiers()) && cls.getDeclaringClass() != null ? - cls.getDeclaredConstructor(cls.getDeclaringClass()) : - cls.getDeclaredConstructor(); - - constructor.setAccessible(true); - } - catch (NoSuchMethodException e) { - throw new IOException("Externalizable class doesn't have default constructor: " + cls, e); - } - } - else { - type = SERIALIZABLE; - - isSerial = Serializable.class.isAssignableFrom(cls); - - writeObjMtds = new ArrayList<>(); - readObjMtds = new ArrayList<>(); - List<ClassFields> fields = new ArrayList<>(); - - for (c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) { - Method mtd; - - try { - mtd = c.getDeclaredMethod("writeObject", ObjectOutputStream.class); - - int mod = mtd.getModifiers(); - - if (!isStatic(mod) && isPrivate(mod) && mtd.getReturnType() == Void.TYPE) - mtd.setAccessible(true); - else - // Set method back to null if it has incorrect signature. - mtd = null; - } - catch (NoSuchMethodException ignored) { - mtd = null; - } - - writeObjMtds.add(mtd); - - try { - mtd = c.getDeclaredMethod("readObject", ObjectInputStream.class); - - int mod = mtd.getModifiers(); - - if (!isStatic(mod) && isPrivate(mod) && mtd.getReturnType() == Void.TYPE) - mtd.setAccessible(true); - else - // Set method back to null if it has incorrect signature. - mtd = null; - } - catch (NoSuchMethodException ignored) { - mtd = null; - } - - readObjMtds.add(mtd); - - final SerializableTransient serTransAn = c.getAnnotation(SerializableTransient.class); - - // Custom serialization policy for transient fields. - if (serTransAn != null) { - try { - serTransMtd = c.getDeclaredMethod(serTransAn.methodName(), cls, IgniteProductVersion.class); - - int mod = serTransMtd.getModifiers(); - - if (isStatic(mod) && isPrivate(mod) - && serTransMtd.getReturnType() == String[].class) - serTransMtd.setAccessible(true); - else - // Set method back to null if it has incorrect signature. - serTransMtd = null; - } - catch (NoSuchMethodException ignored) { - serTransMtd = null; - } - } - - Field[] clsFields0 = c.getDeclaredFields(); - - Map<String, Field> fieldNames = new HashMap<>(); - - for (Field f : clsFields0) - fieldNames.put(f.getName(), f); - - List<FieldInfo> clsFields = new ArrayList<>(clsFields0.length); - - boolean hasSerialPersistentFields = false; - - try { - Field serFieldsDesc = c.getDeclaredField("serialPersistentFields"); - - int mod = serFieldsDesc.getModifiers(); - - if (serFieldsDesc.getType() == ObjectStreamField[].class && - isPrivate(mod) && isStatic(mod) && isFinal(mod)) { - hasSerialPersistentFields = true; - - serFieldsDesc.setAccessible(true); - - ObjectStreamField[] serFields = (ObjectStreamField[]) serFieldsDesc.get(null); - - for (int i = 0; i < serFields.length; i++) { - ObjectStreamField serField = serFields[i]; - - 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(), - GridUnsafe.objectFieldOffset(f), - fieldType(serField.getType())); - } - - clsFields.add(fieldInfo); - } - } - } - catch (NoSuchFieldException ignored) { - // No-op. - } - catch (IllegalAccessException e) { - throw new IOException("Failed to get value of 'serialPersistentFields' field in class: " + - cls.getName(), e); - } - - if (!hasSerialPersistentFields) { - for (int i = 0; i < clsFields0.length; i++) { - Field f = clsFields0[i]; - - int mod = f.getModifiers(); - - if (!isStatic(mod) && !isTransient(mod)) { - FieldInfo fieldInfo = new FieldInfo(f, f.getName(), - GridUnsafe.objectFieldOffset(f), fieldType(f.getType())); - - clsFields.add(fieldInfo); - } - } - } - - Collections.sort(clsFields, new Comparator<FieldInfo>() { - @Override public int compare(FieldInfo t1, FieldInfo t2) { - return t1.name().compareTo(t2.name()); - } - }); - - fields.add(new ClassFields(clsFields)); - } - - Collections.reverse(writeObjMtds); - Collections.reverse(readObjMtds); - Collections.reverse(fields); - - this.fields = new Fields(fields); - } - } - } - - checksum = computeSerialVersionUid(cls, fields != null ? fields.ownFields() : null); - } - - /** - * @return Excluded flag. - */ - boolean excluded() { - return excluded; - } - - /** - * @return Class. - */ - Class<?> describedClass() { - return cls; - } - - /** - * @return Primitive flag. - */ - boolean isPrimitive() { - return isPrimitive; - } - - /** - * @return Enum flag. - */ - boolean isEnum() { - return isEnum; - } - - /** - * @return {@code True} if descriptor is for {@link Class}. - */ - boolean isClass() { - return isCls; - } - - /** - * @return {@code True} if descriptor is for {@link Proxy}. - */ - boolean isProxy() { - return type == PROXY; - } - - /** - * Replaces object. - * - * @param obj Object. - * @return Replaced object or {@code null} if there is no {@code writeReplace} method. - * @throws IOException In case of error. - */ - Object replace(Object obj) throws IOException { - if (writeReplaceMtd != null) { - try { - return writeReplaceMtd.invoke(obj); - } - catch (IllegalAccessException | InvocationTargetException e) { - throw new IOException(e); - } - } - - return obj; - } - - /** - * Writes object to stream. - * - * @param out Output stream. - * @param obj Object. - * @throws IOException In case of error. - */ - @SuppressWarnings("ForLoopReplaceableByForEach") - void write(OptimizedObjectOutputStream out, Object obj) throws IOException { - out.write(type); - - switch (type) { - case BYTE: - out.writeByte((Byte)obj); - - break; - - case SHORT: - out.writeShort((Short)obj); - - break; - - case INT: - out.writeInt((Integer)obj); - - break; - - case LONG: - out.writeLong((Long)obj); - - break; - - case FLOAT: - out.writeFloat((Float)obj); - - break; - - case DOUBLE: - out.writeDouble((Double)obj); - - break; - - case CHAR: - out.writeChar((Character)obj); - - break; - - case BOOLEAN: - out.writeBoolean((Boolean)obj); - - break; - - case BYTE_ARR: - out.writeByteArray((byte[])obj); - - break; - - case SHORT_ARR: - out.writeShortArray((short[])obj); - - break; - - case INT_ARR: - out.writeIntArray((int[])obj); - - break; - - case LONG_ARR: - out.writeLongArray((long[])obj); - - break; - - case FLOAT_ARR: - out.writeFloatArray((float[])obj); - - break; - - case DOUBLE_ARR: - out.writeDoubleArray((double[])obj); - - break; - - case CHAR_ARR: - out.writeCharArray((char[])obj); - - break; - - case BOOLEAN_ARR: - out.writeBooleanArray((boolean[])obj); - - break; - - case OBJ_ARR: - OptimizedClassDescriptor compDesc = classDescriptor(clsMap, - obj.getClass().getComponentType(), - ctx, - mapper); - - compDesc.writeTypeData(out); - - out.writeArray((Object[])obj); - - break; - - case STR: - out.writeString((String)obj); - - break; - - case UUID: - out.writeUuid((UUID)obj); - - break; - - case PROPS: - out.writeProperties((Properties)obj, dfltsFieldOff); - - break; - - case ARRAY_LIST: - out.writeArrayList((ArrayList<?>)obj); - - break; - - case HASH_MAP: - out.writeHashMap((HashMap<?, ?>)obj, loadFactorFieldOff, false); - - break; - - case HASH_SET: - out.writeHashSet((HashSet<?>)obj, HASH_SET_MAP_OFF, loadFactorFieldOff); - - break; - - case LINKED_LIST: - out.writeLinkedList((LinkedList<?>)obj); - - break; - - case LINKED_HASH_MAP: - out.writeLinkedHashMap((LinkedHashMap<?, ?>)obj, loadFactorFieldOff, accessOrderFieldOff, false); - - break; - - case LINKED_HASH_SET: - out.writeLinkedHashSet((LinkedHashSet<?>)obj, HASH_SET_MAP_OFF, loadFactorFieldOff); - - break; - - case DATE: - out.writeDate((Date)obj); - - break; - - case CLS: - OptimizedClassDescriptor clsDesc = classDescriptor(clsMap, (Class<?>)obj, ctx, mapper); - - clsDesc.writeTypeData(out); - - break; - - case PROXY: - out.writeInt(proxyIntfs.length); - - for (Class<?> intf : proxyIntfs) { - OptimizedClassDescriptor intfDesc = classDescriptor(clsMap, intf, ctx, mapper); - - intfDesc.writeTypeData(out); - } - - InvocationHandler ih = Proxy.getInvocationHandler(obj); - - assert ih != null; - - out.writeObject(ih); - - break; - - case ENUM: - writeTypeData(out); - - out.writeInt(((Enum)obj).ordinal()); - - break; - - case EXTERNALIZABLE: - writeTypeData(out); - - out.writeShort(checksum); - out.writeExternalizable(obj); - - break; - - case SERIALIZABLE: - if (out.requireSerializable() && !isSerial) - throw new NotSerializableException("Must implement java.io.Serializable or " + - "set OptimizedMarshaller.setRequireSerializable() to false " + - "(note that performance may degrade if object is not Serializable): " + name); - - writeTypeData(out); - - out.writeShort(checksum); - out.writeSerializable(obj, writeObjMtds, serializableFields(obj.getClass(), obj, null)); - - break; - - default: - throw new IllegalStateException("Invalid class type: " + type); - } - } - - /** - * Gets list of serializable fields. If {@link #serTransMtd} method - * returns list of transient fields, they will be added to other fields. - * Transient fields that are not included in that list will be normally - * ignored. - * - * @param cls Class. - * @param obj Object. - * @param ver Job sender version. - * @return Serializable fields. - */ - @SuppressWarnings("ForLoopReplaceableByForEach") - private Fields serializableFields(Class<?> cls, Object obj, IgniteProductVersion ver) { - if (serTransMtd == null) - return fields; - - try { - final String[] transFields = (String[])serTransMtd.invoke(cls, obj, ver); - - if (transFields == null || transFields.length == 0) - return fields; - - List<FieldInfo> clsFields = new ArrayList<>(); - - clsFields.addAll(fields.fields.get(0).fields); - - for (int i = 0; i < transFields.length; i++) { - final String fieldName = transFields[i]; - - final Field f = cls.getDeclaredField(fieldName); - - FieldInfo fieldInfo = new FieldInfo(f, f.getName(), - GridUnsafe.objectFieldOffset(f), fieldType(f.getType())); - - clsFields.add(fieldInfo); - } - - Collections.sort(clsFields, new Comparator<FieldInfo>() { - @Override public int compare(FieldInfo t1, FieldInfo t2) { - return t1.name().compareTo(t2.name()); - } - }); - - List<ClassFields> fields = new ArrayList<>(); - - fields.add(new ClassFields(clsFields)); - - return new Fields(fields); - } - catch (Exception ignored) { - return fields; - } - } - - /** - * @param out Output stream. - * @throws IOException In case of error. - */ - void writeTypeData(OptimizedObjectOutputStream out) throws IOException { - out.writeInt(typeId); - - if (typeId == 0) - out.writeUTF(name); - } - - /** - * Reads object from stream. - * - * @param in Input stream. - * @return Object. - * @throws ClassNotFoundException If class not found. - * @throws IOException In case of error. - */ - Object read(OptimizedObjectInputStream in) throws ClassNotFoundException, IOException { - switch (type) { - case ENUM: - return enumVals[in.readInt()]; - - case EXTERNALIZABLE: - verifyChecksum(in.readShort()); - - return in.readExternalizable(constructor, readResolveMtd); - - case SERIALIZABLE: - verifyChecksum(in.readShort()); - - // If no serialize method, then unmarshal as usual. - if (serTransMtd != null) - return in.readSerializable(cls, readObjMtds, readResolveMtd, - serializableFields(cls, null, MarshallerUtils.jobSenderVersion())); - else - return in.readSerializable(cls, readObjMtds, readResolveMtd, fields); - - default: - assert false : "Unexpected type: " + type; - - return null; - } - } - - /** - * @param checksum Checksum. - * @throws ClassNotFoundException If checksum is wrong. - * @throws IOException In case of error. - */ - private void verifyChecksum(short checksum) throws ClassNotFoundException, IOException { - if (checksum != this.checksum) - throw new ClassNotFoundException("Optimized stream class checksum mismatch " + - "(is same version of marshalled class present on all nodes?) " + - "[expected=" + this.checksum + ", actual=" + checksum + ", cls=" + cls + ']'); - } - - /** - * @param cls Class. - * @return Type. - */ - @SuppressWarnings("IfMayBeConditional") - private OptimizedFieldType fieldType(Class<?> cls) { - OptimizedFieldType type; - - if (cls == byte.class) - type = OptimizedFieldType.BYTE; - else if (cls == short.class) - type = OptimizedFieldType.SHORT; - else if (cls == int.class) - type = OptimizedFieldType.INT; - else if (cls == long.class) - type = OptimizedFieldType.LONG; - else if (cls == float.class) - type = OptimizedFieldType.FLOAT; - else if (cls == double.class) - type = OptimizedFieldType.DOUBLE; - else if (cls == char.class) - type = OptimizedFieldType.CHAR; - else if (cls == boolean.class) - type = OptimizedFieldType.BOOLEAN; - else - type = OptimizedFieldType.OTHER; - - return type; - } - - /** - * Information about one field. - */ - @SuppressWarnings("PackageVisibleInnerClass") - static class FieldInfo { - /** Field. */ - private final Field field; - - /** Field offset. */ - private final long fieldOffs; - - /** Field type. */ - private final OptimizedFieldType fieldType; - - /** Field name. */ - private final String fieldName; - - /** - * @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. - */ - ClassFields(List<FieldInfo> fields) { - this.fields = fields; - - nameToIndex = U.newHashMap(fields.size()); - - for (int i = 0; i < fields.size(); ++i) - nameToIndex.put(fields.get(i).name(), i); - } - - /** - * @return Class fields. - */ - List<FieldInfo> fields() { - return fields; - } - - /** - * @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 fields Fields. - */ - 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 class's own fields (excluding inherited). - * - * @return List of fields or {@code null} if fields list is empty. - */ - List<Field> ownFields() { - return ownFields; - } - - /** - * Returns field types and their offsets. - * - * @param i hierarchy level where 0 corresponds to top level. - * @return list of pairs where first value is field type and second value is its offset. - */ - ClassFields fields(int i) { - return fields.get(i); - } - } -}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a1b5b8c3/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedFieldType.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedFieldType.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedFieldType.java deleted file mode 100644 index aca7ce4..0000000 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedFieldType.java +++ /dev/null @@ -1,50 +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.marshaller.optimized; - -/** - * Field type used to calculate {@code Unsafe} offsets into objects. - */ -enum OptimizedFieldType { - /** */ - BYTE, - - /** */ - SHORT, - - /** */ - INT, - - /** */ - LONG, - - /** */ - FLOAT, - - /** */ - DOUBLE, - - /** */ - CHAR, - - /** */ - BOOLEAN, - - /** */ - OTHER -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/a1b5b8c3/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java deleted file mode 100644 index e61e8dc..0000000 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java +++ /dev/null @@ -1,313 +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.marshaller.optimized; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.io.Serializable; -import java.util.concurrent.ConcurrentMap; -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.IgniteException; -import org.apache.ignite.IgniteSystemProperties; -import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.marshaller.AbstractNodeNameAwareMarshaller; -import org.jetbrains.annotations.Nullable; -import org.jsr166.ConcurrentHashMap8; -import sun.misc.Unsafe; - -import static org.apache.ignite.IgniteSystemProperties.IGNITE_OPTIMIZED_MARSHALLER_USE_DEFAULT_SUID; - -/** - * Optimized implementation of {@link org.apache.ignite.marshaller.Marshaller}. - * Unlike {@link org.apache.ignite.marshaller.jdk.JdkMarshaller}, - * which is based on standard {@link ObjectOutputStream}, this marshaller does not - * enforce that all serialized objects implement {@link Serializable} interface. It is also - * about 20 times faster as it removes lots of serialization overhead that exists in - * default JDK implementation. - * <p> - * {@code OptimizedMarshaller} is tested only on Java HotSpot VM on other VMs - * it could yield unexpected results. It is the default marshaller on Java HotSpot VMs - * and will be used if no other marshaller was explicitly configured. - * <p> - * <h1 class="header">Configuration</h1> - * <h2 class="header">Mandatory</h2> - * This marshaller has no mandatory configuration parameters. - * <h2 class="header">Java Example</h2> - * <pre name="code" class="java"> - * OptimizedMarshaller marshaller = new OptimizedMarshaller(); - * - * // Enforce Serializable interface. - * marshaller.setRequireSerializable(true); - * - * IgniteConfiguration cfg = new IgniteConfiguration(); - * - * // Override marshaller. - * cfg.setMarshaller(marshaller); - * - * // Starts grid. - * G.start(cfg); - * </pre> - * <h2 class="header">Spring Example</h2> - * GridOptimizedMarshaller can be configured from Spring XML configuration file: - * <pre name="code" class="xml"> - * <bean id="grid.custom.cfg" class="org.apache.ignite.configuration.IgniteConfiguration" singleton="true"> - * ... - * <property name="marshaller"> - * <bean class="org.apache.ignite.marshaller.optimized.OptimizedMarshaller"> - * <property name="requireSerializable">true</property> - * </bean> - * </property> - * ... - * </bean> - * </pre> - * <p> - * <img src="http://ignite.apache.org/images/spring-small.png"> - * <br> - * For information about Spring framework visit <a href="http://www.springframework.org/">www.springframework.org</a> - */ -public class OptimizedMarshaller extends AbstractNodeNameAwareMarshaller { - /** Use default {@code serialVersionUID} for {@link Serializable} classes. */ - public static final boolean USE_DFLT_SUID = - IgniteSystemProperties.getBoolean(IGNITE_OPTIMIZED_MARSHALLER_USE_DEFAULT_SUID, false); - - /** Default class loader. */ - private final ClassLoader dfltClsLdr = getClass().getClassLoader(); - - /** Whether or not to require an object to be serializable in order to be marshalled. */ - private boolean requireSer = true; - - /** ID mapper. */ - private OptimizedMarshallerIdMapper mapper; - - /** Class descriptors by class. */ - private final ConcurrentMap<Class, OptimizedClassDescriptor> clsMap = new ConcurrentHashMap8<>(); - - /** - * Creates new marshaller will all defaults. - * - * @throws IgniteException If this marshaller is not supported on the current JVM. - */ - public OptimizedMarshaller() { - if (!available()) - throw new IgniteException("Using OptimizedMarshaller on unsupported JVM version (some of " + - "JVM-private APIs required for the marshaller to work are missing)."); - } - - /** - * Creates new marshaller providing whether it should - * require {@link Serializable} interface or not. - * - * @param requireSer Whether to require {@link Serializable}. - */ - public OptimizedMarshaller(boolean requireSer) { - this.requireSer = requireSer; - } - - /** - * Sets whether marshaller should require {@link Serializable} interface or not. - * - * @param requireSer Whether to require {@link Serializable}. - * @return {@code this} for chaining. - */ - public OptimizedMarshaller setRequireSerializable(boolean requireSer) { - this.requireSer = requireSer; - - return this; - } - - /** - * Sets ID mapper. - * - * @param mapper ID mapper. - * @return {@code this} for chaining. - */ - public OptimizedMarshaller setIdMapper(OptimizedMarshallerIdMapper mapper) { - this.mapper = mapper; - - return this; - } - - /** - * Specifies size of cached object streams used by marshaller. Object streams are cached for - * performance reason to avoid costly recreation for every serialization routine. If {@code 0} (default), - * pool is not used and each thread has its own cached object stream which it keeps reusing. - * <p> - * Since each stream has an internal buffer, creating a stream for each thread can lead to - * high memory consumption if many large messages are marshalled or unmarshalled concurrently. - * Consider using pool in this case. This will limit number of streams that can be created and, - * therefore, decrease memory consumption. - * <p> - * NOTE: Using streams pool can decrease performance since streams will be shared between - * different threads which will lead to more frequent context switching. - * - * @param poolSize Streams pool size. If {@code 0}, pool is not used. - * @return {@code this} for chaining. - */ - public OptimizedMarshaller setPoolSize(int poolSize) { - OptimizedObjectStreamRegistry.poolSize(poolSize); - - return this; - } - - /** {@inheritDoc} */ - @Override protected void marshal0(@Nullable Object obj, OutputStream out) throws IgniteCheckedException { - assert out != null; - - OptimizedObjectOutputStream objOut = null; - - try { - objOut = OptimizedObjectStreamRegistry.out(); - - objOut.context(clsMap, ctx, mapper, requireSer); - - objOut.out().outputStream(out); - - objOut.writeObject(obj); - } - catch (IOException e) { - throw new IgniteCheckedException("Failed to serialize object: " + obj, e); - } - finally { - OptimizedObjectStreamRegistry.closeOut(objOut); - } - } - - /** {@inheritDoc} */ - @Override protected byte[] marshal0(@Nullable Object obj) throws IgniteCheckedException { - OptimizedObjectOutputStream objOut = null; - - try { - objOut = OptimizedObjectStreamRegistry.out(); - - objOut.context(clsMap, ctx, mapper, requireSer); - - objOut.writeObject(obj); - - return objOut.out().array(); - } - catch (Exception e) { - throw new IgniteCheckedException("Failed to serialize object: " + obj, e); - } - finally { - OptimizedObjectStreamRegistry.closeOut(objOut); - } - } - - /** {@inheritDoc} */ - @SuppressWarnings("unchecked") - @Override protected <T> T unmarshal0(InputStream in, @Nullable ClassLoader clsLdr) throws IgniteCheckedException { - assert in != null; - - OptimizedObjectInputStream objIn = null; - - try { - objIn = OptimizedObjectStreamRegistry.in(); - - objIn.context(clsMap, ctx, mapper, clsLdr != null ? clsLdr : dfltClsLdr); - - objIn.in().inputStream(in); - - return (T)objIn.readObject(); - } - catch (ClassNotFoundException e) { - throw new IgniteCheckedException("Failed to find class with given class loader for unmarshalling " + - "(make sure same versions of all classes are available on all nodes or enable peer-class-loading) " + - "[clsLdr=" + clsLdr + ", cls=" + e.getMessage() + "]", e); - } - catch (Exception e) { - throw new IgniteCheckedException("Failed to deserialize object with given class loader: " + clsLdr, e); - } - finally { - OptimizedObjectStreamRegistry.closeIn(objIn); - } - } - - /** {@inheritDoc} */ - @SuppressWarnings("unchecked") - @Override protected <T> T unmarshal0(byte[] arr, @Nullable ClassLoader clsLdr) throws IgniteCheckedException { - assert arr != null; - - OptimizedObjectInputStream objIn = null; - - try { - objIn = OptimizedObjectStreamRegistry.in(); - - objIn.context(clsMap, ctx, mapper, clsLdr != null ? clsLdr : dfltClsLdr); - - objIn.in().bytes(arr, arr.length); - - return (T)objIn.readObject(); - } - catch (ClassNotFoundException e) { - throw new IgniteCheckedException("Failed to find class with given class loader for unmarshalling " + - "(make sure same version of all classes are available on all nodes or enable peer-class-loading)" + - " [clsLdr=" + clsLdr + ", cls=" + e.getMessage() + "]", e); - } - catch (Exception e) { - throw new IgniteCheckedException("Failed to deserialize object with given class loader: " + clsLdr, e); - } - finally { - OptimizedObjectStreamRegistry.closeIn(objIn); - } - } - - /** - * Checks whether {@code GridOptimizedMarshaller} is able to work on the current JVM. - * <p> - * As long as {@code GridOptimizedMarshaller} uses JVM-private API, which is not guaranteed - * to be available on all JVM, this method should be called to ensure marshaller could work properly. - * <p> - * Result of this method is automatically checked in constructor. - * - * @return {@code true} if {@code GridOptimizedMarshaller} can work on the current JVM or - * {@code false} if it can't. - */ - @SuppressWarnings({"TypeParameterExtendsFinalClass", "ErrorNotRethrown"}) - public static boolean available() { - try { - Class<? extends Unsafe> unsafeCls = Unsafe.class; - - unsafeCls.getMethod("allocateInstance", Class.class); - unsafeCls.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class); - - return true; - } - catch (Exception ignored) { - return false; - } - catch (NoClassDefFoundError ignored) { - return false; - } - } - - /** - * Undeployment callback invoked when class loader is being undeployed. - * - * @param ldr Class loader being undeployed. - */ - @Override public void onUndeploy(ClassLoader ldr) { - for (Class<?> cls : clsMap.keySet()) { - if (ldr.equals(cls.getClassLoader())) - clsMap.remove(cls); - } - - U.clearClassCache(ldr); - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/a1b5b8c3/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIdMapper.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIdMapper.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIdMapper.java deleted file mode 100644 index 91d07df..0000000 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIdMapper.java +++ /dev/null @@ -1,33 +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.marshaller.optimized; - -/** - * ID mapper. - */ -public interface OptimizedMarshallerIdMapper { - /** - * Gets type ID for provided class name. - * <p> - * If {@code 0} is returned, hash code of class name will be used. - * - * @param clsName Class name. - * @return Type ID. - */ - public int typeId(String clsName); -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/a1b5b8c3/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java deleted file mode 100644 index 60a627a..0000000 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java +++ /dev/null @@ -1,551 +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.marshaller.optimized; - -import java.io.IOException; -import java.io.ObjectStreamClass; -import java.io.Serializable; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.nio.charset.Charset; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.ConcurrentMap; -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.IgniteException; -import org.apache.ignite.internal.util.GridUnsafe; -import org.apache.ignite.internal.util.typedef.F; -import org.apache.ignite.marshaller.MarshallerContext; -import org.apache.ignite.marshaller.jdk.JdkMarshaller; - -import static org.apache.ignite.internal.MarshallerPlatformIds.JAVA_ID; - -/** - * Miscellaneous utility methods to facilitate {@link OptimizedMarshaller}. - */ -class OptimizedMarshallerUtils { - /** */ - static final long HASH_SET_MAP_OFF; - - /** */ - static final byte JDK = -2; - - /** */ - static final byte HANDLE = -1; - - /** */ - static final byte NULL = 0; - - /** */ - static final byte BYTE = 1; - - /** */ - static final byte SHORT = 2; - - /** */ - static final byte INT = 3; - - /** */ - static final byte LONG = 4; - - /** */ - static final byte FLOAT = 5; - - /** */ - static final byte DOUBLE = 6; - - /** */ - static final byte CHAR = 7; - - /** */ - static final byte BOOLEAN = 8; - - /** */ - static final byte BYTE_ARR = 9; - - /** */ - static final byte SHORT_ARR = 10; - - /** */ - static final byte INT_ARR = 11; - - /** */ - static final byte LONG_ARR = 12; - - /** */ - static final byte FLOAT_ARR = 13; - - /** */ - static final byte DOUBLE_ARR = 14; - - /** */ - static final byte CHAR_ARR = 15; - - /** */ - static final byte BOOLEAN_ARR = 16; - - /** */ - static final byte OBJ_ARR = 17; - - /** */ - static final byte STR = 18; - - /** */ - static final byte UUID = 19; - - /** */ - static final byte PROPS = 20; - - /** */ - static final byte ARRAY_LIST = 21; - - /** */ - static final byte HASH_MAP = 22; - - /** */ - static final byte HASH_SET = 23; - - /** */ - static final byte LINKED_LIST = 24; - - /** */ - static final byte LINKED_HASH_MAP = 25; - - /** */ - static final byte LINKED_HASH_SET = 26; - - /** */ - static final byte DATE = 27; - - /** */ - static final byte CLS = 28; - - /** */ - static final byte PROXY = 29; - - /** */ - static final byte ENUM = 100; - - /** */ - static final byte EXTERNALIZABLE = 101; - - /** */ - static final byte SERIALIZABLE = 102; - - /** UTF-8 character name. */ - static final Charset UTF_8 = Charset.forName("UTF-8"); - - /** JDK marshaller. */ - static final JdkMarshaller JDK_MARSH = new JdkMarshaller(); - - static { - long mapOff; - - try { - mapOff = GridUnsafe.objectFieldOffset(HashSet.class.getDeclaredField("map")); - } - catch (NoSuchFieldException ignored) { - try { - // Workaround for legacy IBM JRE. - mapOff = GridUnsafe.objectFieldOffset(HashSet.class.getDeclaredField("backingMap")); - } - catch (NoSuchFieldException e2) { - throw new IgniteException("Initialization failure.", e2); - } - } - - HASH_SET_MAP_OFF = mapOff; - } - - /** - */ - private OptimizedMarshallerUtils() { - // No-op. - } - - /** - * Gets descriptor for provided class. - * - * @param clsMap Class descriptors by class map. - * @param cls Class. - * @param ctx Context. - * @param mapper ID mapper. - * @return Descriptor. - * @throws IOException In case of error. - */ - static OptimizedClassDescriptor classDescriptor( - ConcurrentMap<Class, OptimizedClassDescriptor> clsMap, - Class cls, - MarshallerContext ctx, - OptimizedMarshallerIdMapper mapper) - throws IOException - { - OptimizedClassDescriptor desc = clsMap.get(cls); - - if (desc == null) { - int typeId = resolveTypeId(cls.getName(), mapper); - - boolean registered; - - try { - registered = ctx.registerClassName(JAVA_ID, typeId, cls.getName()); - } - catch (IgniteCheckedException e) { - throw new IOException("Failed to register class: " + cls.getName(), e); - } - - desc = new OptimizedClassDescriptor(cls, registered ? typeId : 0, clsMap, ctx, mapper); - - if (registered) { - OptimizedClassDescriptor old = clsMap.putIfAbsent(cls, desc); - - if (old != null) - desc = old; - } - } - - return desc; - } - - /** - * @param clsName Class name. - * @param mapper Mapper. - * @return Type ID. - */ - private static int resolveTypeId(String clsName, OptimizedMarshallerIdMapper mapper) { - int typeId; - - if (mapper != null) { - typeId = mapper.typeId(clsName); - - if (typeId == 0) - typeId = clsName.hashCode(); - } - else - typeId = clsName.hashCode(); - - return typeId; - } - - /** - * Gets descriptor for provided ID. - * - * @param clsMap Class descriptors by class map. - * @param typeId ID. - * @param ldr Class loader. - * @param ctx Context. - * @param mapper ID mapper. - * @return Descriptor. - * @throws IOException In case of error. - * @throws ClassNotFoundException If class was not found. - */ - static OptimizedClassDescriptor classDescriptor( - ConcurrentMap<Class, OptimizedClassDescriptor> clsMap, - int typeId, - ClassLoader ldr, - MarshallerContext ctx, - OptimizedMarshallerIdMapper mapper) throws IOException, ClassNotFoundException { - Class cls; - - try { - cls = ctx.getClass(typeId, ldr); - } - catch (IgniteCheckedException e) { - throw new IOException("Failed to resolve class for ID: " + typeId, e); - } - - OptimizedClassDescriptor desc = clsMap.get(cls); - - if (desc == null) { - OptimizedClassDescriptor old = clsMap.putIfAbsent(cls, desc = - new OptimizedClassDescriptor(cls, resolveTypeId(cls.getName(), mapper), clsMap, ctx, mapper)); - - if (old != null) - desc = old; - } - - return desc; - } - - /** - * Computes the serial version UID value for the given class. The code is taken from {@link - * ObjectStreamClass#computeDefaultSUID(Class)}. - * - * @param cls A class. - * @param fields Fields. - * @return A serial version UID. - * @throws IOException If failed. - */ - @SuppressWarnings("ForLoopReplaceableByForEach") - static short computeSerialVersionUid(Class cls, List<Field> fields) throws IOException { - if (Serializable.class.isAssignableFrom(cls) && !Enum.class.isAssignableFrom(cls)) { - try { - Field field = cls.getDeclaredField("serialVersionUID"); - - if (field.getType() == long.class) { - int mod = field.getModifiers(); - - if (Modifier.isStatic(mod) && Modifier.isFinal(mod)) { - field.setAccessible(true); - - return (short)field.getLong(null); - } - } - } - catch (NoSuchFieldException ignored) { - // No-op. - } - catch (IllegalAccessException e) { - throw new IOException(e); - } - - if (OptimizedMarshaller.USE_DFLT_SUID) - return (short)ObjectStreamClass.lookup(cls).getSerialVersionUID(); - } - - MessageDigest md; - - try { - md = MessageDigest.getInstance("SHA"); - } - catch (NoSuchAlgorithmException e) { - throw new IOException("Failed to get digest for SHA.", e); - } - - md.update(cls.getName().getBytes(UTF_8)); - - if (!F.isEmpty(fields)) { - for (int i = 0; i < fields.size(); i++) { - Field f = fields.get(i); - - md.update(f.getName().getBytes(UTF_8)); - md.update(f.getType().getName().getBytes(UTF_8)); - } - } - - byte[] hashBytes = md.digest(); - - long hash = 0; - - // Composes a single-long hash from the byte[] hash. - for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) - hash = (hash << 8) | (hashBytes[i] & 0xFF); - - return (short)hash; - } - - /** - * Gets byte field value. - * - * @param obj Object. - * @param off Field offset. - * @return Byte value. - */ - static byte getByte(Object obj, long off) { - return GridUnsafe.getByteField(obj, off); - } - - /** - * Sets byte field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setByte(Object obj, long off, byte val) { - GridUnsafe.putByteField(obj, off, val); - } - - /** - * Gets short field value. - * - * @param obj Object. - * @param off Field offset. - * @return Short value. - */ - static short getShort(Object obj, long off) { - return GridUnsafe.getShortField(obj, off); - } - - /** - * Sets short field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setShort(Object obj, long off, short val) { - GridUnsafe.putShortField(obj, off, val); - } - - /** - * Gets integer field value. - * - * @param obj Object. - * @param off Field offset. - * @return Integer value. - */ - static int getInt(Object obj, long off) { - return GridUnsafe.getIntField(obj, off); - } - - /** - * Sets integer field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setInt(Object obj, long off, int val) { - GridUnsafe.putIntField(obj, off, val); - } - - /** - * Gets long field value. - * - * @param obj Object. - * @param off Field offset. - * @return Long value. - */ - static long getLong(Object obj, long off) { - return GridUnsafe.getLongField(obj, off); - } - - /** - * Sets long field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setLong(Object obj, long off, long val) { - GridUnsafe.putLongField(obj, off, val); - } - - /** - * Gets float field value. - * - * @param obj Object. - * @param off Field offset. - * @return Float value. - */ - static float getFloat(Object obj, long off) { - return GridUnsafe.getFloatField(obj, off); - } - - /** - * Sets float field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setFloat(Object obj, long off, float val) { - GridUnsafe.putFloatField(obj, off, val); - } - - /** - * Gets double field value. - * - * @param obj Object. - * @param off Field offset. - * @return Double value. - */ - static double getDouble(Object obj, long off) { - return GridUnsafe.getDoubleField(obj, off); - } - - /** - * Sets double field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setDouble(Object obj, long off, double val) { - GridUnsafe.putDoubleField(obj, off, val); - } - - /** - * Gets char field value. - * - * @param obj Object. - * @param off Field offset. - * @return Char value. - */ - static char getChar(Object obj, long off) { - return GridUnsafe.getCharField(obj, off); - } - - /** - * Sets char field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setChar(Object obj, long off, char val) { - GridUnsafe.putCharField(obj, off, val); - } - - /** - * Gets boolean field value. - * - * @param obj Object. - * @param off Field offset. - * @return Boolean value. - */ - static boolean getBoolean(Object obj, long off) { - return GridUnsafe.getBooleanField(obj, off); - } - - /** - * Sets boolean field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setBoolean(Object obj, long off, boolean val) { - GridUnsafe.putBooleanField(obj, off, val); - } - - /** - * Gets field value. - * - * @param obj Object. - * @param off Field offset. - * @return Value. - */ - static Object getObject(Object obj, long off) { - return GridUnsafe.getObjectField(obj, off); - } - - /** - * Sets field value. - * - * @param obj Object. - * @param off Field offset. - * @param val Value. - */ - static void setObject(Object obj, long off, Object val) { - GridUnsafe.putObjectField(obj, off, val); - } -}
