- 介绍
- 示例`
- 实现简易Pool
- 源码
介绍
Kryo是一个快速有效的对象图序列化Java库。它的目标是快速、高效、易使用。该项目适用于对象持久化到文件或数据库中或通过网络传输。Kryo还可以自动实现深浅的拷贝/克隆。 就是直接复制一个对象对象到另一个对象,而不是对象转换为字节然后转化为对象。
Kryo如果设置References=true
,序列化的时候会从缓存中获取之前序列化过的对象,从而提高效率。
特点
- 序列化、反序列化速度快。
- 序列化和反序列化,第1次加载类的全部信息,如果使用代码里
reference=true
。默认会生成和对象相对应的id值。但第2次、第N次加载类时,会根据id值去缓存中查找相对应的对象。示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14Kryo kryo = new Kryo();
//是否使用引用,默认开启,使用引用对象会和id进行关联
kryo.setReferences(false);
//注册对象,使用java的原生序列化对象
kryo.register(obj.getClass(), new JavaSerializer());
// 序列化
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// 反序列化
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();
实现简易Pool
结构
KryoPool
1 | public interface KryoPool { |
pool
内部构建类。KryoPool#Builder#build
,创建pool
,如果开启softReferences
(软引用),新建一个SoftReferenceQueue
(软引用队列)。否则使用ConcurrentLinkedQueue
。KryoFactory
1
2
3
4
5
6/** Factory to create new configured instances of {@link Kryo}.
*
* @author Martin Grotzke */
public interface KryoFactory {
Kryo create ();
}
KryoCallback
1 | /** Callback to run with a provided kryo instance. |
SoftReferenceQueue
1 | /** Internally uses {@link SoftReference}s for queued Kryo instances, most importantly adjusts the {@link Queue#poll() poll} |
软引用队列,实现Queue
。
源码
项目结构
ClassResolver
:类级别的解释器,把class注册到缓存,根据name、class从缓存中获取注册对象(Registration
)。ReferenceResolver
:引用级别的解释器,把class类中的引用注册到缓存(class类中的引用就是属性),根据referenceId
从缓存中获取对象。Serializer
:序列化接口。实现类通过不同的方式实现此接口。Registration
:注册类。把class注册到缓存,下次从缓存获取对象。属性:id(Class的Id),class,serializer实现类。包结构
factories
:序列化工厂io
:封装的io
类.其中重要Input
,Output
.pool
:Kryo池,通过ConcurrentLinkedQueue
实现,Pool
中实现构造Pool
属性的内部类.serializers
:序列化种类util
:自定义实现的集合类:Map
,List.实现Map,List
,Default的ClassResolver
序列化
Kryo
Kryo主类,实现Write
、Read
、Copy
。Kryo实例属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48//id对应的对象状态
static public final byte NULL = 0;
static public final byte NOT_NULL = 1;
//id对应的对象类型:引用、非引用
static private final int REF = -1;
static private final int NO_REF = -2;
//默认的serializer
private SerializerFactory defaultSerializer = new ReflectionSerializerFactory(FieldSerializer.class);
private final ArrayList<DefaultSerializerEntry> defaultSerializers = new ArrayList(33);
private final int lowPriorityDefaultSerializerCount;
//类解释器接口实例
private final ClassResolver classResolver;
//下一个注册id
private int nextRegisterID;
private ClassLoader classLoader = getClass().getClassLoader();
private InstantiatorStrategy strategy = new DefaultInstantiatorStrategy();
//必须注册
private boolean registrationRequired;
private boolean warnUnregisteredClasses;
//write,read操作序数
private int depth, maxDepth = Integer.MAX_VALUE;
private boolean autoReset = true;
//判断是否是当前线程,代码中日志级别是warn
private volatile Thread thread;
//存储对象的Map
private ObjectMap context, graphContext;
//引用解释器接口实例
private ReferenceResolver referenceResolver;
//read操作referenceId的数组
private final IntArray readReferenceIds = new IntArray(0);
private boolean references, copyReferences = true;
//read操作返回的对象
private Object readObject;
//深度复制对象
private int copyDepth;
//浅度复制对象
private boolean copyShallow;
//原对象to复制
private IdentityMap originalToCopy;
//需要复制的引用
private Object needsCopyReference;
//泛型解释器
private GenericsResolver genericsResolver = new GenericsResolver();
private FieldSerializerConfig fieldSerializerConfig = new FieldSerializerConfig();
private TaggedFieldSerializerConfig taggedFieldSerializerConfig = new TaggedFieldSerializerConfig();
private StreamFactory streamFactory;
Kryo#kryo()
初始化默认Serializer
、注册基本类型1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67/** @param referenceResolver May be null to disable references. */
public Kryo (ClassResolver classResolver, ReferenceResolver referenceResolver, StreamFactory streamFactory) {
if (classResolver == null) throw new IllegalArgumentException("classResolver cannot be null.");
this.classResolver = classResolver;
classResolver.setKryo(this);
this.streamFactory = streamFactory;
streamFactory.setKryo(this);
this.referenceResolver = referenceResolver;
if (referenceResolver != null) {
referenceResolver.setKryo(this);
references = true;
}
addDefaultSerializer(byte[].class, ByteArraySerializer.class);
addDefaultSerializer(char[].class, CharArraySerializer.class);
addDefaultSerializer(short[].class, ShortArraySerializer.class);
addDefaultSerializer(int[].class, IntArraySerializer.class);
addDefaultSerializer(long[].class, LongArraySerializer.class);
addDefaultSerializer(float[].class, FloatArraySerializer.class);
addDefaultSerializer(double[].class, DoubleArraySerializer.class);
addDefaultSerializer(boolean[].class, BooleanArraySerializer.class);
addDefaultSerializer(String[].class, StringArraySerializer.class);
addDefaultSerializer(Object[].class, ObjectArraySerializer.class);
addDefaultSerializer(KryoSerializable.class, KryoSerializableSerializer.class);
addDefaultSerializer(BigInteger.class, BigIntegerSerializer.class);
addDefaultSerializer(BigDecimal.class, BigDecimalSerializer.class);
addDefaultSerializer(Class.class, ClassSerializer.class);
addDefaultSerializer(Date.class, DateSerializer.class);
addDefaultSerializer(Enum.class, EnumSerializer.class);
addDefaultSerializer(EnumSet.class, EnumSetSerializer.class);
addDefaultSerializer(Currency.class, CurrencySerializer.class);
addDefaultSerializer(StringBuffer.class, StringBufferSerializer.class);
addDefaultSerializer(StringBuilder.class, StringBuilderSerializer.class);
addDefaultSerializer(Collections.EMPTY_LIST.getClass(), CollectionsEmptyListSerializer.class);
addDefaultSerializer(Collections.EMPTY_MAP.getClass(), CollectionsEmptyMapSerializer.class);
addDefaultSerializer(Collections.EMPTY_SET.getClass(), CollectionsEmptySetSerializer.class);
addDefaultSerializer(Collections.singletonList(null).getClass(), CollectionsSingletonListSerializer.class);
addDefaultSerializer(Collections.singletonMap(null, null).getClass(), CollectionsSingletonMapSerializer.class);
addDefaultSerializer(Collections.singleton(null).getClass(), CollectionsSingletonSetSerializer.class);
addDefaultSerializer(TreeSet.class, TreeSetSerializer.class);
addDefaultSerializer(Collection.class, CollectionSerializer.class);
addDefaultSerializer(TreeMap.class, TreeMapSerializer.class);
addDefaultSerializer(Map.class, MapSerializer.class);
addDefaultSerializer(TimeZone.class, TimeZoneSerializer.class);
addDefaultSerializer(Calendar.class, CalendarSerializer.class);
addDefaultSerializer(Locale.class, LocaleSerializer.class);
addDefaultSerializer(Charset.class, CharsetSerializer.class);
addDefaultSerializer(URL.class, URLSerializer.class);
OptionalSerializers.addDefaultSerializers(this);
TimeSerializers.addDefaultSerializers(this);
lowPriorityDefaultSerializerCount = defaultSerializers.size();
// Primitives and string. Primitive wrappers automatically use the same registration as primitives.
register(int.class, new IntSerializer());
register(String.class, new StringSerializer());
register(float.class, new FloatSerializer());
register(boolean.class, new BooleanSerializer());
register(byte.class, new ByteSerializer());
register(char.class, new CharSerializer());
register(short.class, new ShortSerializer());
register(long.class, new LongSerializer());
register(double.class, new DoubleSerializer());
register(void.class, new VoidSerializer());
}
Kryo#writeClassAndObject(Output output, Object object)
序列化对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/** Writes the class and object or null using the registered serializer.
* @param object May be null. */
public void writeClassAndObject (Output output, Object object) {
if (output == null) throw new IllegalArgumentException("output cannot be null.");
beginObject();
try {
if (object == null) {
writeClass(output, null);
return;
}
//返回注册对象
Registration registration = writeClass(output, object.getClass());
//使用references方式序列化,writeReferenceOrNull 从缓存中获取,则执行下列代码,也就是不执行write操作.因为数据已经序列化到缓存了.
//非第1次或者null,数据已经存在缓存中,不需要执行其他逻辑
//true:缓存中存在数据
//false:缓存中不存在数据
if (references && writeReferenceOrNull(output, object, false)) {
//设置泛型
registration.getSerializer().setGenerics(this, null);
return;
}
if (TRACE || (DEBUG && depth == 1)) log("Write", object);
//注册对象获取serializer的write方式进行序列化,相当于实时执行序列化
//基本数据类型的引用是实时write
registration.getSerializer().write(this, output, object);
} finally {
if (--depth == 0 && autoReset) reset();
}
}
- 执行
BeginObject()
,depth++
、判断当前是否是多线程。 object == null
,执行writeClass(output, null)
,返回注册对象(Registration
)- writeReferenceOrNull(),引用类型第1次、基本类型 是
return false
;引用类型非第1次、null
是return true
。如果是null
和非第1次(说明数据已经存在缓存中),执行if
中的操作。 registration.getSerializer().write(this, output, object)
,相当于实时write()
数据。基本类型也是实时write()
数据。Kryo#writeClass(Output output, Class type)
输出class,获得注册对象1
2
3
4
5
6
7
8
9
10
11
12
13/** Writes a class and returns its registration.
* @param type May be null.
* @return Will be null if type is null.
* @see ClassResolver#writeClass(Output, Class) */
public Registration writeClass (Output output, Class type) {
if (output == null) throw new IllegalArgumentException("output cannot be null.");
try {
//class解释器实现类实例对象
return classResolver.writeClass(output, type);
} finally {
if (depth == 0 && autoReset) reset();
}
}
classResolver
默认是由DefaultClassResolver()
实现1
2
3public Kryo () {
this(new DefaultClassResolver(), new MapReferenceResolver(), new DefaultStreamFactory());
}
Kryo#writeReferenceOrNull(Output output, Object object, boolean mayBeNull)
write reference
或者 null
对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37/** @param object May be null if mayBeNull is true.
* @return true if no bytes need to be written for the object. */
//第1次、基本类型return false;非第1次、null return true
//true:缓存中存在数据
//false:缓存中不存在数据
boolean writeReferenceOrNull (Output output, Object object, boolean mayBeNull) {
if (object == null) {
if (TRACE || (DEBUG && depth == 1)) log("Write", null);
//null object 在byte缓存的数据范围
output.writeVarInt(Kryo.NULL, true);
return true;
}
//true:基本类型对象;false:引用对象
if (!referenceResolver.useReferences(object.getClass())) {
//基本类型对象的not null存储范围
if (mayBeNull) output.writeVarInt(Kryo.NOT_NULL, true);
return false;
}
// Determine if this object has already been seen in this object graph.
//从缓存中获取referenceId
int id = referenceResolver.getWrittenId(object);
// If not the first time encountered, only write reference ID.
//非第1次
if (id != -1) {
if (DEBUG) debug("kryo", "Write object reference " + id + ": " + string(object));
output.writeVarInt(id + 2, true); // + 2 because 0 and 1 are used for NULL and NOT_NULL.
return true;
}
//第1次,添加到缓存中
// Otherwise write NOT_NULL and then the object bytes.
id = referenceResolver.addWrittenObject(object);
output.writeVarInt(NOT_NULL, true);
if (TRACE) trace("kryo", "Write initial object reference " + id + ": " + string(object));
return false;
}
- 引用类型第1次、基本类型是
return false
。 - 引用类型非第1次、
null
是return true
。 - 这
id
就是reference id
。 方法返回值,
true
是缓存中存在数据。false
是缓存中不存在数据。ReferenceResolver结构
引用解释器接口,根据
referenceId
获取reference
,把reference
存入缓存。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35/** When references are enabled, this tracks objects that have already been read or written, provides an ID for objects that are
1. written, and looks up by ID objects that have been read.
2. @author Nathan Sweet <misc@n4te.com> */
public interface ReferenceResolver {
/** Sets the Kryo instance that this ClassResolver will be used for. This is called automatically by Kryo. */
public void setKryo (Kryo kryo);
/** Returns an ID for the object if it has been written previously, otherwise returns -1. */
public int getWrittenId (Object object);
/** Returns a new ID for an object that is being written for the first time.
* @return The ID, which is stored more efficiently if it is positive and must not be -1 or -2. */
public int addWrittenObject (Object object);
/** Reserves the ID for the next object that will be read. This is called only the first time an object is encountered.
* @param type The type of object that will be read.
* @return The ID, which is stored more efficiently if it is positive and must not be -1 or -2. */
public int nextReadId (Class type);
/** Sets the ID for an object that has been read.
* @param id The ID from {@link #nextReadId(Class)}. */
public void setReadObject (int id, Object object);
/** Returns the object for the specified ID. The ID and object are guaranteed to have been previously passed in a call to
* {@link #setReadObject(int, Object)}. */
//返回对象指定ID,ID和对象是保证之前调用传入
public Object getReadObject (Class type, int id);
/** Called by {@link Kryo#reset()}. */
public void reset ();
/** Returns true if references will be written for the specified type.
* @param type Will never be a primitive type, but may be a primitive type wrapper. */
public boolean useReferences (Class type);
}referenceId
和reference
是对应的。ClassResolver
类解释器接口,类存入缓存方式(
classId
、nameId
),从缓存中获取class方式,对象的注册,获取注册对象,输出类,读取类。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31/** Handles class registration, writing class identifiers to bytes, and reading class identifiers from bytes.
* @author Nathan Sweet <misc@n4te.com> */
public interface ClassResolver {
/** Sets the Kryo instance that this ClassResolver will be used for. This is called automatically by Kryo. */
public void setKryo (Kryo kryo);
/** Stores the specified registration.
* @see Kryo#register(Registration) */
public Registration register (Registration registration);
/** Called when an unregistered type is encountered and {@link Kryo#setRegistrationRequired(boolean)} is false. */
public Registration registerImplicit (Class type);
/** Returns the registration for the specified class, or null if the class is not registered. */
public Registration getRegistration (Class type);
/** Returns the registration for the specified ID, or null if no class is registered with that ID. */
public Registration getRegistration (int classID);
/** Writes a class and returns its registration.
* @param type May be null.
* @return Will be null if type is null. */
public Registration writeClass (Output output, Class type);
/** Reads a class and returns its registration.
* @return May be null. */
public Registration readClass (Input input);
/** Called by {@link Kryo#reset()}. */
public void reset ();
}
Registration
注册对象类(class、reference)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/** Describes the {@link Serializer} and class ID to use for a class.
* @author Nathan Sweet <misc@n4te.com> */
public class Registration {
/**
* 注册类
*/
private final Class type;
/**
* 注册的id
*/
private final int id;
/**
* 序列化方式
*/
private Serializer serializer;
/**
* 复制对象
*/
private ObjectInstantiator instantiator;
...
}
Serializer
序列化抽象类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83/** Reads and writes objects to and from bytes.
* @author Nathan Sweet <misc@n4te.com> */
public abstract class Serializer<T> {
//允许为空、不可变
private boolean acceptsNull, immutable;
public Serializer () {
}
/** @see #setAcceptsNull(boolean) */
public Serializer (boolean acceptsNull) {
this.acceptsNull = acceptsNull;
}
/** @see #setAcceptsNull(boolean)
* @see #setImmutable(boolean) */
public Serializer (boolean acceptsNull, boolean immutable) {
this.acceptsNull = acceptsNull;
this.immutable = immutable;
}
/** Writes the bytes for the object to the output.
* <p>
* This method should not be called directly, instead this serializer can be passed to {@link Kryo} write methods that accept a
* serialier.
* @param object May be null if {@link #getAcceptsNull()} is true. */
abstract public void write (Kryo kryo, Output output, T object);
/** Reads bytes and returns a new object of the specified concrete type.
* <p>
* Before Kryo can be used to read child objects, {@link Kryo#reference(Object)} must be called with the parent object to
* ensure it can be referenced by the child objects. Any serializer that uses {@link Kryo} to read a child object may need to
* be reentrant.
* <p>
* This method should not be called directly, instead this serializer can be passed to {@link Kryo} read methods that accept a
* serialier.
* @return May be null if {@link #getAcceptsNull()} is true. */
abstract public T read (Kryo kryo, Input input, Class<T> type);
public boolean getAcceptsNull () {
return acceptsNull;
}
/** If true, this serializer will handle writing and reading null values. If false, the Kryo framework handles null values and
* the serializer will never receive null.
* <p>
* This can be set to true on a serializer that does not accept nulls if it is known that the serializer will never encounter
* null. Doing this will prevent the framework from writing a byte to denote null. */
public void setAcceptsNull (boolean acceptsNull) {
this.acceptsNull = acceptsNull;
}
public boolean isImmutable () {
return immutable;
}
/** If true, the type this serializer will be used for is considered immutable. This causes {@link #copy(Kryo, Object)} to
* return the original object. */
public void setImmutable (boolean immutable) {
this.immutable = immutable;
}
/** Sets the generic types of the field or method this serializer will be used for on the next call to read or write.
* Subsequent calls to read and write must not use this generic type information. The default implementation does nothing.
* Subclasses may use the information provided to this method for more efficient serialization, eg to use the same type for all
* items in a list.
* @param generics Some (but never all) elements may be null if there is no generic type information at that index. */
public void setGenerics (Kryo kryo, Class[] generics) {
}
/** Returns a copy of the specified object. The default implementation returns the original if {@link #isImmutable()} is true,
* else throws {@link KryoException}. Subclasses should override this method if needed to support {@link Kryo#copy(Object)}.
* <p>
* Before Kryo can be used to copy child objects, {@link Kryo#reference(Object)} must be called with the copy to ensure it can
* be referenced by the child objects. Any serializer that uses {@link Kryo} to copy a child object may need to be reentrant.
* <p>
* This method should not be called directly, instead this serializer can be passed to {@link Kryo} copy methods that accept a
* serialier. */
public T copy (Kryo kryo, T original) {
if (immutable) return original;
throw new KryoException("Serializer does not support copy: " + getClass().getName());
}
}
MapReferenceResolver结构
通过Map
来存储reference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53/** Uses an {@link IdentityObjectIntMap} to track objects that have already been written. This can handle graph with any number of
1. objects, but is slightly slower than {@link ListReferenceResolver} for graphs with few objects.
2. @author Nathan Sweet <misc@n4te.com> */
public class MapReferenceResolver implements ReferenceResolver {
protected Kryo kryo;
/**
* 存储id、reference的Map
*/
protected final IdentityObjectIntMap writtenObjects = new IdentityObjectIntMap();
/**
* read根据id作为list的index,获取reference
*/
protected final ArrayList readObjects = new ArrayList();
public void setKryo (Kryo kryo) {
this.kryo = kryo;
}
public int addWrittenObject (Object object) {
int id = writtenObjects.size;
writtenObjects.put(object, id);
return id;
}
public int getWrittenId (Object object) {
return writtenObjects.get(object, -1);
}
public int nextReadId (Class type) {
int id = readObjects.size();
readObjects.add(null);
return id;
}
public void setReadObject (int id, Object object) {
readObjects.set(id, object);
}
public Object getReadObject (Class type, int id) {
return readObjects.get(id);
}
public void reset () {
readObjects.clear();
writtenObjects.clear();
}
/** Returns false for all primitive wrappers. */
//true:引用对象
public boolean useReferences (Class type) {
return !Util.isWrapperClass(type);
}
}
writtenObjects
,object
作为key
,id
作为value
readObjects
,id
作为index
IdentityObjectIntMap结构
自定义Map
,存储id
和reference
。
引用对象:模仿HashMap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// primes for hash functions 2, 3, and 4
// 为了hash2、hash3、hash3
private static final int PRIME2 = 0xbe1f14b1;
private static final int PRIME3 = 0xb4b82e39;
private static final int PRIME4 = 0xced1c241;
public int size;
/**
* key的数组
*/
K[] keyTable;
/**
* value的数组
*/
int[] valueTable;
/**
* 扩容因子
*/
int capacity, stashSize;
private float loadFactor;
private int hashShift, mask, threshold;
private int stashCapacity;
private int pushIterations;
private boolean isBigTable;
IdentityObjectIntMap#put()
1 | public void put (K key, int value) { |
keyTable[index1] !=null
,比较key
值,相同则更新数据。keyTable[index1] ==null
,重新给key
、value
赋值。以上2条都不执行,则执行
push()
IdentityObjectIntMap#push()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91private void push (K insertKey, int insertValue, int index1, K key1, int index2, K key2, int index3, K key3, int index4,
K key4) {
// avoid getfield opcode
K[] keyTable = this.keyTable;
int[] valueTable = this.valueTable;
int mask = this.mask;
boolean isBigTable = this.isBigTable;
// Push keys until an empty bucket is found.
K evictedKey;
int evictedValue;
int i = 0, pushIterations = this.pushIterations;
int n = isBigTable ? 4 : 3;
do {
// Replace the key and value for one of the hashes.
//随机的覆盖key、value在某个hash点上
switch (ObjectMap.random.nextInt(n)) {
case 0:
evictedKey = key1;
evictedValue = valueTable[index1];
keyTable[index1] = insertKey;
valueTable[index1] = insertValue;
break;
case 1:
evictedKey = key2;
evictedValue = valueTable[index2];
keyTable[index2] = insertKey;
valueTable[index2] = insertValue;
break;
case 2:
evictedKey = key3;
evictedValue = valueTable[index3];
keyTable[index3] = insertKey;
valueTable[index3] = insertValue;
break;
default:
evictedKey = key4;
evictedValue = valueTable[index4];
keyTable[index4] = insertKey;
valueTable[index4] = insertValue;
break;
}
// If the evicted key hashes to an empty bucket, put it there and stop.
int hashCode = System.identityHashCode(evictedKey);
index1 = hashCode & mask;
key1 = keyTable[index1];
if (key1 == null) {
keyTable[index1] = evictedKey;
valueTable[index1] = evictedValue;
if (size++ >= threshold) resize(capacity << 1);
return;
}
index2 = hash2(hashCode);
key2 = keyTable[index2];
if (key2 == null) {
keyTable[index2] = evictedKey;
valueTable[index2] = evictedValue;
if (size++ >= threshold) resize(capacity << 1);
return;
}
index3 = hash3(hashCode);
key3 = keyTable[index3];
if (key3 == null) {
keyTable[index3] = evictedKey;
valueTable[index3] = evictedValue;
if (size++ >= threshold) resize(capacity << 1);
return;
}
if (isBigTable) {
index4 = hash4(hashCode);
key4 = keyTable[index4];
if (key4 == null) {
keyTable[index4] = evictedKey;
valueTable[index4] = evictedValue;
if (size++ >= threshold) resize(capacity << 1);
return;
}
}
if (++i == pushIterations) break;
insertKey = evictedKey;
insertValue = evictedValue;
} while (true);
putStash(evictedKey, evictedValue);
}随机的覆盖
key
、value
在某个hash
点上。keyTable[index1] == null
,覆盖当前的key
、value
在这个hash
点上,条件满足时,扩容。IdentityObjectIntMap#putStash()
容器size++
,put
操作的key
、value
赋值到key[]
、value[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14private void putStash (K key, int value) {
if (stashSize == stashCapacity) {
// Too many pushes occurred and the stash is full, increase the table size.
resize(capacity << 1);
put(key, value);
return;
}
// Store key in the stash.
int index = capacity + stashSize;
keyTable[index] = key;
valueTable[index] = value;
stashSize++;
size++;
}
IdentityObjectIntMap#get()
根据key
值获取id
,如果都找不到、则返回默认值1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/** @param defaultValue Returned if the key was not associated with a value. */
public int get (K key, int defaultValue) {
int hashCode = System.identityHashCode(key);
int index = hashCode & mask;
if (key != keyTable[index]) {
index = hash2(hashCode);
if (key != keyTable[index]) {
index = hash3(hashCode);
if (key != keyTable[index]) {
if (isBigTable) {
index = hash4(hashCode);
if (key != keyTable[index]) return getStash(key, defaultValue);
} else {
return getStash(key, defaultValue);
}
}
}
}
return valueTable[index];
}
DefaultClassResolver
默认类解释器实现类,类存入缓存方式(nameId
,classId
),从缓存中获取class方式(nameId
、classId
),对象的注册,获取注册对象,输出类,读取类。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230/** Resolves classes by ID or by fully qualified class name.
1. @author Nathan Sweet <misc@n4te.com> */
public class DefaultClassResolver implements ClassResolver {
static public final byte NAME = -1;
protected Kryo kryo;
/**
* id获取注册对象
*/
protected final IntMap<Registration> idToRegistration = new IntMap();
/**
* class类型获取注册对象
*/
protected final ObjectMap<Class, Registration> classToRegistration = new ObjectMap();
/**
* class、nameId缓存
*/
protected IdentityObjectIntMap<Class> classToNameId;
/**
* nameId、class缓存
*/
protected IntMap<Class> nameIdToClass;
/**
* name、class的缓存
*/
protected ObjectMap<String, Class> nameToClass;
/**
* name的id
*/
protected int nextNameId;
/**
* 缓存classId
*/
private int memoizedClassId = -1;
/**
* 缓存classId注册对象
*/
private Registration memoizedClassIdValue;
//缓存中的class
private Class memoizedClass;
//缓存中的class注册对象
private Registration memoizedClassValue;
public void setKryo (Kryo kryo) {
this.kryo = kryo;
}
/**
*
* @param registration
* @return
*/
public Registration register (Registration registration) {
if (registration == null) throw new IllegalArgumentException("registration cannot be null.");
//非原始name值
if (registration.getId() != NAME) {
if (TRACE) {
trace("kryo", "Register class ID " + registration.getId() + ": " + className(registration.getType()) + " ("
+ registration.getSerializer().getClass().getName() + ")");
}
//根据id存入注册对象
idToRegistration.put(registration.getId(), registration);
} else if (TRACE) {
trace("kryo", "Register class name: " + className(registration.getType()) + " ("
+ registration.getSerializer().getClass().getName() + ")");
}
//根据class存入注册对象
classToRegistration.put(registration.getType(), registration);
if (registration.getType().isPrimitive()) classToRegistration.put(getWrapperClass(registration.getType()), registration);
return registration;
}
public Registration registerImplicit (Class type) {
return register(new Registration(type, kryo.getDefaultSerializer(type), NAME));
}
public Registration getRegistration (Class type) {
//直接获取缓存注册对象
if (type == memoizedClass) return memoizedClassValue;
//全局状态下,直接获取注册对象
Registration registration = classToRegistration.get(type);
if (registration != null) {
memoizedClass = type;
memoizedClassValue = registration;
}
return registration;
}
public Registration getRegistration (int classID) {
return idToRegistration.get(classID);
}
/**
* 根据class write操作
* @param output
* @param type May be null.
* @return
*/
public Registration writeClass (Output output, Class type) {
if (type == null) {
if (TRACE || (DEBUG && kryo.getDepth() == 1)) log("Write", null);
//null对象的缓存byte存储的位置
output.writeVarInt(Kryo.NULL, true);
return null;
}
//获取注册对象
Registration registration = kryo.getRegistration(type);
//第1次write
if (registration.getId() == NAME)
//没有classId,根据name获取注册对象
writeName(output, type, registration);
else {//非第1次,写入classId
if (TRACE) trace("kryo", "Write class " + registration.getId() + ": " + className(type));
output.writeVarInt(registration.getId() + 2, true);
}
return registration;
}
/**
* 根据name write操作
* @param output
* @param type
* @param registration
*/
protected void writeName (Output output, Class type, Registration registration) {
output.writeVarInt(NAME + 2, true);
//有缓存
if (classToNameId != null) {
//根据class获取nameId
int nameId = classToNameId.get(type, -1);
if (nameId != -1) {
if (TRACE) trace("kryo", "Write class name reference " + nameId + ": " + className(type));
output.writeVarInt(nameId, true);
return;
}
}
// Only write the class name the first time encountered in object graph.
if (TRACE) trace("kryo", "Write class name: " + className(type));
//new nameId
int nameId = nextNameId++;
if (classToNameId == null) classToNameId = new IdentityObjectIntMap();
//class、nameId存入缓存
classToNameId.put(type, nameId);
output.writeVarInt(nameId, true);
output.writeString(type.getName());
}
/**
* 读取class
* @param input
* @return
*/
public Registration readClass (Input input) {
//获取class的id标识
int classID = input.readVarInt(true);
switch (classID) {
case Kryo.NULL:
if (TRACE || (DEBUG && kryo.getDepth() == 1)) log("Read", null);
return null;
case NAME + 2: // Offset for NAME and NULL.
//classId实际上就是nameId,根据nameId获取对象
return readName(input);
}
if (classID == memoizedClassId) return memoizedClassIdValue;
//class的注册对象
Registration registration = idToRegistration.get(classID - 2);
if (registration == null) throw new KryoException("Encountered unregistered class ID: " + (classID - 2));
if (TRACE) trace("kryo", "Read class " + (classID - 2) + ": " + className(registration.getType()));
//新的classId、注册对象赋值到缓存变量
memoizedClassId = classID;
memoizedClassIdValue = registration;
return registration;
}
/**
* 读取class name
* @param input
* @return
*/
protected Registration readName (Input input) {
int nameId = input.readVarInt(true);
//缓存
if (nameIdToClass == null) nameIdToClass = new IntMap();
//根据nameId获取class
Class type = nameIdToClass.get(nameId);
if (type == null) {
// Only read the class name the first time encountered in object graph.
String className = input.readString();
type = getTypeByName(className);
//class is null,通过反射获取class
if (type == null) {
try {
type = Class.forName(className, false, kryo.getClassLoader());
} catch (ClassNotFoundException ex) {
if (WARN) warn("kryo", "Unable to load class " + className + " with kryo's ClassLoader. Retrying with current..");
try {
type = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new KryoException("Unable to find class: " + className, ex);
}
}
if (nameToClass == null) nameToClass = new ObjectMap();
//根据class存入缓存
nameToClass.put(className, type);
}
//根据nameId存入缓存中
nameIdToClass.put(nameId, type);
if (TRACE) trace("kryo", "Read class name: " + className);
} else {
if (TRACE) trace("kryo", "Read class name reference " + nameId + ": " + className(type));
}
return kryo.getRegistration(type);
}
protected Class<?> getTypeByName (final String className) {
return nameToClass != null ? nameToClass.get(className) : null;
}
public void reset () {
if (!kryo.isRegistrationRequired()) {
if (classToNameId != null) classToNameId.clear();
if (nameIdToClass != null) nameIdToClass.clear();
nextNameId = 0;
}
}
}
- writeClass 最终可能还是执行writeName。
- readClass 最终执行readName。
Output结构
继承Java的OutputStream
,把对象存储byte[]
,这byte[]
作为缓存使用1
public class Output extends OutputStream
Output#writeVarInt (int value, boolean optimizePositive)
写入int
到byte[]
,返回int
占byte[]
的长度1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42/** Writes a 1-5 byte int. It is guaranteed that a varible length encoding will be used.
*
* @param optimizePositive If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be
* inefficient (5 bytes). */
public int writeVarInt (int value, boolean optimizePositive) throws KryoException {
if (!optimizePositive) value = (value << 1) ^ (value >> 31);
if (value >>> 7 == 0) {
require(1);
buffer[position++] = (byte)value;
return 1;
}
if (value >>> 14 == 0) {
require(2);
buffer[position++] = (byte)((value & 0x7F) | 0x80);
buffer[position++] = (byte)(value >>> 7);
return 2;
}
if (value >>> 21 == 0) {
require(3);
buffer[position++] = (byte)((value & 0x7F) | 0x80);
buffer[position++] = (byte)(value >>> 7 | 0x80);
buffer[position++] = (byte)(value >>> 14);
return 3;
}
if (value >>> 28 == 0) {
require(4);
buffer[position++] = (byte)((value & 0x7F) | 0x80);
buffer[position++] = (byte)(value >>> 7 | 0x80);
buffer[position++] = (byte)(value >>> 14 | 0x80);
buffer[position++] = (byte)(value >>> 21);
return 4;
}
//需要5个字节的空间
require(5);
buffer[position++] = (byte)((value & 0x7F) | 0x80);
buffer[position++] = (byte)(value >>> 7 | 0x80);
buffer[position++] = (byte)(value >>> 14 | 0x80);
buffer[position++] = (byte)(value >>> 21 | 0x80);
buffer[position++] = (byte)(value >>> 28);
//返回byte[]的长度
return 5;
}
Output#require (int required)
byte[]
的扩容1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/** @return true if the buffer has been resized. */
//重置数组的长度
protected boolean require (int required) throws KryoException {
if (capacity - position >= required) return false;
if (required > maxCapacity)
throw new KryoException("Buffer overflow. Max capacity: " + maxCapacity + ", required: " + required);
flush();
while (capacity - position < required) {
if (capacity == maxCapacity)
throw new KryoException("Buffer overflow. Available: " + (capacity - position) + ", required: " + required);
// Grow buffer.
if (capacity == 0) capacity = 1;
capacity = Math.min(capacity * 2, maxCapacity);
if (capacity < 0) capacity = maxCapacity;
byte[] newBuffer = new byte[capacity];
System.arraycopy(buffer, 0, newBuffer, 0, position);
buffer = newBuffer;
}
return true;
}
JavaSerializer
Java自带的序列化方式。官方提示:此方法不高效,应该尽量避免使用。
1 | /** Serializes objects using Java's built in serialization mechanism. Note that this is very inefficient and should be avoided if |
MapSerializer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171/** Serializes objects that implement the {@link Map} interface.
* <p>
* With the default constructor, a map requires a 1-3 byte header and an extra 4 bytes is written for each key/value pair.
* @author Nathan Sweet <misc@n4te.com> */
public class MapSerializer extends Serializer<Map> {
private Class keyClass, valueClass;
private Serializer keySerializer, valueSerializer;
private boolean keysCanBeNull = true, valuesCanBeNull = true;
private Class keyGenericType, valueGenericType;
....
/**
* 设置泛型
* @param kryo
* @param generics Some (but never all) elements may be null if there is no generic type information at that index.
*/
public void setGenerics (Kryo kryo, Class[] generics) {
keyGenericType = null;
valueGenericType = null;
if (generics != null && generics.length > 0) {
if (generics[0] != null && kryo.isFinal(generics[0])) keyGenericType = generics[0];
if (generics.length > 1 && generics[1] != null && kryo.isFinal(generics[1])) valueGenericType = generics[1];
}
}
public void write (Kryo kryo, Output output, Map map) {
int length = map.size();
//写入Map的长度到缓存中
output.writeInt(length, true);
Serializer keySerializer = this.keySerializer;
//泛型
if (keyGenericType != null) {
if (keySerializer == null) keySerializer = kryo.getSerializer(keyGenericType);
keyGenericType = null;
}
Serializer valueSerializer = this.valueSerializer;
if (valueGenericType != null) {
if (valueSerializer == null) valueSerializer = kryo.getSerializer(valueGenericType);
valueGenericType = null;
}
//遍历map
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
Entry entry = (Entry)iter.next();
//写入key的序列化对象值
if (keySerializer != null) {
if (keysCanBeNull)
kryo.writeObjectOrNull(output, entry.getKey(), keySerializer);
else
kryo.writeObject(output, entry.getKey(), keySerializer);
} else
kryo.writeClassAndObject(output, entry.getKey());
//写入value的序列化对象值
if (valueSerializer != null) {
if (valuesCanBeNull)
kryo.writeObjectOrNull(output, entry.getValue(), valueSerializer);
else
kryo.writeObject(output, entry.getValue(), valueSerializer);
} else
kryo.writeClassAndObject(output, entry.getValue());
}
}
/** Used by {@link #read(Kryo, Input, Class)} to create the new object. This can be overridden to customize object creation, eg
* to call a constructor with arguments. The default implementation uses {@link Kryo#newInstance(Class)}. */
protected Map create (Kryo kryo, Input input, Class<Map> type) {
return kryo.newInstance(type);
}
public Map read (Kryo kryo, Input input, Class<Map> type) {
Map map = create(kryo, input, type);
//读取Map的长度
int length = input.readInt(true);
Class keyClass = this.keyClass;
Class valueClass = this.valueClass;
Serializer keySerializer = this.keySerializer;
if (keyGenericType != null) {
keyClass = keyGenericType;
if (keySerializer == null) keySerializer = kryo.getSerializer(keyClass);
keyGenericType = null;
}
Serializer valueSerializer = this.valueSerializer;
if (valueGenericType != null) {
valueClass = valueGenericType;
if (valueSerializer == null) valueSerializer = kryo.getSerializer(valueClass);
valueGenericType = null;
}
kryo.reference(map);
for (int i = 0; i < length; i++) {
Object key;
if (keySerializer != null) {
if (keysCanBeNull)
key = kryo.readObjectOrNull(input, keyClass, keySerializer);
else
key = kryo.readObject(input, keyClass, keySerializer);
} else
key = kryo.readClassAndObject(input);
Object value;
if (valueSerializer != null) {
if (valuesCanBeNull)
value = kryo.readObjectOrNull(input, valueClass, valueSerializer);
else
value = kryo.readObject(input, valueClass, valueSerializer);
} else
value = kryo.readClassAndObject(input);
map.put(key, value);
}
return map;
}
protected Map createCopy (Kryo kryo, Map original) {
return kryo.newInstance(original.getClass());
}
public Map copy (Kryo kryo, Map original) {
Map copy = createCopy(kryo, original);
for (Iterator iter = original.entrySet().iterator(); iter.hasNext();) {
Entry entry = (Entry)iter.next();
copy.put(kryo.copy(entry.getKey()), kryo.copy(entry.getValue()));
}
return copy;
}
/** Used to annotate fields that are maps with specific Kryo serializers for their keys or values. */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindMap {
/** Serializer to be used for keys
*
* @return the class<? extends serializer> used for keys serialization */
@SuppressWarnings("rawtypes")
Class<? extends Serializer> keySerializer() default Serializer.class;
/** Serializer to be used for values
*
* @return the class<? extends serializer> used for values serialization */
@SuppressWarnings("rawtypes")
Class<? extends Serializer> valueSerializer() default Serializer.class;
/** Class used for keys
*
* @return the class used for keys */
Class<?> keyClass() default Object.class;
/** Class used for values
*
* @return the class used for values */
Class<?> valueClass() default Object.class;
/** Indicates if keys can be null
*
* @return true, if keys can be null */
boolean keysCanBeNull() default true;
/** Indicates if values can be null
*
* @return true, if values can be null */
boolean valuesCanBeNull() default true;
}
}
反序列化
Kryo
Kryo#readClassAndObject (Input input)
通过input
(输入流)读取对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32/** Reads the class and object or null using the registered serializer.
* @return May be null. */
public Object readClassAndObject (Input input) {
if (input == null) throw new IllegalArgumentException("input cannot be null.");
beginObject();
try {
//先读取class的注册对象
Registration registration = readClass(input);
if (registration == null) return null;
Class type = registration.getType();
Object object;
//有引用
if (references) {
//设置泛型
registration.getSerializer().setGenerics(this, null);
//返回对象id
int stackSize = readReferenceOrNull(input, type, false);
//基本类型和第1次读取对象,返回readReferenceIds.size()
if (stackSize == REF) return readObject;
//直接Serializer实现类中获取readObject
object = registration.getSerializer().read(this, input, type);
//id=id数组的长度,存储到缓存中
if (stackSize == readReferenceIds.size) reference(object);
} else//从实现的Serializer中读取对象
object = registration.getSerializer().read(this, input, type);
if (TRACE || (DEBUG && depth == 1)) log("Read", object);
return object;
} finally {
if (--depth == 0 && autoReset) reset();
}
}
readClass
,根据nameId
获取class。- 有引用,返回对象
id
。如果id
是REF
值。返回object
,object
值是not null
和null
。 - 无引用,从
Serializer
实现类中执行read()
。Kryo#readClass (Input input)
这里是由DefaultClassResolver
实现的readClass()
1
2
3
4
5
6
7
8
9
10
11/** Reads a class and returns its registration.
* @return May be null.
* @see ClassResolver#readClass(Input) */
public Registration readClass (Input input) {
if (input == null) throw new IllegalArgumentException("input cannot be null.");
try {
return classResolver.readClass(input);
} finally {
if (depth == 0 && autoReset) reset();
}
}
Kryo#readReferenceOrNull (Input input, Class type, boolean mayBeNull)
读取对象。根据基本类型与Ref
的null
和not null
获取object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54/** Returns {@link #REF} if a reference to a previously read object was read, which is stored in {@link #readObject}. Returns a
* stack size (> 0) if a reference ID has been put on the stack. */
//读取readobject或者是null
int readReferenceOrNull (Input input, Class type, boolean mayBeNull) {
//基本数据类型
if (type.isPrimitive()) type = getWrapperClass(type);
//是否支持引用类型
boolean referencesSupported = referenceResolver.useReferences(type);
int id;
//允许null
if (mayBeNull) {
//获取当前对象的id
id = input.readVarInt(true);
//当前id对应的对象值是null
if (id == Kryo.NULL) {
if (TRACE || (DEBUG && depth == 1)) log("Read", null);
readObject = null;
//返回对象引用
return REF;
}
//对象!=null,基本数据类型,添加到id数组中
if (!referencesSupported) {
readReferenceIds.add(NO_REF);
return readReferenceIds.size;
}
} else {//not null
//基本类型
if (!referencesSupported) {
//添加基本类型的id
readReferenceIds.add(NO_REF);
return readReferenceIds.size;
}
//引用读取byte[]缓存,返回id值
id = input.readVarInt(true);
}
//id对应的引用对象!=null,第1次读取,存入read的id数组
if (id == NOT_NULL) {
// First time object has been encountered.
//id递增
//这里的id是read的reference数组的id
id = referenceResolver.nextReadId(type);
if (TRACE) trace("kryo", "Read initial object reference " + id + ": " + className(type));
//添加到read的reference数组中
readReferenceIds.add(id);
//id值就是readReferenceIds.size
return readReferenceIds.size;
}
// The id is an object reference.id == NULL
id -= 2; // - 2 because 0 and 1 are used for NULL and NOT_NULL.
//默认从MapReferenceResolver中获取object
readObject = referenceResolver.getReadObject(type, id);
if (DEBUG) debug("kryo", "Read object reference " + id + ": " + string(readObject));
return REF;
}
mayBeNull == true
,如果object
是null
,则直接返回REF
;如果是基本类型对象,readReferenceIds
添加Not_Ref
,返回readReferenceIds.size()
。mayBeNull == false
,获取id
,id == NOT_NULL
,说明是第1次读取,readReferenceIds
添加id
。返回id
,这id=readReferenceIds.size()
。mayBeNull == false
,id is Null
,存在MapReferenceResolver
中,直接获取Object
,返回Ref
。基本类型和第1次读取对象,返回
readReferenceIds.size()
。Kryo#reference (Object object)
重置缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/** Called by {@link Serializer#read(Kryo, Input, Class)} and {@link Serializer#copy(Kryo, Object)} before Kryo can be used to
* deserialize or copy child objects. Calling this method is unnecessary if Kryo is not used to deserialize or copy child
* objects.
* @param object May be null, unless calling this method from {@link Serializer#copy(Kryo, Object)}. */
//重置引用对象
public void reference (Object object) {
//复制深度
if (copyDepth > 0) {
//需要复制的引用
if (needsCopyReference != null) {
if (object == null) throw new IllegalArgumentException("object cannot be null.");
//原数据 TO 复制
originalToCopy.put(needsCopyReference, object);
needsCopyReference = null;
}
} else if (references && object != null) {
//获取对象对应的id
int id = readReferenceIds.pop();
//id==Ref,把id重新存储到MapReferenceResolver中
if (id != NO_REF) referenceResolver.setReadObject(id, object);
}
}第1次读取时,
MapReferenceResolver
存入object
对象。originalToCopy
存入Object
。Kryo#copy(T object)
深度复制对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/** Returns a deep copy of the object. Serializers for the classes involved must support {@link Serializer#copy(Kryo, Object)}.
* @param object May be null. */
//深度复制
public <T> T copy (T object) {
if (object == null) return null;
//浅度复制对象
if (copyShallow) return object;
//深度复制对象序号
copyDepth++;
try {
if (originalToCopy == null) originalToCopy = new IdentityMap();
//获取深度复制对象
Object existingCopy = originalToCopy.get(object);
if (existingCopy != null) return (T)existingCopy;
//existingcopy==null
if (copyReferences) needsCopyReference = object;
Object copy;
if (object instanceof KryoCopyable)
copy = ((KryoCopyable)object).copy(this);
else
//默认是直接返回Object
copy = getSerializer(object.getClass()).copy(this, object);
if (needsCopyReference != null) reference(copy);
if (TRACE || (DEBUG && copyDepth == 1)) log("Copy", copy);
return (T)copy;
} finally {
if (--copyDepth == 0) reset();
}
}
Kryo#copyShallow (T object)
浅度复制1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27/** Returns a shallow copy of the object. Serializers for the classes involved must support
* {@link Serializer#copy(Kryo, Object)}.
* @param object May be null. */
//浅度复制
public <T> T copyShallow (T object) {
if (object == null) return null;
copyDepth++;
copyShallow = true;
try {
if (originalToCopy == null) originalToCopy = new IdentityMap();
Object existingCopy = originalToCopy.get(object);
if (existingCopy != null) return (T)existingCopy;
if (copyReferences) needsCopyReference = object;
Object copy;
if (object instanceof KryoCopyable)
copy = ((KryoCopyable)object).copy(this);
else
copy = getSerializer(object.getClass()).copy(this, object);
if (needsCopyReference != null) reference(copy);
if (TRACE || (DEBUG && copyDepth == 1)) log("Shallow copy", copy);
return (T)copy;
} finally {
copyShallow = false;
if (--copyDepth == 0) reset();
}
}