File kryo-4.0.2-unsafe.patch of Package kryo.28016

--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/factories/PseudoSerializerFactory.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/factories/PseudoSerializerFactory.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,43 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.factories;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-
-/** A serializer factory that always returns a given serializer instance. This implementation of {@link SerializerFactory} is not
- * a real factory since it only provides a given instance instead of dynamically creating new serializers. It can be used when all
- * types should be serialized by the same serializer. This also allows serializers to be shared among different {@link Kryo}
- * instances.
- *
- * @author Rafael Winterhalter <rafael.wth@web.de> */
-public class PseudoSerializerFactory implements SerializerFactory {
-
-	private final Serializer<?> serializer;
-
-	public PseudoSerializerFactory (Serializer<?> serializer) {
-		this.serializer = serializer;
-	}
-
-	@Override
-	public Serializer makeSerializer (Kryo kryo, Class<?> type) {
-		return serializer;
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/factories/ReflectionSerializerFactory.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/factories/ReflectionSerializerFactory.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,69 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.factories;
-
-import static com.esotericsoftware.kryo.util.Util.*;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-
-/** This factory instantiates new serializers of a given class via reflection. The constructors of the given
- * {@code serializerClass} must either take an instance of {@link Kryo} and an instance of {@link Class} as its parameter, take
- * only a {@link Kryo} or {@link Class} as its only argument or take no arguments. If several of the described constructors are
- * found, the first found constructor is used, in the order as they were just described.
- *
- * @author Rafael Winterhalter <rafael.wth@web.de> */
-public class ReflectionSerializerFactory implements SerializerFactory {
-
-	private final Class<? extends Serializer> serializerClass;
-
-	public ReflectionSerializerFactory (Class<? extends Serializer> serializerClass) {
-		this.serializerClass = serializerClass;
-	}
-
-	@Override
-	public Serializer makeSerializer (Kryo kryo, Class<?> type) {
-		return makeSerializer(kryo, serializerClass, type);
-	}
-
-	/** Creates a new instance of the specified serializer for serializing the specified class. Serializers must have a zero
-	 * argument constructor or one that takes (Kryo), (Class), or (Kryo, Class). */
-	public static Serializer makeSerializer (Kryo kryo, Class<? extends Serializer> serializerClass, Class<?> type) {
-		try {
-			try {
-				return serializerClass.getConstructor(Kryo.class, Class.class).newInstance(kryo, type);
-			} catch (NoSuchMethodException ex1) {
-				try {
-					return serializerClass.getConstructor(Kryo.class).newInstance(kryo);
-				} catch (NoSuchMethodException ex2) {
-					try {
-						return serializerClass.getConstructor(Class.class).newInstance(type);
-					} catch (NoSuchMethodException ex3) {
-						return serializerClass.newInstance();
-					}
-				}
-			}
-		} catch (Exception ex) {
-			throw new IllegalArgumentException(
-				"Unable to create serializer \"" + serializerClass.getName() + "\" for class: " + className(type), ex);
-		}
-
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/factories/SerializerFactory.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/factories/SerializerFactory.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,37 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.factories;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-
-/** A serializer factory that allows the creation of serializers. This factory will be called when a {@link Kryo} serializer
- * discovers a new type for which no serializer is yet known. For example, when a factory is registered via
- * {@link Kryo#setDefaultSerializer(SerializerFactory)} a different serializer can be created dependent on the type of a class.
- *
- * @author Rafael Winterhalter <rafael.wth@web.de> */
-public interface SerializerFactory {
-
-	/** Creates a new serializer
-	 * @param kryo The serializer instance requesting the new serializer.
-	 * @param type The type of the object that is to be serialized.
-	 * @return An implementation of a serializer that is able to serialize an object of type {@code type}. */
-	Serializer makeSerializer (Kryo kryo, Class<?> type);
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/ByteBufferInput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/ByteBufferInput.java	2018-12-20 09:20:46.838804225 +0100
@@ -31,7 +31,7 @@
 import java.nio.ShortBuffer;
 
 import com.esotericsoftware.kryo.KryoException;
-import com.esotericsoftware.kryo.util.UnsafeUtil;
+import com.esotericsoftware.kryo.util.Util;
 
 /** An InputStream that reads data from a byte array and optionally fills the byte array from another InputStream as needed.
  * Utility methods are provided for efficiently reading primitive types and strings.
@@ -114,37 +114,6 @@
 		inputStream = null;
 	}
 
-	/** Releases a direct buffer. {@link #setBuffer(ByteBuffer)} must be called before any write operations can be performed. */
-	public void release () {
-		close();
-		UnsafeUtil.releaseBuffer(niobuffer);
-		niobuffer = null;
-	}
-
-	/** This constructor allows for creation of a direct ByteBuffer of a given size at a given address.
-	 * 
-	 * <p>
-	 * Typical usage could look like this snippet:
-	 * 
-	 * <pre>
-	 * // Explicitly allocate memory
-	 * long bufAddress = UnsafeUtil.unsafe().allocateMemory(4096);
-	 * // Create a ByteBufferInput using the allocated memory region
-	 * ByteBufferInput buffer = new ByteBufferInput(bufAddress, 4096);
-	 * 
-	 * // Do some operations on this buffer here
-	 * 
-	 * // Say that ByteBuffer won't be used anymore
-	 * buffer.release();
-	 * // Release the allocated region
-	 * UnsafeUtil.unsafe().freeMemory(bufAddress);
-	 * </pre>
-	 * 
-	 * @param address starting address of a memory region pre-allocated using Unsafe.allocateMemory() */
-	public ByteBufferInput (long address, int size) {
-		setBuffer(UnsafeUtil.getDirectBufferAt(address, size));
-	}
-
 	public ByteBuffer getByteBuffer () {
 		return niobuffer;
 	}
@@ -316,7 +285,7 @@
 	public long skip (long count) throws KryoException {
 		long remaining = count;
 		while (remaining > 0) {
-			int skip = (int)Math.min(Util.MAX_SAFE_ARRAY_SIZE, remaining);
+			int skip = (int)Math.min(Util.maxArraySize, remaining);
 			skip(skip);
 			remaining -= skip;
 		}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/ByteBufferOutput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/ByteBufferOutput.java	2018-12-20 09:20:46.838804225 +0100
@@ -31,7 +31,7 @@
 import java.nio.ShortBuffer;
 
 import com.esotericsoftware.kryo.KryoException;
-import com.esotericsoftware.kryo.util.UnsafeUtil;
+import com.esotericsoftware.kryo.util.Util;
 
 /** An OutputStream that buffers data in a byte array and optionally flushes to another OutputStream. Utility methods are provided
  * for efficiently writing primitive types and strings.
@@ -64,7 +64,7 @@
 	public ByteBufferOutput (int bufferSize, int maxBufferSize) {
 		if (maxBufferSize < -1) throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize);
 		this.capacity = bufferSize;
-		this.maxCapacity = maxBufferSize == -1 ? Util.MAX_SAFE_ARRAY_SIZE : maxBufferSize;
+		this.maxCapacity = maxBufferSize == -1 ? Util.maxArraySize : maxBufferSize;
 		niobuffer = ByteBuffer.allocateDirect(bufferSize);
 		niobuffer.order(byteOrder);
 	}
@@ -94,41 +94,6 @@
 		setBuffer(buffer, maxBufferSize);
 	}
 
-	/** Creates a direct ByteBuffer of a given size at a given address.
-	 * <p>
-	 * Typical usage could look like this snippet:
-	 * 
-	 * <pre>
-	 * // Explicitly allocate memory
-	 * long bufAddress = UnsafeUtil.unsafe().allocateMemory(4096);
-	 * // Create a ByteBufferOutput using the allocated memory region
-	 * ByteBufferOutput buffer = new ByteBufferOutput(bufAddress, 4096);
-	 * 
-	 * // Do some operations on this buffer here
-	 * 
-	 * // Say that ByteBuffer won't be used anymore
-	 * buffer.release();
-	 * // Release the allocated region
-	 * UnsafeUtil.unsafe().freeMemory(bufAddress);
-	 * </pre>
-	 * 
-	 * @param address starting address of a memory region pre-allocated using Unsafe.allocateMemory()
-	 * @param maxBufferSize */
-	public ByteBufferOutput (long address, int maxBufferSize) {
-		niobuffer = UnsafeUtil.getDirectBufferAt(address, maxBufferSize);
-		setBuffer(niobuffer, maxBufferSize);
-	}
-
-	/** Release a direct buffer. {@link #setBuffer(ByteBuffer, int)} should be called before next write operations can be called.
-	 * 
-	 * NOTE: If Cleaner is not accessible due to SecurityManager restrictions, reflection could be used to obtain the "clean"
-	 * method and then invoke it. */
-	public void release () {
-		clear();
-		UnsafeUtil.releaseBuffer(niobuffer);
-		niobuffer = null;
-	}
-
 	public ByteOrder order () {
 		return byteOrder;
 	}
@@ -163,7 +128,7 @@
 		if (buffer == null) throw new IllegalArgumentException("buffer cannot be null.");
 		if (maxBufferSize < -1) throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize);
 		this.niobuffer = buffer;
-		this.maxCapacity = maxBufferSize == -1 ? Util.MAX_SAFE_ARRAY_SIZE : maxBufferSize;
+		this.maxCapacity = maxBufferSize == -1 ? Util.maxArraySize : maxBufferSize;
 		byteOrder = buffer.order();
 		capacity = buffer.capacity();
 		position = buffer.position();
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/FastInput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/FastInput.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,69 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.io;
-
-import java.io.InputStream;
-
-import com.esotericsoftware.kryo.KryoException;
-
-/** Same as Input, but does not use variable length encoding for integer types.
- * @author Roman Levenstein <romxilev@gmail.com> */
-public final class FastInput extends Input {
-
-	/** Creates an uninitialized Output. {@link #setBuffer(byte[], int, int)} must be called before the Output is used. */
-	public FastInput () {
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * @param bufferSize The initial and maximum size of the buffer. An exception is thrown if this size is exceeded. */
-	public FastInput (int bufferSize) {
-		super(bufferSize);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * @see #setBuffer(byte[]) */
-	public FastInput (byte[] buffer) {
-		super(buffer);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * @see #setBuffer(byte[], int, int) */
-	public FastInput (byte[] buffer, int offset, int count) {
-		super(buffer, offset, count);
-	}
-
-	/** Creates a new Output for writing to an OutputStream. A buffer size of 4096 is used. */
-	public FastInput (InputStream outputStream) {
-		super(outputStream);
-	}
-
-	/** Creates a new Output for writing to an OutputStream. */
-	public FastInput (InputStream outputStream, int bufferSize) {
-		super(outputStream, bufferSize);
-	}
-
-	public int readInt (boolean optimizePositive) throws KryoException {
-		return readInt();
-	}
-
-	public long readLong (boolean optimizePositive) throws KryoException {
-		return readLong();
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/FastOutput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/FastOutput.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,83 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.io;
-
-import java.io.OutputStream;
-
-import com.esotericsoftware.kryo.KryoException;
-
-/** Same as Output, but does not use variable length encoding for integer types.
- * @author Roman Levenstein <romxilev@gmail.com> */
-public final class FastOutput extends Output {
-
-	/** Creates an uninitialized Output. {@link #setBuffer(byte[], int)} must be called before the Output is used. */
-	public FastOutput () {
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @param bufferSize The initial and maximum size of the buffer. An exception is thrown if this size is exceeded. */
-	public FastOutput (int bufferSize) {
-		this(bufferSize, bufferSize);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @param bufferSize The initial size of the buffer.
-	 * @param maxBufferSize The buffer is doubled as needed until it exceeds maxBufferSize and an exception is thrown. */
-	public FastOutput (int bufferSize, int maxBufferSize) {
-		super(bufferSize, maxBufferSize);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @see #setBuffer(byte[]) */
-	public FastOutput (byte[] buffer) {
-		this(buffer, buffer.length);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @see #setBuffer(byte[], int) */
-	public FastOutput (byte[] buffer, int maxBufferSize) {
-		super(buffer, maxBufferSize);
-	}
-
-	/** Creates a new Output for writing to an OutputStream. A buffer size of 4096 is used. */
-	public FastOutput (OutputStream outputStream) {
-		super(outputStream);
-	}
-
-	/** Creates a new Output for writing to an OutputStream. */
-	public FastOutput (OutputStream outputStream, int bufferSize) {
-		super(outputStream, bufferSize);
-	}
-
-	public int writeInt (int value, boolean optimizePositive) throws KryoException {
-		writeInt(value);
-		return 4;
-	}
-
-	public int writeLong (long value, boolean optimizePositive) throws KryoException {
-		writeLong(value);
-		return 8;
-	}
-
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/Input.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/Input.java	2018-12-20 09:20:46.838804225 +0100
@@ -23,6 +23,7 @@
 import java.io.InputStream;
 
 import com.esotericsoftware.kryo.KryoException;
+import com.esotericsoftware.kryo.util.Util;
 
 /** An InputStream that reads data from a byte array and optionally fills the byte array from another InputStream as needed.
  * Utility methods are provided for efficiently reading primitive types and strings.
@@ -289,7 +290,7 @@
 	public long skip (long count) throws KryoException {
 		long remaining = count;
 		while (remaining > 0) {
-			int skip = (int)Math.min(Util.MAX_SAFE_ARRAY_SIZE, remaining);
+			int skip = (int)Math.min(Util.maxArraySize, remaining);
 			skip(skip);
 			remaining -= skip;
 		}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/KryoDataInput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/KryoDataInput.java	2018-12-20 09:20:46.838804225 +0100
@@ -97,9 +97,7 @@
 		return input.readDouble();
 	}
 
-	/** This is not currently implemented. The method will currently throw an {@link java.lang.UnsupportedOperationException}
-	 * whenever it is called.
-	 *
+	/** Not implemented.
 	 * @throws UnsupportedOperationException when called.
 	 * @deprecated this method is not supported in this implementation. */
 	public String readLine () throws UnsupportedOperationException {
@@ -110,7 +108,6 @@
 	 * {@link KryoDataOutput#writeUTF(String)}, {@link com.esotericsoftware.kryo.io.Output#writeString(String)},
 	 * {@link com.esotericsoftware.kryo.io.Output#writeString(CharSequence)}, and
 	 * {@link com.esotericsoftware.kryo.io.Output#writeAscii(String)}.
-	 *
 	 * @return May be null. */
 	public String readUTF () throws IOException {
 		return input.readString();
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/Output.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/Output.java	2018-12-20 09:20:46.838804225 +0100
@@ -23,6 +23,7 @@
 import java.io.OutputStream;
 
 import com.esotericsoftware.kryo.KryoException;
+import com.esotericsoftware.kryo.util.Util;
 
 /** An OutputStream that buffers data in a byte array and optionally flushes to another OutputStream. Utility methods are provided
  * for efficiently writing primitive types and strings.
@@ -58,7 +59,7 @@
 			"bufferSize: " + bufferSize + " cannot be greater than maxBufferSize: " + maxBufferSize);
 		if (maxBufferSize < -1) throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize);
 		this.capacity = bufferSize;
-		this.maxCapacity = maxBufferSize == -1 ? Util.MAX_SAFE_ARRAY_SIZE : maxBufferSize;
+		this.maxCapacity = maxBufferSize == -1 ? Util.maxArraySize : maxBufferSize;
 		buffer = new byte[bufferSize];
 	}
 
@@ -116,7 +117,7 @@
 			"buffer has length: " + buffer.length + " cannot be greater than maxBufferSize: " + maxBufferSize);
 		if (maxBufferSize < -1) throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize);
 		this.buffer = buffer;
-		this.maxCapacity = maxBufferSize == -1 ? Util.MAX_SAFE_ARRAY_SIZE : maxBufferSize;
+		this.maxCapacity = maxBufferSize == -1 ? Util.maxArraySize : maxBufferSize;
 		capacity = buffer.length;
 		position = 0;
 		total = 0;
@@ -482,8 +483,7 @@
 	}
 
 	private void writeAscii_slow (String value, int charCount) throws KryoException {
-		if (charCount == 0)
-			return;
+		if (charCount == 0) return;
 		// It should be possible to write at least one character.
 		if (capacity == 0) {
 			require(1);
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/UnsafeInput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/UnsafeInput.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,258 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.io;
-
-import static com.esotericsoftware.kryo.util.UnsafeUtil.*;
-
-import java.io.InputStream;
-
-import com.esotericsoftware.kryo.KryoException;
-
-/** An optimized InputStream that reads data from a byte array and optionally fills the byte array from another InputStream as
- * needed. Utility methods are provided for efficiently writing primitive types, arrays of primitive types and strings. It uses
- * @link{sun.misc.Unsafe} to achieve a very good performance.
- * 
- *                        <p>
- *                        Important notes:<br/>
- *                        <li>Bulk operations, e.g. on arrays of primitive types, are always using native byte order.</li>
- *                        <li>Fixed-size char, int, long, short, float and double elements are always read using native byte
- *                        order.</li>
- *                        <li>Best performance is achieved if no variable length encoding for integers is used.</li>
- *                        <li>Serialized representation used as input for this class should always be produced
- *                        using @link{UnsafeOutput}</li>
- *                        </p>
- * @author Roman Levenstein <romixlev@gmail.com> */
-public final class UnsafeInput extends Input {
-
-	private boolean varIntsEnabled = false;
-
-	/** Creates an uninitialized Input. {@link #setBuffer(byte[], int, int)} must be called before the Input is used. */
-	public UnsafeInput () {
-	}
-
-	/** Creates a new Input for reading from a byte array.
-	 * @param bufferSize The initial and maximum size of the buffer. An exception is thrown if this size is exceeded. */
-	public UnsafeInput (int bufferSize) {
-		super(bufferSize);
-	}
-
-	/** Creates a new Input for reading from a byte array.
-	 * @see #setBuffer(byte[]) */
-	public UnsafeInput (byte[] buffer) {
-		super(buffer);
-	}
-
-	/** Creates a new Input for reading from a byte array.
-	 * @see #setBuffer(byte[], int, int) */
-	public UnsafeInput (byte[] buffer, int offset, int count) {
-		super(buffer, offset, count);
-	}
-
-	/** Creates a new Input for reading from an InputStream. A buffer size of 4096 is used. */
-	public UnsafeInput (InputStream inputStream) {
-		super(inputStream);
-	}
-
-	/** Creates a new Input for reading from an InputStream. */
-	public UnsafeInput (InputStream inputStream, int bufferSize) {
-		super(inputStream, bufferSize);
-	}
-
-	// int
-
-	/** Reads a 4 byte int. */
-	public int readInt () throws KryoException {
-		require(4);
-		int result = unsafe().getInt(buffer, byteArrayBaseOffset + position);
-		position += 4;
-		return result;
-	}
-
-	// float
-
-	/** Reads a 4 byte float. */
-	public float readFloat () throws KryoException {
-		require(4);
-		float result = unsafe().getFloat(buffer, byteArrayBaseOffset + position);
-		position += 4;
-		return result;
-	}
-
-	// short
-
-	/** Reads a 2 byte short. */
-	public short readShort () throws KryoException {
-		require(2);
-		short result = unsafe().getShort(buffer, byteArrayBaseOffset + position);
-		position += 2;
-		return result;
-	}
-
-	// long
-
-	/** Reads an 8 byte long. */
-	public long readLong () throws KryoException {
-		require(8);
-		long result = unsafe().getLong(buffer, byteArrayBaseOffset + position);
-		position += 8;
-		return result;
-	}
-
-	// double
-
-	/** Writes an 8 byte double. */
-	public double readDouble () throws KryoException {
-		require(8);
-		double result = unsafe().getDouble(buffer, byteArrayBaseOffset + position);
-		position += 8;
-		return result;
-	}
-
-	// char
-
-	public char readChar () throws KryoException {
-		require(2);
-		char result = unsafe().getChar(buffer, byteArrayBaseOffset + position);
-		position += 2;
-		return result;
-	}
-
-	public int readInt (boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled)
-			return readInt();
-		else
-			return super.readInt(optimizePositive);
-	}
-
-	public long readLong (boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled)
-			return readLong();
-		else
-			return super.readLong(optimizePositive);
-	}
-
-	// Methods implementing bulk operations on arrays of primitive types
-
-	/** {@inheritDoc} */
-	final public int[] readInts (int length, boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled) {
-			int bytesToCopy = length << 2;
-			int[] array = new int[length];
-			readBytes(array, intArrayBaseOffset, 0, bytesToCopy);
-			return array;
-		} else
-			return super.readInts(length, optimizePositive);
-	}
-
-	/** {@inheritDoc} */
-	final public long[] readLongs (int length, boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled) {
-			int bytesToCopy = length << 3;
-			long[] array = new long[length];
-			readBytes(array, longArrayBaseOffset, 0, bytesToCopy);
-			return array;
-		} else
-			return super.readLongs(length, optimizePositive);
-	}
-
-	/** {@inheritDoc} */
-	final public int[] readInts (int length) throws KryoException {
-		int bytesToCopy = length << 2;
-		int[] array = new int[length];
-		readBytes(array, intArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** {@inheritDoc} */
-	final public long[] readLongs (int length) throws KryoException {
-		int bytesToCopy = length << 3;
-		long[] array = new long[length];
-		readBytes(array, longArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** {@inheritDoc} */
-	final public float[] readFloats (int length) throws KryoException {
-		int bytesToCopy = length << 2;
-		float[] array = new float[length];
-		readBytes(array, floatArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** {@inheritDoc} */
-	final public short[] readShorts (int length) throws KryoException {
-		int bytesToCopy = length << 1;
-		short[] array = new short[length];
-		readBytes(array, shortArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** {@inheritDoc} */
-	final public char[] readChars (int length) throws KryoException {
-		int bytesToCopy = length << 1;
-		char[] array = new char[length];
-		readBytes(array, charArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** {@inheritDoc} */
-	final public double[] readDoubles (int length) throws KryoException {
-		int bytesToCopy = length << 3;
-		double[] array = new double[length];
-		readBytes(array, doubleArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	final public void readBytes (Object dstObj, long offset, long count) throws KryoException {
-		// Unsafe supports efficient bulk reading into arrays of primitives only because
-		// of JVM limitations due to GC
-		if (dstObj.getClass().isArray())
-			readBytes(dstObj, 0, offset, (int)count);
-		else {
-			throw new KryoException("Only bulk reads of arrays is supported");
-		}
-	}
-
-	final private void readBytes (Object dstArray, long dstArrayTypeOffset, long offset, int count) throws KryoException {
-		int copyCount = Math.min(limit - position, count);
-		while (true) {
-			unsafe().copyMemory(buffer, byteArrayBaseOffset + position, dstArray, dstArrayTypeOffset + offset, copyCount);
-			position += copyCount;
-			count -= copyCount;
-			if (count == 0) break;
-			offset += copyCount;
-			copyCount = Math.min(count, capacity);
-			require(copyCount);
-		}
-	}
-
-	/*** Return current setting for variable length encoding of integers
-	 * @return current setting for variable length encoding of integers */
-	public boolean getVarIntsEnabled () {
-		return varIntsEnabled;
-	}
-
-	/*** Controls if a variable length encoding for integer types should be used when serializers suggest it.
-	 * 
-	 * @param varIntsEnabled */
-	public void setVarIntsEnabled (boolean varIntsEnabled) {
-		this.varIntsEnabled = varIntsEnabled;
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/UnsafeMemoryInput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/UnsafeMemoryInput.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,260 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.io;
-
-import static com.esotericsoftware.kryo.util.UnsafeUtil.*;
-
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-import com.esotericsoftware.kryo.KryoException;
-
-import sun.nio.ch.DirectBuffer;
-
-/** An optimized InputStream that reads data directly from the off-heap memory. Utility methods are provided for efficiently
- * reading primitive types, arrays of primitive types and strings. It uses @link{sun.misc.Unsafe} to achieve a very good
- * performance.
- * 
- * <p>
- * Important notes:<br/>
- * <li>Bulk operations, e.g. on arrays of primitive types, are always using native byte order.</li>
- * <li>Fixed-size char, int, long, short, float and double elements are always read using native byte order.</li>
- * <li>Best performance is achieved if no variable length encoding for integers is used.</li>
- * <li>Serialized representation used as input for this class should always be produced using @link{UnsafeMemoryOutput}</li>
- * </p>
- * @author Roman Levenstein <romixlev@gmail.com> */
-public final class UnsafeMemoryInput extends ByteBufferInput {
-	/** Start address of the memory buffer The memory buffer should be non-movable, which normally means that is is allocated
-	 * off-heap */
-	private long bufaddress;
-
-	{
-		varIntsEnabled = false;
-
-	}
-
-	/** Creates an uninitialized Input. {@link #setBuffer(byte[], int, int)} must be called before the Input is used. */
-	public UnsafeMemoryInput () {
-	}
-
-	/** Creates a new Input for reading from a byte array.
-	 * @param bufferSize The initial and maximum size of the buffer. An exception is thrown if this size is exceeded. */
-	public UnsafeMemoryInput (int bufferSize) {
-		super(bufferSize);
-		updateBufferAddress();
-	}
-
-	/** Creates a new Input for reading from a byte array.
-	 * @see #setBuffer(byte[]) */
-	public UnsafeMemoryInput (byte[] buffer) {
-		super(buffer);
-		updateBufferAddress();
-	}
-
-	public UnsafeMemoryInput (ByteBuffer buffer) {
-		super(buffer);
-		updateBufferAddress();
-	}
-
-	public UnsafeMemoryInput (long address, int maxBufferSize) {
-		super(address, maxBufferSize);
-		updateBufferAddress();
-	}
-
-	/** Creates a new Input for reading from an InputStream. A buffer size of 4096 is used. */
-	public UnsafeMemoryInput (InputStream inputStream) {
-		super(inputStream);
-		updateBufferAddress();
-	}
-
-	/** Creates a new Input for reading from an InputStream. */
-	public UnsafeMemoryInput (InputStream inputStream, int bufferSize) {
-		super(inputStream, bufferSize);
-		updateBufferAddress();
-	}
-
-	public void setBuffer (ByteBuffer buffer) {
-		super.setBuffer(buffer);
-		updateBufferAddress();
-	}
-
-	private void updateBufferAddress () {
-		bufaddress = ((DirectBuffer)super.niobuffer).address();
-	}
-
-	/** Reads a 4 byte int. */
-	public int readInt () throws KryoException {
-		require(4);
-		int result = unsafe().getInt(bufaddress + position);
-		position += 4;
-		return result;
-	}
-
-	/** Reads a 4 byte float. */
-	public float readFloat () throws KryoException {
-		require(4);
-		float result = unsafe().getFloat(bufaddress + position);
-		position += 4;
-		return result;
-	}
-
-	/** Reads a 2 byte short. */
-	public short readShort () throws KryoException {
-		require(2);
-		short result = unsafe().getShort(bufaddress + position);
-		position += 2;
-		return result;
-	}
-
-	/** Reads an 8 byte long. */
-	public long readLong () throws KryoException {
-		require(8);
-		long result = unsafe().getLong(bufaddress + position);
-		position += 8;
-		return result;
-	}
-
-	/** Reads a 1 byte boolean. */
-	public boolean readBoolean () throws KryoException {
-		super.niobuffer.position(position);
-		return super.readBoolean();
-	}
-
-	/** Reads a single byte. */
-	public byte readByte () throws KryoException {
-		super.niobuffer.position(position);
-		return super.readByte();
-	}
-
-	/** Reads a 2 byte char. */
-	public char readChar () throws KryoException {
-		require(2);
-		char result = unsafe().getChar(bufaddress + position);
-		position += 2;
-		return result;
-	}
-
-	/** Reads an 8 byte double. */
-	public double readDouble () throws KryoException {
-		require(8);
-		double result = unsafe().getDouble(bufaddress + position);
-		position += 8;
-		return result;
-	}
-
-	public int readInt (boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled)
-			return readInt();
-		else
-			return super.readInt(optimizePositive);
-	}
-
-	public long readLong (boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled)
-			return readLong();
-		else
-			return super.readLong(optimizePositive);
-	}
-
-	// Methods implementing bulk operations on arrays of primitive types
-
-	/** {@inheritDoc} */
-	final public int[] readInts (int length, boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled) {
-			int bytesToCopy = length << 2;
-			int[] array = new int[length];
-			readBytes(array, intArrayBaseOffset, 0, bytesToCopy);
-			return array;
-		} else
-			return super.readInts(length, optimizePositive);
-	}
-
-	/** {@inheritDoc} */
-	final public long[] readLongs (int length, boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled) {
-			int bytesToCopy = length << 3;
-			long[] array = new long[length];
-			readBytes(array, longArrayBaseOffset, 0, bytesToCopy);
-			return array;
-		} else
-			return super.readLongs(length, optimizePositive);
-	}
-
-	/** {@inheritDoc} */
-	final public float[] readFloats (int length) throws KryoException {
-		int bytesToCopy = length << 2;
-		float[] array = new float[length];
-		readBytes(array, floatArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** {@inheritDoc} */
-	final public short[] readShorts (int length) throws KryoException {
-		int bytesToCopy = length << 1;
-		short[] array = new short[length];
-		readBytes(array, shortArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** {@inheritDoc} */
-	final public char[] readChars (int length) throws KryoException {
-		int bytesToCopy = length << 1;
-		char[] array = new char[length];
-		readBytes(array, charArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** {@inheritDoc} */
-	final public double[] readDoubles (int length) throws KryoException {
-		int bytesToCopy = length << 3;
-		double[] array = new double[length];
-		readBytes(array, doubleArrayBaseOffset, 0, bytesToCopy);
-		return array;
-	}
-
-	/** Reads the specified number of bytes into a new byte[]. */
-	public byte[] readBytes (int length) throws KryoException {
-		byte[] bytes = new byte[length];
-		readBytes(bytes, 0, (long)bytes.length);
-		return bytes;
-	}
-
-	final public void readBytes (Object dstObj, long offset, long count) throws KryoException {
-		/* Unsafe supports efficient bulk reading into arrays of primitives only because of JVM limitations due to GC */
-		if (dstObj.getClass().isArray())
-			readBytes(dstObj, byteArrayBaseOffset, offset, (int)count);
-		else {
-			throw new KryoException("Only bulk reads of arrays is supported");
-		}
-	}
-
-	final private void readBytes (Object dstObj, long dstArrayTypeOffset, long offset, int count) throws KryoException {
-		int copyCount = Math.min(limit - position, count);
-		while (true) {
-			unsafe().copyMemory(null, bufaddress + position, dstObj, dstArrayTypeOffset + offset, copyCount);
-			position += copyCount;
-			count -= copyCount;
-			if (count == 0) break;
-			offset += copyCount;
-			copyCount = Math.min(count, capacity);
-			require(copyCount);
-		}
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/UnsafeMemoryOutput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/UnsafeMemoryOutput.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,422 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.io;
-
-import static com.esotericsoftware.kryo.util.UnsafeUtil.*;
-
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-import com.esotericsoftware.kryo.KryoException;
-import com.esotericsoftware.kryo.util.Util;
-
-import sun.nio.ch.DirectBuffer;
-
-/** An optimized OutputStream that writes data directly into the off-heap memory. Utility methods are provided for efficiently
- * writing primitive types, arrays of primitive types and strings. It uses @link{sun.misc.Unsafe} to achieve a very good
- * performance.
- * 
- * <p>
- * Important notes:<br/>
- * <li>This class increases performance, but may result in bigger size of serialized representation.</li>
- * <li>Bulk operations, e.g. on arrays of primitive types, are always using native byte order.</li>
- * <li>Fixed-size char, int, long, short, float and double elements are always written using native byte order.</li>
- * <li>Best performance is achieved if no variable length encoding for integers is used.</li>
- * <li>Output serialized using this class should always be deserilized using @link{UnsafeMemoryInput}</li>
- * 
- * </p>
- * @author Roman Levenstein <romixlev@gmail.com> */
-public final class UnsafeMemoryOutput extends ByteBufferOutput {
-
-	/** Start address of the memory buffer The memory buffer should be non-movable, which normally means that is is allocated
-	 * off-heap */
-	private long bufaddress;
-
-	private final static boolean isLittleEndian = ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
-
-	{
-		varIntsEnabled = false;
-
-	}
-
-	/** Creates an uninitialized Output. {@link #setBuffer(byte[])} must be called before the Output is used. */
-	public UnsafeMemoryOutput () {
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @param bufferSize The initial and maximum size of the buffer. An exception is thrown if this size is exceeded. */
-	public UnsafeMemoryOutput (int bufferSize) {
-		this(bufferSize, bufferSize);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @param bufferSize The initial size of the buffer.
-	 * @param maxBufferSize The buffer is doubled as needed until it exceeds maxBufferSize and an exception is thrown. */
-	public UnsafeMemoryOutput (int bufferSize, int maxBufferSize) {
-		super(bufferSize, maxBufferSize);
-		updateBufferAddress();
-	}
-
-	/** Creates a new Output for writing to an OutputStream. A buffer size of 4096 is used. */
-	public UnsafeMemoryOutput (OutputStream outputStream) {
-		super(outputStream);
-		updateBufferAddress();
-	}
-
-	/** Creates a new Output for writing to an OutputStream. */
-	public UnsafeMemoryOutput (OutputStream outputStream, int bufferSize) {
-		super(outputStream, bufferSize);
-		updateBufferAddress();
-	}
-
-	public UnsafeMemoryOutput (long address, int maxBufferSize) {
-		super(address, maxBufferSize);
-		updateBufferAddress();
-	}
-
-	public void setBuffer (ByteBuffer buffer, int maxBufferSize) {
-		super.setBuffer(buffer, maxBufferSize);
-		updateBufferAddress();
-	}
-
-	private void updateBufferAddress () {
-		bufaddress = ((DirectBuffer)super.niobuffer).address();
-	}
-
-	/** Writes a 4 byte int. */
-	final public void writeInt (int value) throws KryoException {
-		require(4);
-		unsafe().putInt(bufaddress + position, value);
-		position += 4;
-	}
-
-	/** Writes a 4 byte float. */
-	final public void writeFloat (float value) throws KryoException {
-		require(4);
-		unsafe().putFloat(bufaddress + position, value);
-		position += 4;
-	}
-
-	/** Writes a 2 byte short. */
-	final public void writeShort (int value) throws KryoException {
-		require(2);
-		unsafe().putShort(bufaddress + position, (short)value);
-		position += 2;
-	}
-
-	/** Writes an 8 byte long. */
-	final public void writeLong (long value) throws KryoException {
-		require(8);
-		unsafe().putLong(bufaddress + position, value);
-		position += 8;
-	}
-
-	final public void writeByte (int value) throws KryoException {
-		super.niobuffer.position(position);
-		super.writeByte(value);
-	}
-
-	public void writeByte (byte value) throws KryoException {
-		super.niobuffer.position(position);
-		super.writeByte(value);
-	}
-
-	/** Writes a 1 byte boolean. */
-	final public void writeBoolean (boolean value) throws KryoException {
-		super.niobuffer.position(position);
-		super.writeBoolean(value);
-	}
-
-	/** Writes a 2 byte char. */
-	final public void writeChar (char value) throws KryoException {
-		require(2);
-		unsafe().putChar(bufaddress + position, value);
-		position += 2;
-	}
-
-	/** Writes an 8 byte double. */
-	final public void writeDouble (double value) throws KryoException {
-		require(8);
-		unsafe().putDouble(bufaddress + position, value);
-		position += 8;
-	}
-
-	final public int writeInt (int value, boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled) {
-			writeInt(value);
-			return 4;
-		} else
-			return writeVarInt(value, optimizePositive);
-	}
-
-	final public int writeLong (long value, boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled) {
-			writeLong(value);
-			return 8;
-		} else
-			return writeVarLong(value, optimizePositive);
-	}
-
-	final public int writeVarInt (int val, boolean optimizePositive) throws KryoException {
-		long value = val;
-		if (!optimizePositive) value = (value << 1) ^ (value >> 31);
-		long varInt = 0;
-
-		varInt = (value & 0x7F);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeByte((byte)varInt);
-			return 1;
-		}
-
-		varInt |= 0x80;
-		varInt |= ((value & 0x7F) << 8);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt((int)varInt);
-			position -= 2;
-			return 2;
-		}
-
-		varInt |= (0x80 << 8);
-		varInt |= ((value & 0x7F) << 16);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt((int)varInt);
-			position -= 1;
-			return 3;
-		}
-
-		varInt |= (0x80 << 16);
-		varInt |= ((value & 0x7F) << 24);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt((int)varInt);
-			position -= 0;
-			return 4;
-		}
-
-		varInt |= (0x80L << 24);
-		varInt |= ((value & 0x7F) << 32);
-		varInt &= 0xFFFFFFFFFL;
-		writeLittleEndianLong(varInt);
-		position -= 3;
-		return 5;
-	}
-
-	final public int writeVarLong (long value, boolean optimizePositive) throws KryoException {
-		if (!optimizePositive) value = (value << 1) ^ (value >> 63);
-		int varInt = 0;
-
-		varInt = (int)(value & 0x7F);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeByte(varInt);
-			return 1;
-		}
-
-		varInt |= 0x80;
-		varInt |= ((value & 0x7F) << 8);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 2;
-			return 2;
-		}
-
-		varInt |= (0x80 << 8);
-		varInt |= ((value & 0x7F) << 16);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 1;
-			return 3;
-		}
-
-		varInt |= (0x80 << 16);
-		varInt |= ((value & 0x7F) << 24);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 0;
-			return 4;
-		}
-
-		varInt |= (0x80L << 24);
-		long varLong = (varInt & 0xFFFFFFFFL);
-		varLong |= ((value & 0x7F) << 32);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianLong(varLong);
-			position -= 3;
-			return 5;
-		}
-
-		varLong |= (0x80L << 32);
-		varLong |= ((value & 0x7F) << 40);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianLong(varLong);
-			position -= 2;
-			return 6;
-		}
-
-		varLong |= (0x80L << 40);
-		varLong |= ((value & 0x7F) << 48);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianLong(varLong);
-			position -= 1;
-			return 7;
-		}
-
-		varLong |= (0x80L << 48);
-		varLong |= ((value & 0x7F) << 56);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianLong(varLong);
-			return 8;
-		}
-
-		varLong |= (0x80L << 56);
-		writeLittleEndianLong(varLong);
-		writeByte((int)(value & 0xFF));
-		return 9;
-	}
-
-	final private void writeLittleEndianInt (int val) {
-		if (isLittleEndian)
-			writeInt(val);
-		else
-			writeInt(Util.swapInt(val));
-	}
-
-	final private void writeLittleEndianLong (long val) {
-		if (isLittleEndian)
-			writeLong(val);
-		else
-			writeLong(Util.swapLong(val));
-	}
-
-	// Methods implementing bulk operations on arrays of primitive types
-
-	final public void writeInts (int[] object, boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled) {
-			int bytesToCopy = object.length << 2;
-			writeBytes(object, intArrayBaseOffset, 0, bytesToCopy);
-		} else
-			super.writeInts(object, optimizePositive);
-	}
-
-	final public void writeLongs (long[] object, boolean optimizePositive) throws KryoException {
-		if (!varIntsEnabled) {
-			int bytesToCopy = object.length << 3;
-			writeBytes(object, longArrayBaseOffset, 0, bytesToCopy);
-		} else
-			super.writeLongs(object, optimizePositive);
-	}
-
-	final public void writeInts (int[] object) throws KryoException {
-		int bytesToCopy = object.length << 2;
-		writeBytes(object, intArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeLongs (long[] object) throws KryoException {
-		int bytesToCopy = object.length << 3;
-		writeBytes(object, longArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeFloats (float[] object) throws KryoException {
-		int bytesToCopy = object.length << 2;
-		writeBytes(object, floatArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeShorts (short[] object) throws KryoException {
-		int bytesToCopy = object.length << 1;
-		writeBytes(object, shortArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeChars (char[] object) throws KryoException {
-		int bytesToCopy = object.length << 1;
-		writeBytes(object, charArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeDoubles (double[] object) throws KryoException {
-		int bytesToCopy = object.length << 3;
-		writeBytes(object, doubleArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	/** Writes the bytes. Note the byte[] length is not written. */
-	public void writeBytes (byte[] bytes) throws KryoException {
-		if (bytes == null) throw new IllegalArgumentException("bytes cannot be null.");
-		writeBytes(bytes, 0, (long)bytes.length);
-	}
-
-	/*** Output count bytes from a memory region starting at the given #{offset} inside the in-memory representation of obj object.
-	 * @param obj
-	 * @param offset
-	 * @param count */
-	final public void writeBytes (Object obj, long offset, long count) throws KryoException {
-		writeBytes(obj, byteArrayBaseOffset, offset, count);
-	}
-
-	/*** Output count bytes from a memory region starting at the given #{offset} inside the in-memory representation of obj object.
-	 * The destination is defined by its address */
-	final private void writeBytes (Object srcArray, long srcArrayTypeOffset, long srcOffset, long count) throws KryoException {
-		int copyCount = Math.min(capacity - position, (int)count);
-
-		while (true) {
-			unsafe().copyMemory(srcArray, srcArrayTypeOffset + srcOffset, null, bufaddress + position, copyCount);
-			position += copyCount;
-			count -= copyCount;
-			if (count == 0) return;
-			srcOffset += copyCount;
-			copyCount = Math.min(capacity, (int)count);
-			require(copyCount);
-		}
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/UnsafeOutput.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/UnsafeOutput.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,400 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.io;
-
-import static com.esotericsoftware.kryo.util.UnsafeUtil.*;
-
-import java.io.OutputStream;
-import java.nio.ByteOrder;
-
-import com.esotericsoftware.kryo.KryoException;
-import com.esotericsoftware.kryo.util.Util;
-
-/** An optimized OutputStream that buffers data in a byte array and optionally flushes to another OutputStream. Utility methods
- * are provided for efficiently writing primitive types, arrays of primitive types and strings. It uses @link{sun.misc.Unsafe} to
- * achieve a very good performance.
- * 
- * <p>
- * Important notes:<br/>
- * <li>This class increases performance, but may result in bigger size of serialized representation.</li>
- * <li>Bulk operations, e.g. on arrays of primitive types, are always using native byte order.</li>
- * <li>Fixed-size char, int, long, short, float and double elements are always written using native byte order.</li>
- * <li>Best performance is achieved if no variable length encoding for integers is used.</li>
- * <li>Output serialized using this class should always be deserilized using @link{UnsafeInput}</li>
- * 
- * </p>
- * @author Roman Levenstein <romixlev@gmail.com> */
-public final class UnsafeOutput extends Output {
-
-	/** If set, variable length encoding will be set for integer types if it is required */
-	private boolean supportVarInts = false;
-
-	private static final boolean isLittleEndian = ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
-
-	/** Creates an uninitialized Output. {@link #setBuffer(byte[], int)} must be called before the Output is used. */
-	public UnsafeOutput () {
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @param bufferSize The initial and maximum size of the buffer. An exception is thrown if this size is exceeded. */
-	public UnsafeOutput (int bufferSize) {
-		this(bufferSize, bufferSize);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @param bufferSize The initial size of the buffer.
-	 * @param maxBufferSize The buffer is doubled as needed until it exceeds maxBufferSize and an exception is thrown. */
-	public UnsafeOutput (int bufferSize, int maxBufferSize) {
-		super(bufferSize, maxBufferSize);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @see #setBuffer(byte[]) */
-	public UnsafeOutput (byte[] buffer) {
-		this(buffer, buffer.length);
-	}
-
-	/** Creates a new Output for writing to a byte array.
-	 * 
-	 * @see #setBuffer(byte[], int) */
-	public UnsafeOutput (byte[] buffer, int maxBufferSize) {
-		super(buffer, maxBufferSize);
-	}
-
-	/** Creates a new Output for writing to an OutputStream. A buffer size of 4096 is used. */
-	public UnsafeOutput (OutputStream outputStream) {
-		super(outputStream);
-	}
-
-	/** Creates a new Output for writing to an OutputStream. */
-	public UnsafeOutput (OutputStream outputStream, int bufferSize) {
-		super(outputStream, bufferSize);
-	}
-
-	/** Writes a 4 byte int. */
-	final public void writeInt (int value) throws KryoException {
-		require(4);
-		unsafe().putInt(buffer, byteArrayBaseOffset + position, value);
-		position += 4;
-	}
-
-	final private void writeLittleEndianInt (int val) {
-		if (isLittleEndian)
-			writeInt(val);
-		else
-			writeInt(Util.swapInt(val));
-	}
-
-	/** Writes a 4 byte float. */
-	final public void writeFloat (float value) throws KryoException {
-		require(4);
-		unsafe().putFloat(buffer, byteArrayBaseOffset + position, value);
-		position += 4;
-	}
-
-	/** Writes a 2 byte short. */
-	final public void writeShort (int value) throws KryoException {
-		require(2);
-		unsafe().putShort(buffer, byteArrayBaseOffset + position, (short)value);
-		position += 2;
-	}
-
-	/** Writes an 8 byte long. */
-	final public void writeLong (long value) throws KryoException {
-		require(8);
-		unsafe().putLong(buffer, byteArrayBaseOffset + position, value);
-		position += 8;
-	}
-
-	final private void writeLittleEndianLong (long val) {
-		if (isLittleEndian)
-			writeLong(val);
-		else
-			writeLong(Util.swapLong(val));
-	}
-
-	/** Writes an 8 byte double. */
-	final public void writeDouble (double value) throws KryoException {
-		require(8);
-		unsafe().putDouble(buffer, byteArrayBaseOffset + position, value);
-		position += 8;
-	}
-
-	/** Writes a 2 byte char. */
-	final public void writeChar (char value) throws KryoException {
-		require(2);
-		unsafe().putChar(buffer, byteArrayBaseOffset + position, value);
-		position += 2;
-	}
-
-	final public int writeInt (int value, boolean optimizePositive) throws KryoException {
-		if (!supportVarInts) {
-			writeInt(value);
-			return 4;
-		} else
-			return writeVarInt(value, optimizePositive);
-	}
-
-	final public int writeLong (long value, boolean optimizePositive) throws KryoException {
-		if (!supportVarInts) {
-			writeLong(value);
-			return 8;
-		} else
-			return writeVarLong(value, optimizePositive);
-	}
-
-	final public int writeVarInt (int val, boolean optimizePositive) throws KryoException {
-		int value = val;
-		if (!optimizePositive) value = (value << 1) ^ (value >> 31);
-		int varInt = 0;
-
-		varInt = (value & 0x7F);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			write(varInt);
-			return 1;
-		}
-
-		varInt |= 0x80;
-		varInt |= ((value & 0x7F) << 8);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 2;
-			return 2;
-		}
-
-		varInt |= 0x80 << 8;
-		varInt |= ((value & 0x7F) << 16);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 1;
-			return 3;
-		}
-
-		varInt |= 0x80 << 16;
-		varInt |= ((value & 0x7F) << 24);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 0;
-			return 4;
-		}
-
-		long varLong = varInt;
-		varLong |= (0x80L << 24);
-		varLong |= ((long)(value & 0x7F) << 32);
-		varLong &= 0xFFFFFFFFFL;
-		writeLittleEndianLong(varLong);
-		position -= 3;
-		return 5;
-	}
-
-	// TODO: Make it work on little and big endian machines
-	final public int writeVarLong (long value, boolean optimizePositive) throws KryoException {
-		if (!optimizePositive) value = (value << 1) ^ (value >> 63);
-		int varInt = 0;
-
-		varInt = (int)(value & 0x7F);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeByte(varInt);
-			return 1;
-		}
-
-		varInt |= 0x80;
-		varInt |= ((value & 0x7F) << 8);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 2;
-			return 2;
-		}
-
-		varInt |= (0x80 << 8);
-		varInt |= ((value & 0x7F) << 16);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 1;
-			return 3;
-		}
-
-		varInt |= (0x80 << 16);
-		varInt |= ((value & 0x7F) << 24);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianInt(varInt);
-			position -= 0;
-			return 4;
-		}
-
-		long varLong = (varInt & 0xFFFFFFFFL) | (0x80L << 24);
-		varLong |= ((value & 0x7F) << 32);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianLong(varLong);
-			position -= 3;
-			return 5;
-		}
-
-		varLong |= (0x80L << 32);
-		varLong |= ((value & 0x7F) << 40);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianLong(varLong);
-			position -= 2;
-			return 6;
-		}
-
-		varLong |= (0x80L << 40);
-		varLong |= ((value & 0x7F) << 48);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianLong(varLong);
-			position -= 1;
-			return 7;
-		}
-
-		varLong |= (0x80L << 48);
-		varLong |= ((value & 0x7F) << 56);
-
-		value >>>= 7;
-
-		if (value == 0) {
-			writeLittleEndianLong(varLong);
-			return 8;
-		}
-
-		varLong |= (0x80L << 56);
-		writeLittleEndianLong(varLong);
-		write((int)(value & 0xFF));
-		return 9;
-	}
-
-	// Methods implementing bulk operations on arrays of primitive types
-
-	final public void writeInts (int[] object, boolean optimizePositive) throws KryoException {
-		if (!supportVarInts) {
-			int bytesToCopy = object.length << 2;
-			writeBytes(object, intArrayBaseOffset, 0, bytesToCopy);
-		} else
-			super.writeInts(object, optimizePositive);
-	}
-
-	final public void writeLongs (long[] object, boolean optimizePositive) throws KryoException {
-		if (!supportVarInts) {
-			int bytesToCopy = object.length << 3;
-			writeBytes(object, longArrayBaseOffset, 0, bytesToCopy);
-		} else
-			super.writeLongs(object, optimizePositive);
-	}
-
-	final public void writeInts (int[] object) throws KryoException {
-		int bytesToCopy = object.length << 2;
-		writeBytes(object, intArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeLongs (long[] object) throws KryoException {
-		int bytesToCopy = object.length << 3;
-		writeBytes(object, longArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeFloats (float[] object) throws KryoException {
-		int bytesToCopy = object.length << 2;
-		writeBytes(object, floatArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeShorts (short[] object) throws KryoException {
-		int bytesToCopy = object.length << 1;
-		writeBytes(object, shortArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeChars (char[] object) throws KryoException {
-		int bytesToCopy = object.length << 1;
-		writeBytes(object, charArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	final public void writeDoubles (double[] object) throws KryoException {
-		int bytesToCopy = object.length << 3;
-		writeBytes(object, doubleArrayBaseOffset, 0, bytesToCopy);
-	}
-
-	/*** Output count bytes from a memory region starting at the given #{offset} inside the in-memory representation of obj object.
-	 * @param obj
-	 * @param offset
-	 * @param count */
-	final public void writeBytes (Object obj, long offset, long count) throws KryoException {
-		writeBytes(obj, 0, offset, count);
-	}
-
-	final private void writeBytes (Object srcArray, long srcArrayTypeOffset, long srcOffset, long count) throws KryoException {
-		int copyCount = Math.min(capacity - position, (int)count);
-
-		while (true) {
-			unsafe().copyMemory(srcArray, srcArrayTypeOffset + srcOffset, buffer, byteArrayBaseOffset + position, copyCount);
-			position += copyCount;
-			count -= copyCount;
-			if (count == 0) return;
-			srcOffset += copyCount;
-			copyCount = Math.min(capacity, (int)count);
-			require(copyCount);
-		}
-	}
-
-	/*** Return current setting for variable length encoding of integers
-	 * @return current setting for variable length encoding of integers */
-	public boolean supportVarInts () {
-		return supportVarInts;
-	}
-
-	/*** Controls if a variable length encoding for integer types should be used when serializers suggest it.
-	 * 
-	 * @param supportVarInts */
-	public void supportVarInts (boolean supportVarInts) {
-		this.supportVarInts = supportVarInts;
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/Util.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/io/Util.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,29 +0,0 @@
-/* Copyright (c) 2017, Nathan Sweet
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.io;
-
-/** IO package utilities.
- * @author Rafal Wojdyla <ravwojdyla@gmail.com> */
-class Util {
-
-    //See: https://stackoverflow.com/questions/3038392/do-java-arrays-have-a-maximum-size
-    static final int MAX_SAFE_ARRAY_SIZE = Integer.MAX_VALUE - 8;
-
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/Kryo.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/Kryo.java	2018-12-20 09:20:46.834804204 +0100
@@ -49,9 +49,8 @@
 import org.objenesis.strategy.SerializingInstantiatorStrategy;
 import org.objenesis.strategy.StdInstantiatorStrategy;
 
-import com.esotericsoftware.kryo.factories.PseudoSerializerFactory;
-import com.esotericsoftware.kryo.factories.ReflectionSerializerFactory;
-import com.esotericsoftware.kryo.factories.SerializerFactory;
+import com.esotericsoftware.kryo.SerializerFactory.ReflectionSerializerFactory;
+import com.esotericsoftware.kryo.SerializerFactory.SingletonSerializerFactory;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
 import com.esotericsoftware.kryo.serializers.ClosureSerializer;
@@ -100,14 +99,11 @@
 import com.esotericsoftware.kryo.serializers.DefaultSerializers.URLSerializer;
 import com.esotericsoftware.kryo.serializers.DefaultSerializers.VoidSerializer;
 import com.esotericsoftware.kryo.serializers.FieldSerializer;
-import com.esotericsoftware.kryo.serializers.FieldSerializerConfig;
 import com.esotericsoftware.kryo.serializers.GenericsResolver;
 import com.esotericsoftware.kryo.serializers.MapSerializer;
 import com.esotericsoftware.kryo.serializers.OptionalSerializers;
-import com.esotericsoftware.kryo.serializers.TaggedFieldSerializerConfig;
 import com.esotericsoftware.kryo.serializers.TimeSerializers;
 import com.esotericsoftware.kryo.util.DefaultClassResolver;
-import com.esotericsoftware.kryo.util.DefaultStreamFactory;
 import com.esotericsoftware.kryo.util.IdentityMap;
 import com.esotericsoftware.kryo.util.IntArray;
 import com.esotericsoftware.kryo.util.MapReferenceResolver;
@@ -151,37 +147,24 @@
 	private Object needsCopyReference;
 	private GenericsResolver genericsResolver = new GenericsResolver();
 
-	private FieldSerializerConfig fieldSerializerConfig = new FieldSerializerConfig();
-	private TaggedFieldSerializerConfig taggedFieldSerializerConfig = new TaggedFieldSerializerConfig();
-
-	private StreamFactory streamFactory;
-
 	/** Creates a new Kryo with a {@link DefaultClassResolver} and a {@link MapReferenceResolver}. */
 	public Kryo () {
-		this(new DefaultClassResolver(), new MapReferenceResolver(), new DefaultStreamFactory());
+		this(new DefaultClassResolver(), new MapReferenceResolver());
 	}
 
 	/** Creates a new Kryo with a {@link DefaultClassResolver}.
 	 * @param referenceResolver May be null to disable references. */
 	public Kryo (ReferenceResolver referenceResolver) {
-		this(new DefaultClassResolver(), referenceResolver, new DefaultStreamFactory());
+		this(new DefaultClassResolver(), referenceResolver);
 	}
 
 	/** @param referenceResolver May be null to disable references. */
 	public Kryo (ClassResolver classResolver, ReferenceResolver referenceResolver) {
-		this(classResolver, referenceResolver, new DefaultStreamFactory());
-	}
-
-	/** @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);
@@ -263,7 +246,7 @@
 	public void addDefaultSerializer (Class type, Serializer serializer) {
 		if (type == null) throw new IllegalArgumentException("type cannot be null.");
 		if (serializer == null) throw new IllegalArgumentException("serializer cannot be null.");
-		DefaultSerializerEntry entry = new DefaultSerializerEntry(type, new PseudoSerializerFactory(serializer));
+		DefaultSerializerEntry entry = new DefaultSerializerEntry(type, new SingletonSerializerFactory(serializer));
 		defaultSerializers.add(defaultSerializers.size() - lowPriorityDefaultSerializerCount, entry);
 	}
 
@@ -279,7 +262,7 @@
 
 	/** Instances of the specified class will use the specified serializer when {@link #register(Class)} or
 	 * {@link #register(Class, int)} are called. Serializer instances are created as needed via
-	 * {@link ReflectionSerializerFactory#makeSerializer(Kryo, Class, Class)}. By default, the following classes have a default
+	 * {@link ReflectionSerializerFactory#newSerializer(Kryo, Class, Class)}. By default, the following classes have a default
 	 * serializer set:
 	 * <p>
 	 * <table>
@@ -372,7 +355,7 @@
 		for (int i = 0, n = defaultSerializers.size(); i < n; i++) {
 			DefaultSerializerEntry entry = defaultSerializers.get(i);
 			if (entry.type.isAssignableFrom(type)) {
-				Serializer defaultSerializer = entry.serializerFactory.makeSerializer(this, type);
+				Serializer defaultSerializer = entry.serializerFactory.newSerializer(this, type);
 				return defaultSerializer;
 			}
 		}
@@ -383,17 +366,16 @@
 	protected Serializer getDefaultSerializerForAnnotatedType (Class type) {
 		if (type.isAnnotationPresent(DefaultSerializer.class)) {
 			DefaultSerializer defaultSerializerAnnotation = (DefaultSerializer)type.getAnnotation(DefaultSerializer.class);
-			return ReflectionSerializerFactory.makeSerializer(this, defaultSerializerAnnotation.value(), type);
+			return ReflectionSerializerFactory.newSerializer(this, defaultSerializerAnnotation.value(), type);
 		}
-
 		return null;
 	}
 
 	/** Called by {@link #getDefaultSerializer(Class)} when no default serializers matched the type. Subclasses can override this
-	 * method to customize behavior. The default implementation calls {@link SerializerFactory#makeSerializer(Kryo, Class)} using
+	 * method to customize behavior. The default implementation calls {@link SerializerFactory#newSerializer(Kryo, Class)} using
 	 * the {@link #setDefaultSerializer(Class) default serializer}. */
 	protected Serializer newDefaultSerializer (Class type) {
-		return defaultSerializer.makeSerializer(this, type);
+		return defaultSerializer.newSerializer(this, type);
 	}
 
 	// --- Registration ---
@@ -442,8 +424,8 @@
 	 * cause the old entry to be overwritten. Registering a primitive also affects the corresponding primitive wrapper.
 	 * <p>
 	 * IDs must be the same at deserialization as they were for serialization.
-	 * @param id Must be >= 0. Smaller IDs are serialized more efficiently. IDs 0-9 are used by default for primitive types
-	 *           and their wrappers, String, and void, but these IDs can be repurposed. */
+	 * @param id Must be >= 0. Smaller IDs are serialized more efficiently. IDs 0-9 are used by default for primitive types and
+	 *           their wrappers, String, and void, but these IDs can be repurposed. */
 	public Registration register (Class type, Serializer serializer, int id) {
 		if (id < 0) throw new IllegalArgumentException("id must be >= 0: " + id);
 		return register(new Registration(type, serializer, id));
@@ -1052,9 +1034,7 @@
 
 	/** If true, kryo writes a warn log telling about the classes unregistered. Default is false.
 	 * <p>
-	 * If false, no log are written when unregistered classes are encountered.
-	 * </p>
-	*/
+	 * If false, no log are written when unregistered classes are encountered. */
 	public void setWarnUnregisteredClasses (boolean warnUnregisteredClasses) {
 		this.warnUnregisteredClasses = warnUnregisteredClasses;
 		if (TRACE) trace("kryo", "Warn unregistered classes: " + warnUnregisteredClasses);
@@ -1084,17 +1064,6 @@
 		this.copyReferences = copyReferences;
 	}
 
-	/** The default configuration for {@link FieldSerializer} instances. Already existing serializer instances (e.g. implicitely
-	 * created for already registered classes) are not affected by this configuration. You can override the configuration for a
-	 * single {@link FieldSerializer}. */
-	public FieldSerializerConfig getFieldSerializerConfig () {
-		return fieldSerializerConfig;
-	}
-
-	public TaggedFieldSerializerConfig getTaggedFieldSerializerConfig () {
-		return taggedFieldSerializerConfig;
-	}
-
 	/** Sets the reference resolver and enables references. */
 	public void setReferenceResolver (ReferenceResolver referenceResolver) {
 		if (referenceResolver == null) throw new IllegalArgumentException("referenceResolver cannot be null.");
@@ -1123,7 +1092,6 @@
 	 * uses reflection if the class has a zero argument constructor, an exception is thrown. If a
 	 * {@link #setInstantiatorStrategy(InstantiatorStrategy) strategy} is set, it will be used instead of throwing an exception. */
 	protected ObjectInstantiator newInstantiator (final Class type) {
-		// InstantiatorStrategy.
 		return strategy.newInstantiatorOf(type);
 	}
 
@@ -1212,36 +1180,6 @@
 		return genericsResolver;
 	}
 
-	public StreamFactory getStreamFactory () {
-		return streamFactory;
-	}
-
-	public void setStreamFactory (StreamFactory streamFactory) {
-		this.streamFactory = streamFactory;
-	}
-
-	/** Tells Kryo, if ASM-based backend should be used by new serializer instances created using this Kryo instance. Already
-	 * existing serializer instances are not affected by this setting.
-	 * 
-	 * <p>
-	 * By default, Kryo uses ASM-based backend.
-	 * </p>
-	 * 
-	 * @param flag if true, ASM-based backend will be used. Otherwise Unsafe-based backend could be used by some serializers, e.g.
-	 *           FieldSerializer
-	 *
-	 * @deprecated Use {@link #getFieldSerializerConfig()} to change the default {@link FieldSerializer} configuration. */
-	@Deprecated
-	public void setAsmEnabled (boolean flag) {
-		fieldSerializerConfig.setUseAsm(flag);
-	}
-
-	/** @deprecated Use {@link #getFieldSerializerConfig()} to change the default {@link FieldSerializer} configuration. */
-	@Deprecated
-	public boolean getAsmEnabled () {
-		return fieldSerializerConfig.isUseAsm();
-	}
-
 	static public class DefaultInstantiatorStrategy implements org.objenesis.strategy.InstantiatorStrategy {
 		private InstantiatorStrategy fallbackStrategy;
 
@@ -1261,7 +1199,7 @@
 		}
 
 		public ObjectInstantiator newInstantiatorOf (final Class type) {
-			if (!Util.IS_ANDROID) {
+			if (!Util.isAndroid) {
 				// Use ReflectASM if the class is not a non-static member class.
 				Class enclosingType = type.getEnclosingClass();
 				boolean isNonStaticMemberClass = enclosingType != null && type.isMemberClass()
@@ -1307,13 +1245,17 @@
 				if (type.isMemberClass() && !Modifier.isStatic(type.getModifiers()))
 					throw new KryoException("Class cannot be created (non-static member class): " + className(type));
 				else {
-					StringBuilder errorMessageSb = new StringBuilder("Class cannot be created (missing no-arg constructor): " + className(type));
+					StringBuilder errorMessageSb = new StringBuilder(
+						"Class cannot be created (missing no-arg constructor): " + className(type));
 					if (type.getSimpleName().equals("")) {
-						errorMessageSb.append("\n\tThis is an anonymous class, which is not serializable by default in Kryo. Possible solutions: ")
+						errorMessageSb
+							.append("\n\tThis is an anonymous class, which is not serializable by default in Kryo. Possible solutions: ")
 							.append("1. Remove uses of anonymous classes, including double brace initialization, from the containing ")
-							.append("class. This is the safest solution, as anonymous classes don't have predictable names for serialization.")
+							.append(
+								"class. This is the safest solution, as anonymous classes don't have predictable names for serialization.")
 							.append("\n\t2. Register a FieldSerializer for the containing class and call ")
-							.append( "FieldSerializer#setIgnoreSyntheticFields(false) on it. This is not safe but may be sufficient temporarily. ")
+							.append(
+								"FieldSerializer#setIgnoreSyntheticFields(false) on it. This is not safe but may be sufficient temporarily. ")
 							.append("Use at your own risk.");
 					}
 					throw new KryoException(errorMessageSb.toString());
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/KryoCallback.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/KryoCallback.java	2018-12-20 09:20:46.842804245 +0100
@@ -22,9 +22,7 @@
 import com.esotericsoftware.kryo.Kryo;
 
 /** Callback to run with a provided kryo instance.
- *
  * @author Martin Grotzke
- *
  * @param <T> The type of the result of the interaction with kryo. */
 public interface KryoCallback<T> {
 	T execute (Kryo kryo);
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/KryoFactory.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/KryoFactory.java	2018-12-20 09:20:46.842804245 +0100
@@ -22,7 +22,6 @@
 import com.esotericsoftware.kryo.Kryo;
 
 /** Factory to create new configured instances of {@link Kryo}.
- * 
  * @author Martin Grotzke */
 public interface KryoFactory {
 	Kryo create ();
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/KryoPool.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/KryoPool.java	2018-12-20 09:20:46.842804245 +0100
@@ -52,7 +52,6 @@
  *     return kryo.readObject(input, String.class);
  *   }
  * });
- *
  * </pre>
  * 
  * @author Martin Grotzke */
@@ -69,8 +67,7 @@
 	<T> T run (KryoCallback<T> callback);
 
 	/** Builder for a {@link KryoPool} instance, constructs a {@link KryoPoolQueueImpl} instance. */
-	public static class Builder {
-
+	static public class Builder {
 		private final KryoFactory factory;
 		private Queue<Kryo> queue = new ConcurrentLinkedQueue<Kryo>();
 		private boolean softReferences;
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/KryoPoolQueueImpl.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/KryoPoolQueueImpl.java	2018-12-20 09:20:46.842804245 +0100
@@ -24,10 +24,8 @@
 import com.esotericsoftware.kryo.Kryo;
 
 /** A simple {@link Queue} based {@link KryoPool} implementation, should be built using the KryoPool.Builder.
- *
  * @author Martin Grotzke */
 class KryoPoolQueueImpl implements KryoPool {
-
 	private final Queue<Kryo> queue;
 	private final KryoFactory factory;
 
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/SoftReferenceQueue.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/pool/SoftReferenceQueue.java	2018-12-20 09:20:46.842804245 +0100
@@ -27,11 +27,9 @@
 import com.esotericsoftware.kryo.Kryo;
 
 /** Internally uses {@link SoftReference}s for queued Kryo instances, most importantly adjusts the {@link Queue#poll() poll}
- * behavior so that gc'ed Kryo instances are skipped. Most other methods are unsupported.
- *
+ * behavior so that GC'ed Kryo instances are skipped. Most other methods are unsupported.
  * @author Martin Grotzke */
 class SoftReferenceQueue implements Queue<Kryo> {
-
 	private Queue<SoftReference<Kryo>> delegate;
 
 	public SoftReferenceQueue (Queue<?> delegate) {
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/SerializerFactory.java	1970-01-01 01:00:00.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/SerializerFactory.java	2018-12-20 09:20:46.834804204 +0100
@@ -0,0 +1,141 @@
+/* Copyright (c) 2008-2017, Nathan Sweet
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
+ * conditions are met:
+ * 
+ * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the distribution.
+ * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+package com.esotericsoftware.kryo;
+
+import static com.esotericsoftware.kryo.util.Util.*;
+
+import com.esotericsoftware.kryo.serializers.FieldSerializer;
+import com.esotericsoftware.kryo.serializers.FieldSerializerConfig;
+import com.esotericsoftware.kryo.serializers.TaggedFieldSerializer;
+import com.esotericsoftware.kryo.serializers.TaggedFieldSerializerConfig;
+
+/** A serializer factory that allows the creation of serializers. This factory will be called when a {@link Kryo} serializer
+ * discovers a new type for which no serializer is yet known. For example, when a factory is registered via
+ * {@link Kryo#setDefaultSerializer(SerializerFactory)} a different serializer can be created dependent on the type of a class.
+ * @author Rafael Winterhalter <rafael.wth@web.de> */
+public interface SerializerFactory {
+	/** Creates a new serializer
+	 * @param kryo The serializer instance requesting the new serializer.
+	 * @param type The type of the object that is to be serialized.
+	 * @return An implementation of a serializer that is able to serialize an object of type {@code type}. */
+	Serializer newSerializer (Kryo kryo, Class<?> type);
+
+	/** This factory instantiates new serializers of a given class via reflection. The constructors of the given
+	 * {@code serializerClass} must either take an instance of {@link Kryo} and an instance of {@link Class} as its parameter, take
+	 * only a {@link Kryo} or {@link Class} as its only argument or take no arguments. If several of the described constructors are
+	 * found, the first found constructor is used, in the order as they were just described.
+	 * @author Rafael Winterhalter <rafael.wth@web.de> */
+	static public class ReflectionSerializerFactory implements SerializerFactory {
+		private final Class<? extends Serializer> serializerClass;
+
+		public ReflectionSerializerFactory (Class<? extends Serializer> serializerClass) {
+			this.serializerClass = serializerClass;
+		}
+
+		@Override
+		public Serializer newSerializer (Kryo kryo, Class<?> type) {
+			return newSerializer(kryo, serializerClass, type);
+		}
+
+		/** Creates a new instance of the specified serializer for serializing the specified class. Serializers must have a zero
+		 * argument constructor or one that takes (Kryo), (Class), or (Kryo, Class). */
+		static public Serializer newSerializer (Kryo kryo, Class<? extends Serializer> serializerClass, Class<?> type) {
+			try {
+				try {
+					return serializerClass.getConstructor(Kryo.class, Class.class).newInstance(kryo, type);
+				} catch (NoSuchMethodException ex1) {
+					try {
+						return serializerClass.getConstructor(Kryo.class).newInstance(kryo);
+					} catch (NoSuchMethodException ex2) {
+						try {
+							return serializerClass.getConstructor(Class.class).newInstance(type);
+						} catch (NoSuchMethodException ex3) {
+							return serializerClass.newInstance();
+						}
+					}
+				}
+			} catch (Exception ex) {
+				throw new IllegalArgumentException(
+					"Unable to create serializer \"" + serializerClass.getName() + "\" for class: " + className(type), ex);
+			}
+		}
+	}
+
+	/** A serializer factory that always returns a given serializer instance rather than creating new serializer instances. It can
+	 * be used when multiple types should be serialized by the same serializer. This also allows serializers to be shared among
+	 * different {@link Kryo} instances.
+	 * @author Rafael Winterhalter <rafael.wth@web.de> */
+	static public class SingletonSerializerFactory implements SerializerFactory {
+		private final Serializer<?> serializer;
+
+		public SingletonSerializerFactory (Serializer<?> serializer) {
+			this.serializer = serializer;
+		}
+
+		@Override
+		public Serializer newSerializer (Kryo kryo, Class<?> type) {
+			return serializer;
+		}
+	}
+
+	/** A serializer factory that returns new, configured {@link FieldSerializer} instances.
+	 * @author Nathan Sweet */
+	static public class FieldSerializerFactory implements SerializerFactory {
+		private final FieldSerializerConfig config;
+
+		public FieldSerializerFactory () {
+			this.config = new FieldSerializerConfig();
+		}
+
+		public FieldSerializerFactory (FieldSerializerConfig config) {
+			this.config = config;
+		}
+
+		public FieldSerializerConfig getConfig () {
+			return config;
+		}
+
+		public Serializer newSerializer (Kryo kryo, Class<?> type) {
+			return new FieldSerializer(kryo, type, null, config.clone());
+		}
+	}
+
+	/** A serializer factory that returns new, configured {@link TaggedFieldSerializer} instances.
+	 * @author Nathan Sweet */
+	static public class TaggedFieldSerializerFactory implements SerializerFactory {
+		private final TaggedFieldSerializerConfig config;
+
+		public TaggedFieldSerializerFactory () {
+			this.config = new TaggedFieldSerializerConfig();
+		}
+
+		public TaggedFieldSerializerFactory (TaggedFieldSerializerConfig config) {
+			this.config = config;
+		}
+
+		public TaggedFieldSerializerConfig getConfig () {
+			return config;
+		}
+
+		public Serializer newSerializer (Kryo kryo, Class<?> type) {
+			return new TaggedFieldSerializer(kryo, type, config.clone());
+		}
+	}
+}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/ClosureSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/ClosureSerializer.java	2018-12-20 09:20:46.842804245 +0100
@@ -37,11 +37,11 @@
 	/** Marker class to bind ClosureSerializer to. See also {@link Kryo#isClosure(Class)} and
 	 * {@link Kryo#getRegistration(Class)} */
 	@SuppressWarnings("javadoc")
-	public static class Closure {
+	static public class Closure {
 	}
 
-	private static Method readResolve;
-	private static Class serializedLambda = java.lang.invoke.SerializedLambda.class;
+	static private Method readResolve;
+	static private Class serializedLambda = java.lang.invoke.SerializedLambda.class;
 	static {
 		try {
 			readResolve = serializedLambda.getDeclaredMethod("readResolve");
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/CollectionSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/CollectionSerializer.java	2018-12-20 09:20:46.842804245 +0100
@@ -155,18 +155,14 @@
 	@Target(ElementType.FIELD)
 	public @interface BindCollection {
 		/** Serializer to be used for values
-		 * 
 		 * @return the class<? extends Serializer> used for values serialization */
-		@SuppressWarnings("rawtypes")
 		Class<? extends Serializer> elementSerializer() default Serializer.class;
 
 		/** Class used for elements
-		 * 
 		 * @return the class used for elements */
 		Class<?> elementClass() default Object.class;
 
 		/** Indicates if elements can be null
-		 * 
 		 * @return true, if elements can be null */
 		boolean elementsCanBeNull() default true;
 	}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.java	2018-12-20 09:20:46.842804245 +0100
@@ -41,12 +41,16 @@
  * Note that the field data is identified by name. The situation where a super class has a field with the same name as a subclass
  * must be avoided.
  * @author Nathan Sweet <misc@n4te.com> */
-public class CompatibleFieldSerializer<T> extends FieldSerializer<T> {
+public class CompatibleFieldSerializer<T> extends FieldSerializer<T, FieldSerializerConfig> {
 	/* For object with more than BINARY_SEARCH_THRESHOLD fields, use binary search instead of iterative search */
-	private static final int THRESHOLD_BINARY_SEARCH = 32;
+	static private final int THRESHOLD_BINARY_SEARCH = 32;
 
 	public CompatibleFieldSerializer (Kryo kryo, Class type) {
-		super(kryo, type);
+		super(kryo, type, null, new FieldSerializerConfig());
+	}
+
+	public CompatibleFieldSerializer (Kryo kryo, Class type, FieldSerializerConfig config) {
+		super(kryo, type, null, config);
 	}
 
 	public void write (Kryo kryo, Output output, T object) {
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/DefaultSerializers.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/DefaultSerializers.java	2018-12-20 09:20:46.842804245 +0100
@@ -811,25 +811,14 @@
 			return create(language, country, variant);
 		}
 
-		// Removed as Locale is declares as immutable
-		// public Locale copy (Kryo kryo, Locale original) {
-		// return create(original.getLanguage(), original.getDisplayCountry(), original.getVariant());
-		// }
-
 		protected static boolean isSameLocale (Locale locale, String language, String country, String variant) {
-			try {
 				return (locale.getLanguage().equals(language) && locale.getCountry().equals(country)
 					&& locale.getVariant().equals(variant));
-			} catch (NullPointerException npe) {
-				// Shouldn't ever happen, no nulls
-				return false;
-			}
 		}
 	}
 
 	/** Serializer for {@link Charset}. */
-	public static class CharsetSerializer extends Serializer<Charset> {
-
+	static public class CharsetSerializer extends Serializer<Charset> {
 		{
 			setImmutable(true);
 		}
@@ -841,12 +830,10 @@
 		public Charset read (Kryo kryo, Input input, Class<Charset> type) {
 			return Charset.forName(input.readString());
 		}
-
 	}
 
 	/** Serializer for {@link URL}. */
-	public static class URLSerializer extends Serializer<URL> {
-
+	static public class URLSerializer extends Serializer<URL> {
 		{
 			setImmutable(true);
 		}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/ExternalizableSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/ExternalizableSerializer.java	2018-12-20 09:20:46.842804245 +0100
@@ -20,7 +20,6 @@
 package com.esotericsoftware.kryo.serializers;
 
 import java.io.Externalizable;
-import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.lang.reflect.Method;
@@ -73,9 +71,7 @@
 	private void writeExternal (Kryo kryo, Output output, Object object) {
 		try {
 			((Externalizable)object).writeExternal(getObjectOutput(kryo, output));
-		} catch (ClassCastException e) {
-			throw new KryoException(e);
-		} catch (IOException e) {
+		} catch (Exception e) {
 			throw new KryoException(e);
 		}
 	}
@@ -85,11 +81,7 @@
 			Externalizable object = (Externalizable)kryo.newInstance(type);
 			object.readExternal(getObjectInput(kryo, input));
 			return object;
-		} catch (ClassCastException e) {
-			throw new KryoException(e);
-		} catch (ClassNotFoundException e) {
-			throw new KryoException(e);
-		} catch (IOException e) {
+		} catch (Exception e) {
 			throw new KryoException(e);
 		}
 	}
@@ -144,7 +135,7 @@
 	}
 
 	/* find out if there are any pesky serialization extras on this class */
-	private static boolean hasInheritableReplaceMethod (Class type, String methodName) {
+	static private boolean hasInheritableReplaceMethod (Class type, String methodName) {
 		Method method = null;
 		Class<?> current = type;
 		while (current != null) {
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerAnnotationsUtil.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerAnnotationsUtil.java	2018-12-20 09:20:46.846804266 +0100
@@ -24,7 +24,7 @@
 import java.util.Map;
 
 import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.factories.ReflectionSerializerFactory;
+import com.esotericsoftware.kryo.SerializerFactory.ReflectionSerializerFactory;
 import com.esotericsoftware.kryo.serializers.FieldSerializer.CachedField;
 
 /** A few utility methods for processing field annotations.
@@ -47,7 +47,7 @@
 			// Set a specific serializer for a particular field
 			if (field.isAnnotationPresent(FieldSerializer.Bind.class)) {
 				Class<? extends Serializer> serializerClass = field.getAnnotation(FieldSerializer.Bind.class).value();
-				Serializer s = ReflectionSerializerFactory.makeSerializer(fieldSerializer.getKryo(), serializerClass,
+				Serializer s = ReflectionSerializerFactory.newSerializer(fieldSerializer.getKryo(), serializerClass,
 					field.getClass());
 				fields[i].setSerializer(s);
 			}
@@ -66,7 +66,7 @@
 					Class<? extends Serializer> elementSerializerClass = annotation.elementSerializer();
 					if (elementSerializerClass == Serializer.class) elementSerializerClass = null;
 					Serializer elementSerializer = (elementSerializerClass == null) ? null
-						: ReflectionSerializerFactory.makeSerializer(fieldSerializer.getKryo(), elementSerializerClass,
+						: ReflectionSerializerFactory.newSerializer(fieldSerializer.getKryo(), elementSerializerClass,
 							field.getClass());
 					boolean elementsCanBeNull = annotation.elementsCanBeNull();
 					Class<?> elementClass = annotation.elementClass();
@@ -97,9 +97,9 @@
 					if (keySerializerClass == Serializer.class) keySerializerClass = null;
 
 					Serializer valueSerializer = (valueSerializerClass == null) ? null
-						: ReflectionSerializerFactory.makeSerializer(fieldSerializer.getKryo(), valueSerializerClass, field.getClass());
+						: ReflectionSerializerFactory.newSerializer(fieldSerializer.getKryo(), valueSerializerClass, field.getClass());
 					Serializer keySerializer = (keySerializerClass == null) ? null
-						: ReflectionSerializerFactory.makeSerializer(fieldSerializer.getKryo(), keySerializerClass, field.getClass());
+						: ReflectionSerializerFactory.newSerializer(fieldSerializer.getKryo(), keySerializerClass, field.getClass());
 					boolean valuesCanBeNull = annotation.valuesCanBeNull();
 					boolean keysCanBeNull = annotation.keysCanBeNull();
 					Class<?> keyClass = annotation.keyClass();
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerConfig.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerConfig.java	2018-12-20 09:20:46.846804266 +0100
@@ -23,16 +23,11 @@
 
 import com.esotericsoftware.kryo.Kryo;
 
-/** Configuration for FieldSerializer instances. To configure defaults for new FieldSerializer instances use
- * {@link Kryo#getFieldSerializerConfig()}, to configure a specific FieldSerializer instance use setters for configuration
- * settings on this specific FieldSerializer. */
+/** Configuration for FieldSerializer instances. */
 public class FieldSerializerConfig implements Cloneable {
-
 	private boolean fieldsCanBeNull = true, setFieldsAsAccessible = true;
 	private boolean ignoreSyntheticFields = true;
 	private boolean fixedFieldTypes;
-	/** If set, ASM-backend is used. Otherwise Unsafe-based backend or reflection is used */
-	private boolean useAsm;
 	/** If set, transient fields will be copied */
 	private boolean copyTransient = true;
 	/** If set, transient fields will be serialized */
@@ -42,13 +37,8 @@
 
 	private FieldSerializer.CachedFieldNameStrategy cachedFieldNameStrategy = FieldSerializer.CachedFieldNameStrategy.DEFAULT;
 
-	{
-		useAsm = !FieldSerializer.unsafeAvailable;
-		if (TRACE) trace("kryo.FieldSerializerConfig", "useAsm: " + useAsm);
-	}
-
 	@Override
-	protected FieldSerializerConfig clone () {
+	public FieldSerializerConfig clone () {
 		// clone is ok here as we have only primitive fields
 		try {
 			return (FieldSerializerConfig)super.clone();
@@ -88,17 +78,6 @@
 		if (TRACE) trace("kryo.FieldSerializerConfig", "setFixedFieldTypes: " + fixedFieldTypes);
 	}
 
-	/** Controls whether ASM should be used.
-	 * @param setUseAsm If true, ASM will be used for fast serialization. If false, Unsafe will be used (default) */
-	public void setUseAsm (boolean setUseAsm) {
-		useAsm = setUseAsm;
-		if (!useAsm && !FieldSerializer.unsafeAvailable) {
-			useAsm = true;
-			if (TRACE) trace("kryo.FieldSerializerConfig", "sun.misc.Unsafe is unavailable, using ASM.");
-		}
-		if (TRACE) trace("kryo.FieldSerializerConfig", "setUseAsm: " + setUseAsm);
-	}
-
 	/** Controls if the serialization of generics should be optimized for smaller size.
 	 * <p>
 	 * <strong>Important:</strong> This setting changes the serialized representation, so that data can be deserialized only with
@@ -123,35 +102,31 @@
 		this.serializeTransient = serializeTransient;
 	}
 
-	public boolean isFieldsCanBeNull () {
+	public boolean getFieldsCanBeNull () {
 		return fieldsCanBeNull;
 	}
 
-	public boolean isSetFieldsAsAccessible () {
+	public boolean getSetFieldsAsAccessible () {
 		return setFieldsAsAccessible;
 	}
 
-	public boolean isIgnoreSyntheticFields () {
+	public boolean getIgnoreSyntheticFields () {
 		return ignoreSyntheticFields;
 	}
 
-	public boolean isFixedFieldTypes () {
+	public boolean getFixedFieldTypes () {
 		return fixedFieldTypes;
 	}
 
-	public boolean isUseAsm () {
-		return useAsm;
-	}
-
-	public boolean isOptimizedGenerics () {
+	public boolean getOptimizedGenerics () {
 		return optimizedGenerics;
 	}
 
-	public boolean isCopyTransient () {
+	public boolean getCopyTransient () {
 		return copyTransient;
 	}
 
-	public boolean isSerializeTransient () {
+	public boolean getSerializeTransient () {
 		return serializeTransient;
 	}
 
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerGenericsUtil.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerGenericsUtil.java	2018-12-20 09:20:46.846804266 +0100
@@ -251,7 +251,7 @@
 
 	/** Returns the first level of classes or interfaces for a generic type.
 	 * @return null if the specified type is not generic or its generic types are not classes. */
-	public static Class[] getGenerics (Type genericType, Kryo kryo) {
+	static public Class[] getGenerics (Type genericType, Kryo kryo) {
 		if (genericType instanceof GenericArrayType) {
 			Type componentType = ((GenericArrayType)genericType).getGenericComponentType();
 			if (componentType instanceof Class)
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializer.java	2018-12-20 09:20:46.846804266 +0100
@@ -26,7 +26,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
@@ -63,19 +62,19 @@
  * @see CompatibleFieldSerializer
  * @author Nathan Sweet <misc@n4te.com>
  * @author Roman Levenstein <romixlev@gmail.com> */
-public class FieldSerializer<T> extends Serializer<T> implements Comparator<FieldSerializer.CachedField> {
+public class FieldSerializer<T, C extends FieldSerializerConfig> extends Serializer<T>
+	implements Comparator<FieldSerializer.CachedField> {
 
 	final Kryo kryo;
 	final Class type;
 	/** type variables declared for this type */
 	final TypeVariable[] typeParameters;
 	final Class componentType;
-	protected final FieldSerializerConfig config;
+	protected final C config;
 	private CachedField[] fields = new CachedField[0];
 	private CachedField[] transientFields = new CachedField[0];
 	protected HashSet<CachedField> removedFields = new HashSet();
 	Object access;
-	private FieldSerializerUnsafeUtil unsafeUtil;
 
 	private FieldSerializerGenericsUtil genericsUtil;
 
@@ -89,37 +88,10 @@
 	/** If set, this serializer tries to use a variable length encoding for int and long fields */
 	private boolean varIntsEnabled;
 
-	/** If set, adjacent primitive fields are written in bulk This flag may only work with Oracle JVMs, because they layout
-	 * primitive fields in memory in such a way that primitive fields are grouped together. This option has effect only when used
-	 * with Unsafe-based FieldSerializer.
-	 * <p>
-	 * FIXME: Not all versions of Sun/Oracle JDK properly work with this option. Disable it for now. Later add dynamic checks to
-	 * see if this feature is supported by a current JDK version.
-	 * </p>
-	*/
-	private boolean useMemRegions = false;
-
 	private boolean hasObjectFields = false;
 
 	static CachedFieldFactory asmFieldFactory;
 	static CachedFieldFactory objectFieldFactory;
-	static CachedFieldFactory unsafeFieldFactory;
-
-	static boolean unsafeAvailable;
-	static Class<?> unsafeUtilClass;
-	static Method sortFieldsByOffsetMethod;
-
-	static {
-		try {
-			unsafeUtilClass = FieldSerializer.class.getClassLoader().loadClass("com.esotericsoftware.kryo.util.UnsafeUtil");
-			Method unsafeMethod = unsafeUtilClass.getMethod("unsafe");
-			sortFieldsByOffsetMethod = unsafeUtilClass.getMethod("sortFieldsByOffset", List.class);
-			Object unsafe = unsafeMethod.invoke(null);
-			if (unsafe != null) unsafeAvailable = true;
-		} catch (Throwable e) {
-			if (TRACE) trace("kryo", "sun.misc.Unsafe is unavailable.");
-		}
-	}
 
 	{
 		varIntsEnabled = true;
@@ -131,10 +103,11 @@
 	}
 
 	public FieldSerializer (Kryo kryo, Class type, Class[] generics) {
-		this(kryo, type, generics, kryo.getFieldSerializerConfig().clone());
+		this(kryo, type, generics, (C)new FieldSerializerConfig());
 	}
 
-	protected FieldSerializer (Kryo kryo, Class type, Class[] generics, FieldSerializerConfig config) {
+	public FieldSerializer (Kryo kryo, Class type, Class[] generics, C config) {
+		if (config == null) throw new IllegalArgumentException("config cannot be null.");
 		this.config = config;
 		this.kryo = kryo;
 		this.type = type;
@@ -145,7 +118,6 @@
 		else
 			this.componentType = null;
 		this.genericsUtil = new FieldSerializerGenericsUtil(this);
-		this.unsafeUtil = FieldSerializerUnsafeUtil.Factory.getInstance(this);
 		this.annotationsUtil = new FieldSerializerAnnotationsUtil(this);
 		rebuildCachedFields();
 	}
@@ -170,7 +142,7 @@
 
 		hasObjectFields = false;
 
-		if (config.isOptimizedGenerics()) {
+		if (config.getOptimizedGenerics()) {
 			// For generic classes, generate a mapping from type variable names to the concrete types
 			// This mapping is the same for the whole class.
 			Generics genScope = genericsUtil.buildGenericsScope(type, generics);
@@ -201,16 +173,6 @@
 
 			ObjectMap context = kryo.getContext();
 
-			// Sort fields by their offsets
-			if (useMemRegions && !config.isUseAsm() && unsafeAvailable) {
-				try {
-					Field[] allFieldsArray = (Field[])sortFieldsByOffsetMethod.invoke(null, allFields);
-					allFields = Arrays.asList(allFieldsArray);
-				} catch (Exception e) {
-					throw new RuntimeException("Cannot invoke UnsafeUtil.sortFieldsByOffset()", e);
-				}
-			}
-
 			// TODO: useAsm is modified as a side effect, this should be pulled out of buildValidFields
 			// Build a list of valid non-transient fields
 			validFields = buildValidFields(false, allFields, context, useAsm);
@@ -218,7 +180,7 @@
 			validTransientFields = buildValidFields(true, allFields, context, useAsm);
 
 			// Use ReflectASM for any public fields.
-			if (config.isUseAsm() && !Util.IS_ANDROID && Modifier.isPublic(type.getModifiers()) && useAsm.indexOf(1) != -1) {
+			if (!Util.isAndroid && Modifier.isPublic(type.getModifiers()) && useAsm.indexOf(1) != -1) {
 				try {
 					access = FieldAccess.get(type);
 				} catch (RuntimeException ignored) {
@@ -275,10 +237,10 @@
 			int modifiers = field.getModifiers();
 			if (Modifier.isTransient(modifiers) != transientFields) continue;
 			if (Modifier.isStatic(modifiers)) continue;
-			if (field.isSynthetic() && config.isIgnoreSyntheticFields()) continue;
+			if (field.isSynthetic() && config.getIgnoreSyntheticFields()) continue;
 
 			if (!field.isAccessible()) {
-				if (!config.isSetFieldsAsAccessible()) continue;
+				if (!config.getSetFieldsAsAccessible()) continue;
 				try {
 					field.setAccessible(true);
 				} catch (AccessControlException ex) {
@@ -292,29 +254,24 @@
 			result.add(field);
 
 			// BOZO - Must be public?
-			useAsm
-				.add(!Modifier.isFinal(modifiers) && Modifier.isPublic(modifiers) && Modifier.isPublic(field.getType().getModifiers())
-					? 1 : 0);
+			useAsm.add(
+				!Modifier.isFinal(modifiers) && Modifier.isPublic(modifiers) && Modifier.isPublic(field.getType().getModifiers()) ? 1
+					: 0);
 		}
 		return result;
 	}
 
 	private void createCachedFields (IntArray useAsm, List<Field> validFields, List<CachedField> cachedFields, int baseIndex) {
-
-		if (config.isUseAsm() || !useMemRegions) {
 			for (int i = 0, n = validFields.size(); i < n; i++) {
 				Field field = validFields.get(i);
 				int accessIndex = -1;
 				if (access != null && useAsm.get(baseIndex + i) == 1) accessIndex = ((FieldAccess)access).getIndex(field.getName());
 				cachedFields.add(newCachedField(field, cachedFields.size(), accessIndex));
 			}
-		} else {
-			unsafeUtil.createUnsafeCacheFieldsAndRegions(validFields, cachedFields, baseIndex, useAsm);
-		}
 	}
 
 	public void setGenerics (Kryo kryo, Class[] generics) {
-		if (!config.isOptimizedGenerics()) return;
+		if (!config.getOptimizedGenerics()) return;
 		this.generics = generics;
 		if (typeParameters != null && typeParameters.length > 0) {
 			// There is no need to rebuild all cached fields from scratch.
@@ -336,10 +293,10 @@
 
 	CachedField newCachedField (Field field, int fieldIndex, int accessIndex) {
 		Class[] fieldClass = new Class[] {field.getType()};
-		Type fieldGenericType = (config.isOptimizedGenerics()) ? field.getGenericType() : null;
+		Type fieldGenericType = (config.getOptimizedGenerics()) ? field.getGenericType() : null;
 		CachedField cachedField;
 
-		if (!config.isOptimizedGenerics() || fieldGenericType == fieldClass[0]) {
+		if (!config.getOptimizedGenerics() || fieldGenericType == fieldClass[0]) {
 			// For optimized generics this is a field without generic type parameters
 			if (TRACE) trace("kryo", "Field " + field.getName() + ": " + fieldClass[0]);
 			cachedField = newMatchingCachedField(field, accessIndex, fieldClass[0], fieldGenericType, null);
@@ -353,18 +310,13 @@
 
 		cachedField.field = field;
 		cachedField.varIntsEnabled = varIntsEnabled;
-
-		if (!config.isUseAsm()) {
-			cachedField.offset = unsafeUtil.getObjectFieldOffset(field);
-		}
-
 		cachedField.access = (FieldAccess)access;
 		cachedField.accessIndex = accessIndex;
-		cachedField.canBeNull = config.isFieldsCanBeNull() && !fieldClass[0].isPrimitive()
+		cachedField.canBeNull = config.getFieldsCanBeNull() && !fieldClass[0].isPrimitive()
 			&& !field.isAnnotationPresent(NotNull.class);
 
 		// Always use the same serializer for this field if the field's class is final.
-		if (kryo.isFinal(fieldClass[0]) || config.isFixedFieldTypes()) cachedField.valueClass = fieldClass[0];
+		if (kryo.isFinal(fieldClass[0]) || config.getFixedFieldTypes()) cachedField.valueClass = fieldClass[0];
 
 		return cachedField;
 	}
@@ -374,11 +326,9 @@
 		CachedField cachedField;
 		if (accessIndex != -1) {
 			cachedField = getAsmFieldFactory().createCachedField(fieldClass, field, this);
-		} else if (!config.isUseAsm()) {
-			cachedField = getUnsafeFieldFactory().createCachedField(fieldClass, field, this);
 		} else {
 			cachedField = getObjectFieldFactory().createCachedField(fieldClass, field, this);
-			if (config.isOptimizedGenerics()) {
+			if (config.getOptimizedGenerics()) {
 				if (fieldGenerics != null)
 					((ObjectField)cachedField).generics = fieldGenerics;
 				else if (fieldGenericType != null) {
@@ -401,21 +351,6 @@
 		return objectFieldFactory;
 	}
 
-	private CachedFieldFactory getUnsafeFieldFactory () {
-		// Use reflection to load UnsafeFieldFactory, so that there is no explicit dependency
-		// on anything using Unsafe. This is required to make FieldSerializer work on those
-		// platforms that do not support sun.misc.Unsafe properly.
-		if (unsafeFieldFactory == null) {
-			try {
-				unsafeFieldFactory = (CachedFieldFactory)this.getClass().getClassLoader()
-					.loadClass("com.esotericsoftware.kryo.serializers.UnsafeCachedFieldFactory").newInstance();
-			} catch (Exception e) {
-				throw new RuntimeException("Cannot create UnsafeFieldFactory", e);
-			}
-		}
-		return unsafeFieldFactory;
-	}
-
 	public int compare (CachedField o1, CachedField o2) {
 		// Fields are sorted by alpha so the order of the data is known.
 		return getCachedFieldName(o1).compareTo(getCachedFieldName(o2));
@@ -454,13 +389,6 @@
 		rebuildCachedFields();
 	}
 
-	/** Controls whether ASM should be used. Calling this method resets the {@link #getFields() cached fields}.
-	 * @param setUseAsm If true, ASM will be used for fast serialization. If false, Unsafe will be used (default) */
-	public void setUseAsm (boolean setUseAsm) {
-		config.setUseAsm(setUseAsm);
-		rebuildCachedFields();
-	}
-
 	// Enable/disable copying of transient fields
 	public void setCopyTransient (boolean setCopyTransient) {
 		config.setCopyTransient(setCopyTransient);
@@ -491,7 +419,7 @@
 	public void write (Kryo kryo, Output output, T object) {
 		if (TRACE) trace("kryo", "FieldSerializer.write fields of class: " + object.getClass().getName());
 
-		if (config.isOptimizedGenerics()) {
+		if (config.getOptimizedGenerics()) {
 			if (typeParameters != null && generics != null) {
 				// Rebuild fields info. It may result in rebuilding the genericScope
 				rebuildCachedFields();
@@ -508,12 +436,12 @@
 			fields[i].write(output, object);
 
 		// Serialize transient fields
-		if (config.isSerializeTransient()) {
+		if (config.getSerializeTransient()) {
 			for (int i = 0, n = transientFields.length; i < n; i++)
 				transientFields[i].write(output, object);
 		}
 
-		if (config.isOptimizedGenerics() && genericsScope != null) {
+		if (config.getOptimizedGenerics() && genericsScope != null) {
 			// Pop the scope for generics
 			kryo.getGenericsResolver().popScope();
 		}
@@ -522,7 +450,7 @@
 	public T read (Kryo kryo, Input input, Class<T> type) {
 		try {
 
-			if (config.isOptimizedGenerics()) {
+			if (config.getOptimizedGenerics()) {
 				if (typeParameters != null && generics != null) {
 					// Rebuild fields info. It may result in rebuilding the
 					// genericScope
@@ -543,13 +471,13 @@
 				fields[i].read(input, object);
 
 			// De-serialize transient fields
-			if (config.isSerializeTransient()) {
+			if (config.getSerializeTransient()) {
 				for (int i = 0, n = transientFields.length; i < n; i++)
 					transientFields[i].read(input, object);
 			}
 			return object;
 		} finally {
-			if (config.isOptimizedGenerics() && genericsScope != null && kryo.getGenericsResolver() != null) {
+			if (config.getOptimizedGenerics() && genericsScope != null && kryo.getGenericsResolver() != null) {
 				// Pop the scope for generics
 				kryo.getGenericsResolver().popScope();
 			}
@@ -649,20 +577,12 @@
 		return kryo;
 	}
 
-	public boolean getUseAsmEnabled () {
-		return config.isUseAsm();
-	}
-
-	public boolean getUseMemRegions () {
-		return useMemRegions;
-	}
-
 	public boolean getCopyTransient () {
-		return config.isCopyTransient();
+		return config.getCopyTransient();
 	}
 
 	public boolean getSerializeTransient () {
-		return config.isSerializeTransient();
+		return config.getSerializeTransient();
 	}
 
 	/** Used by {@link #copy(Kryo, Object)} to create the new object. This can be overridden to customize object creation, eg to
@@ -676,7 +596,7 @@
 		kryo.reference(copy);
 
 		// Copy transient fields
-		if (config.isCopyTransient()) {
+		if (config.getCopyTransient()) {
 			for (int i = 0, n = transientFields.length; i < n; i++)
 				transientFields[i].copy(original, copy);
 		}
@@ -691,15 +611,18 @@
 		return genericsScope;
 	}
 
+	public C getConfig () {
+		return config;
+	}
+
 	/** Controls how a field will be serialized. */
-	public static abstract class CachedField<X> {
+	static public abstract class CachedField<X> {
 		Field field;
 		FieldAccess access;
 		Class valueClass;
 		Serializer serializer;
 		boolean canBeNull;
 		int accessIndex = -1;
-		long offset = -1;
 		boolean varIntsEnabled = true;
 
 		/** @param valueClass The concrete class of the values for this field. This saves 1-2 bytes. The serializer registered for
@@ -744,7 +667,7 @@
 		abstract public void copy (Object original, Object copy);
 	}
 
-	public static interface CachedFieldFactory {
+	static public interface CachedFieldFactory {
 		public CachedField createCachedField (Class fieldClass, Field field, FieldSerializer ser);
 	}
 
@@ -782,12 +704,8 @@
 	@Retention(RetentionPolicy.RUNTIME)
 	@Target(ElementType.FIELD)
 	public @interface Bind {
-
 		/** Value.
-		 * 
 		 * @return the class<? extends serializer> used for this field */
-		@SuppressWarnings("rawtypes")
 		Class<? extends Serializer> value();
-
 	}
 }
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerUnsafeUtilImpl.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerUnsafeUtilImpl.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,137 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.serializers;
-
-import static com.esotericsoftware.kryo.util.UnsafeUtil.*;
-import static com.esotericsoftware.minlog.Log.*;
-
-import java.lang.reflect.Field;
-import java.util.List;
-
-import com.esotericsoftware.kryo.serializers.FieldSerializer.CachedField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeRegionField;
-import com.esotericsoftware.kryo.util.IntArray;
-import com.esotericsoftware.reflectasm.FieldAccess;
-
-/* Helper class for implementing FieldSerializer using Unsafe-based approach. 
- * @author Roman Levenstein <romixlev@gmail.com> */
-final class FieldSerializerUnsafeUtilImpl implements FieldSerializerUnsafeUtil {
-	private FieldSerializer serializer;
-
-	public FieldSerializerUnsafeUtilImpl (FieldSerializer serializer) {
-		this.serializer = serializer;
-	}
-
-	public void createUnsafeCacheFieldsAndRegions (List<Field> validFields, List<CachedField> cachedFields, int baseIndex,
-		IntArray useAsm) {
-		// Find adjacent fields of primitive types
-		long startPrimitives = 0;
-		long endPrimitives = 0;
-		boolean lastWasPrimitive = false;
-		int primitiveLength = 0;
-		int lastAccessIndex = -1;
-		Field lastField = null;
-		long fieldOffset = -1;
-		long fieldEndOffset = -1;
-		long lastFieldEndOffset = -1;
-
-		for (int i = 0, n = validFields.size(); i < n; i++) {
-			Field field = validFields.get(i);
-
-			int accessIndex = -1;
-			if (serializer.access != null && useAsm.get(baseIndex + i) == 1)
-				accessIndex = ((FieldAccess)serializer.access).getIndex(field.getName());
-
-			fieldOffset = unsafe().objectFieldOffset(field);
-			fieldEndOffset = fieldOffset + fieldSizeOf(field.getType());
-
-			if (!field.getType().isPrimitive() && lastWasPrimitive) {
-				// This is not a primitive field. Therefore, it marks
-				// the end of a region of primitive fields
-				endPrimitives = lastFieldEndOffset;
-				lastWasPrimitive = false;
-				if (primitiveLength > 1) {
-					if (TRACE) trace("kryo",
-						"Class " + serializer.getType().getName() + ". Found a set of consecutive primitive fields. Number of fields = "
-							+ primitiveLength + ". Byte length = " + (endPrimitives - startPrimitives) + " Start offset = "
-							+ startPrimitives + " endOffset=" + endPrimitives);
-					// TODO: register a region instead of a field
-					CachedField cf = new UnsafeRegionField(startPrimitives, (endPrimitives - startPrimitives));
-					cf.field = lastField;
-					cachedFields.add(cf);
-				} else {
-					if (lastField != null)
-						cachedFields.add(serializer.newCachedField(lastField, cachedFields.size(), lastAccessIndex));
-				}
-				cachedFields.add(serializer.newCachedField(field, cachedFields.size(), accessIndex));
-			} else if (!field.getType().isPrimitive()) {
-				cachedFields.add(serializer.newCachedField(field, cachedFields.size(), accessIndex));
-			} else if (!lastWasPrimitive) {
-				// If previous field was non primitive, it marks a start
-				// of a region of primitive fields
-				startPrimitives = fieldOffset;
-				lastWasPrimitive = true;
-				primitiveLength = 1;
-			} else {
-				primitiveLength++;
-			}
-
-			lastAccessIndex = accessIndex;
-			lastField = field;
-			lastFieldEndOffset = fieldEndOffset;
-		}
-
-		if (!serializer.getUseAsmEnabled() && serializer.getUseMemRegions() && lastWasPrimitive) {
-			endPrimitives = lastFieldEndOffset;
-			if (primitiveLength > 1) {
-				if (TRACE) {
-					trace("kryo",
-						"Class " + serializer.getType().getName() + ". Found a set of consecutive primitive fields. Number of fields = "
-							+ primitiveLength + ". Byte length = " + (endPrimitives - startPrimitives) + " Start offset = "
-							+ startPrimitives + " endOffset=" + endPrimitives);
-				}
-				// register a region instead of a field
-				CachedField cf = new UnsafeRegionField(startPrimitives, (endPrimitives - startPrimitives));
-				cf.field = lastField;
-				cachedFields.add(cf);
-			} else {
-				if (lastField != null) cachedFields.add(serializer.newCachedField(lastField, cachedFields.size(), lastAccessIndex));
-			}
-		}
-	}
-
-	/** Returns the in-memory size of a field which has a given class */
-	private int fieldSizeOf (Class<?> clazz) {
-		if (clazz == int.class || clazz == float.class) return 4;
-
-		if (clazz == long.class || clazz == double.class) return 8;
-
-		if (clazz == byte.class || clazz == boolean.class) return 1;
-
-		if (clazz == short.class || clazz == char.class) return 2;
-
-		// Everything else is a reference to an object, i.e. an address
-		return unsafe().addressSize();
-	}
-
-	public long getObjectFieldOffset (Field field) {
-		return unsafe().objectFieldOffset(field);
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerUnsafeUtil.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/FieldSerializerUnsafeUtil.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,63 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.serializers;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.util.List;
-
-import com.esotericsoftware.kryo.serializers.FieldSerializer.CachedField;
-import com.esotericsoftware.kryo.util.IntArray;
-
-/* Helper interface for using Unsafe-based operations inside FieldSerializer. 
- * @author Roman Levenstein <romixlev@gmail.com> */
-interface FieldSerializerUnsafeUtil {
-
-	/** Use Unsafe-based information about fields layout in memory to build a list of cached fields and memory regions representing
-	 * consecutive fields in memory */
-	public abstract void createUnsafeCacheFieldsAndRegions (List<Field> validFields, List<CachedField> cachedFields, int baseIndex,
-		IntArray useAsm);
-
-	public abstract long getObjectFieldOffset (Field field);
-
-	static class Factory {
-		static Constructor<FieldSerializerUnsafeUtil> fieldSerializerUnsafeUtilConstructor;
-
-		static {
-			try {
-				fieldSerializerUnsafeUtilConstructor = (Constructor<FieldSerializerUnsafeUtil>)FieldSerializer.class.getClassLoader()
-					.loadClass("com.esotericsoftware.kryo.serializers.FieldSerializerUnsafeUtilImpl")
-					.getConstructor(FieldSerializer.class);
-			} catch (Throwable e) {
-
-			}
-		}
-
-		static FieldSerializerUnsafeUtil getInstance (FieldSerializer serializer) {
-			if (fieldSerializerUnsafeUtilConstructor != null) {
-				try {
-					return fieldSerializerUnsafeUtilConstructor.newInstance(serializer);
-				} catch (Exception e) {
-				}
-			}
-			return null;
-		}
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/JavaSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/JavaSerializer.java	2018-12-20 09:20:46.846804266 +0100
@@ -69,14 +69,11 @@
 		}
 	}
 
-	/**
-	 * ${@link ObjectInputStream} uses the last user-defined ${@link ClassLoader} which may not be the correct one.
-		* This is a known Java issue and is often solved by using a specific class loader.
-	 * See:
+	/** ${@link ObjectInputStream} uses the last user-defined ${@link ClassLoader} which may not be the correct one. This is a
+	 * known Java issue and is often solved by using a specific class loader. See:
 	 * https://github.com/apache/spark/blob/v1.6.3/streaming/src/main/scala/org/apache/spark/streaming/Checkpoint.scala#L154
-	 * https://issues.apache.org/jira/browse/GROOVY-1627
-	 */
-	private static class ObjectInputStreamWithKryoClassLoader extends ObjectInputStream {
+	 * https://issues.apache.org/jira/browse/GROOVY-1627 */
+	static private class ObjectInputStreamWithKryoClassLoader extends ObjectInputStream {
 		private final ClassLoader loader;
 
 		ObjectInputStreamWithKryoClassLoader(InputStream in, Kryo kryo) throws IOException {
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/MapSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/MapSerializer.java	2018-12-20 09:20:46.846804266 +0100
@@ -181,36 +181,27 @@
 	@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-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/OptionalSerializers.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/OptionalSerializers.java	2018-12-20 09:20:46.846804266 +0100
@@ -34,8 +34,7 @@
 /** Serializers for {@link Optional}, {@link OptionalInt}, {@link OptionalLong} and {@link OptionalDouble}. Are added as default
  * serializers for java >= 1.8. */
 public final class OptionalSerializers {
-
-	public static void addDefaultSerializers (Kryo kryo) {
+	static public void addDefaultSerializers (Kryo kryo) {
 		if (isClassAvailable("java.util.Optional")) kryo.addDefaultSerializer(Optional.class, new OptionalSerializer());
 		if (isClassAvailable("java.util.OptionalInt")) kryo.addDefaultSerializer(OptionalInt.class, new OptionalIntSerializer());
 		if (isClassAvailable("java.util.OptionalLong")) kryo.addDefaultSerializer(OptionalLong.class, new OptionalLongSerializer());
@@ -43,8 +42,7 @@
 			kryo.addDefaultSerializer(OptionalDouble.class, new OptionalDoubleSerializer());
 	}
 
-	private static class OptionalSerializer extends Serializer<Optional> {
-
+	static class OptionalSerializer extends Serializer<Optional> {
 		{
 			setAcceptsNull(false);
 		}
@@ -70,7 +68,7 @@
 		}
 	}
 
-	private static class OptionalIntSerializer extends Serializer<OptionalInt> {
+	static class OptionalIntSerializer extends Serializer<OptionalInt> {
 		{
 			setImmutable(true);
 		}
@@ -86,7 +84,7 @@
 		}
 	}
 
-	private static class OptionalLongSerializer extends Serializer<OptionalLong> {
+	static class OptionalLongSerializer extends Serializer<OptionalLong> {
 		{
 			setImmutable(true);
 		}
@@ -102,7 +100,7 @@
 		}
 	}
 
-	private static class OptionalDoubleSerializer extends Serializer<OptionalDouble> {
+	static class OptionalDoubleSerializer extends Serializer<OptionalDouble> {
 		{
 			setImmutable(true);
 		}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/TaggedFieldSerializerConfig.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/TaggedFieldSerializerConfig.java	2018-12-20 09:20:46.846804266 +0100
@@ -23,54 +23,32 @@
 
 /** Configuration for TaggedFieldSerializer instances. */
 public class TaggedFieldSerializerConfig extends FieldSerializerConfig {
+	boolean skipUnknownTags;
 
-	private boolean skipUnknownTags = false;
-
-	/** Set whether associated TaggedFieldSerializers should attempt to skip reading the data of unknown tags, rather
-	 * than throwing a KryoException. Data can be skipped if it was tagged with {@link TaggedFieldSerializer.Tag#annexed()}
-	 * set true. This enables forward compatibility.
+	/** Set whether associated TaggedFieldSerializers should attempt to skip reading the data of unknown tags, rather than throwing
+	 * a KryoException. Data can be skipped if it was tagged with {@link TaggedFieldSerializer.Tag#annexed()} set true. This
+	 * enables forward compatibility.
 	 * <p>
 	 * This setting is false by default.
 	 * </p>
 	 *
-	 * @param skipUnknownTags If true, unknown field tags will be skipped, with the assumption that they are future
-	 *                          tagged values with {@link TaggedFieldSerializer.Tag#annexed()} set true. If false
-	 *                          KryoException will be thrown whenever unknown tags are encountered. */
+	 * @param skipUnknownTags If true, unknown field tags will be skipped, with the assumption that they are future tagged values
+	 *           with {@link TaggedFieldSerializer.Tag#annexed()} set true. If false KryoException will be thrown whenever unknown
+	 *           tags are encountered. */
 	public void setSkipUnknownTags (boolean skipUnknownTags) {
 		this.skipUnknownTags = skipUnknownTags;
 		if (TRACE) trace("kryo.TaggedFieldSerializerConfig", "setSkipUnknownTags: " + skipUnknownTags);
 	}
 
-	/**
-	 * Whether the TaggedFieldSerializers should attempt to skip reading the data of unknown tags, rather than
-	 * throwing a KryoException. The data may only be skipped if the later version of the application which created the
-	 * data set those unknown tags with {@link TaggedFieldSerializer.Tag#annexed()} true.
-	 * See {@link #setSkipUnknownTags(boolean)}.
-	 */
-	public boolean isSkipUnknownTags () {
+	/** Whether the TaggedFieldSerializers should attempt to skip reading the data of unknown tags, rather than throwing a
+	 * KryoException. The data may only be skipped if the later version of the application which created the data set those unknown
+	 * tags with {@link TaggedFieldSerializer.Tag#annexed()} true. See {@link #setSkipUnknownTags(boolean)}. */
+	public boolean getSkipUnknownTags () {
 		return skipUnknownTags;
 	}
 
-	/**
-	 * @deprecated The {@code ignoreUnknownTags} feature is deprecated and the functionality is disabled, as it is an
-	 * invalid means of preserving forward compatibility. See {@link #setSkipUnknownTags(boolean)} for an alternate means.
-	 * @param ignoreUnknownTags This setting is now ignored.
-	 */
-	@Deprecated
-	public void setIgnoreUnknownTags (boolean ignoreUnknownTags) {
-	}
-
-	/**
-	 * @deprecated See {@link #setIgnoreUnknownTags(boolean)} for information.
-	 * @return Always returns false, as this feature has been disabled.
-	 */
-	@Deprecated
-	public boolean isIgnoreUnknownTags () {
-		return false;
-	}
-
 	@Override
-	protected TaggedFieldSerializerConfig clone () {
+	public TaggedFieldSerializerConfig clone () {
 		return (TaggedFieldSerializerConfig)super.clone();
 	}
 }
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/TaggedFieldSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/TaggedFieldSerializer.java	2018-12-20 09:20:46.846804266 +0100
@@ -45,48 +45,28 @@
  * provides more flexibility for classes to evolve. The downside is that it has a small amount of additional overhead compared to
  * VersionFieldSerializer (an additional varint per field). 
  * <p>
- * Forward compatibility is optionally supported by enabling {@link #setSkipUnknownTags(boolean)}, which allows it to
- * skip reading unknown tagged fields, which are presumably new fields added in future versions of an application. The
- * data is only forward compatible if the newly added fields are tagged with {@link TaggedFieldSerializer.Tag#annexed()}
- * set true, which comes with the cost of chunked encoding. When annexed fields are encountered during the read or write
- * process of an object, a buffer is allocated to perform the chunked encoding.
+ * Forward compatibility is optionally supported by enabling {@link TaggedFieldSerializerConfig#setSkipUnknownTags(boolean)},
+ * which allows it to skip reading unknown tagged fields, which are presumably new fields added in future versions of an
+ * application. The data is only forward compatible if the newly added fields are tagged with
+ * {@link TaggedFieldSerializer.Tag#annexed()} set true, which comes with the cost of chunked encoding. When annexed fields are
+ * encountered during the read or write process of an object, a buffer is allocated to perform the chunked encoding.
  * <p>
- * Tag values must be entirely unique, even among a class and its superclass(es). An IllegalArgumentException will be
- * thrown by {@link Kryo#register(Class)} (and its overloads) if duplicate Tag values are encountered.
+ * Tag values must be entirely unique, even among a class and its superclass(es). An IllegalArgumentException will be thrown by
+ * {@link Kryo#register(Class)} (and its overloads) if duplicate Tag values are encountered.
  * @see VersionFieldSerializer
  * @author Nathan Sweet <misc@n4te.com> */
-public class TaggedFieldSerializer<T> extends FieldSerializer<T> {
+public class TaggedFieldSerializer<T> extends FieldSerializer<T, TaggedFieldSerializerConfig> {
 	private int[] tags;
 	private int writeFieldCount;
 	private boolean[] deprecated;
 	private boolean[] annexed;
 
 	public TaggedFieldSerializer (Kryo kryo, Class type) {
-		super(kryo, type, null, kryo.getTaggedFieldSerializerConfig().clone());
+		super(kryo, type, null, new TaggedFieldSerializerConfig());
 	}
 
-	/** Set whether TaggedFieldSerializer should attempt to skip reading the data of unknown tags, rather than throwing a
-	 * KryoException. Data can be skipped if it is tagged with {@link Tag#annexed()} set true. This enables forward
-	 * compatibility.
-	 * <p>
-	 * By default, this setting matches the value of {@link TaggedFieldSerializerConfig#isSkipUnknownTags()} in
-	 * {@link Kryo#getTaggedFieldSerializerConfig()}, which is false by default.
-	 * </p>
-	 *
-	 * @param skipUnknownTags If true, unknown field tags will be skipped, with the assumption that they are future
-	 *                          tagged values with {@link Tag#annexed()} set true. If false KryoException will be thrown
-	 *                          whenever unknown tags are encountered. */
-	public void setSkipUnknownTags (boolean skipUnknownTags) {
-		((TaggedFieldSerializerConfig)config).setSkipUnknownTags(skipUnknownTags);
-		rebuildCachedFields();
-	}
-
-	/**
-	 * @return Whether the TaggedFieldSerializers should attempt to skip reading the data of unknown tags, rather than
-	 * throwing a KryoException. See {@link #setSkipUnknownTags(boolean)}.
-	 */
-	public boolean isSkipUnknownTags() {
-		return ((TaggedFieldSerializerConfig)config).isSkipUnknownTags();
+	public TaggedFieldSerializer (Kryo kryo, Class type, TaggedFieldSerializerConfig config) {
+		super(kryo, type, null, config);
 	}
 
 	protected void initializeCachedFields () {
@@ -111,13 +91,13 @@
 			Field field = fields[i].getField();
 			tags[i] = field.getAnnotation(Tag.class).value();
 			if (i > 0 && tags[i] == tags[i-1]) // This check relies on fields having been sorted
-				throw new KryoException(String.format("The fields [%s] and [%s] both have a Tag value of %d.", field, fields[i-1].getField(), tags[i]));
+				throw new KryoException(
+					String.format("The fields [%s] and [%s] both have a Tag value of %d.", field, fields[i - 1].getField(), tags[i]));
 			if (field.getAnnotation(Deprecated.class) != null) {
 				deprecated[i] = true;
 				writeFieldCount--;
 			}
-			if (field.getAnnotation(Tag.class).annexed())
-				annexed[i] = true;
+			if (field.getAnnotation(Tag.class).annexed()) annexed[i] = true;
 		}
 
 		this.removedFields.clear();
@@ -142,8 +122,7 @@
 			if (deprecated[i]) continue;
 			output.writeVarInt(tags[i], true);
 			if (annexed[i]){
-				if (outputChunked == null)
-					outputChunked = new OutputChunked(output, 1024);
+				if (outputChunked == null) outputChunked = new OutputChunked(output, 1024);
 				fields[i].write(outputChunked, object);
 				outputChunked.endChunks();
 			} else {
@@ -172,11 +151,11 @@
 				}
 			}
 			if (cachedField == null) {
-				if (isSkipUnknownTags()) {
+				if (config.skipUnknownTags) {
 					if (inputChunked == null) inputChunked = new InputChunked(input, 1024);
 					inputChunked.nextChunks(); // assume future annexed field and skip
-					if (TRACE) trace(String.format("Unknown field tag: %d (%s) encountered. Assuming a future annexed " +
-									"tag with chunked encoding and skipping.", tag, getType().getName()));
+					if (TRACE) trace(String.format("Unknown field tag: %d (%s) encountered. Assuming a future annexed "
+						+ "tag with chunked encoding and skipping.", tag, getType().getName()));
 				} else
 					throw new KryoException("Unknown field tag: " + tag + " (" + getType().getName() + ")");
 			} else if (isAnnexed){
@@ -190,7 +169,7 @@
 		return object;
 	}
 
-	private static final Comparator<CachedField> TAGGED_VALUE_COMPARATOR = new Comparator<CachedField>() {
+	static private final Comparator<CachedField> TAGGED_VALUE_COMPARATOR = new Comparator<CachedField>() {
 		public int compare (CachedField o1, CachedField o2) {
 			return o1.getField().getAnnotation(Tag.class).value() - o2.getField().getAnnotation(Tag.class).value();
 		}
@@ -201,26 +180,9 @@
 	@Target(ElementType.FIELD)
 	public @interface Tag {
 		int value();
-		/** If true, the field is serialized with chunked encoding and is forward compatible, meaning safe to read in
-		 * iterations of the class without it if {@link #isSkipUnknownTags()}. */
-		boolean annexed() default false;
-	}
 
-	/**
-	 * @deprecated The {@code ignoreUnknownTags} feature is deprecated and the functionality is disabled, as it is an
-	 * invalid means of preserving forward compatibility. See {@link #setSkipUnknownTags(boolean)} for an alternate means.
-	 * @param ignoreUnknownTags This setting is now ignored.
-	 */
-	@Deprecated
-	public void setIgnoreUnknownTags (boolean ignoreUnknownTags){
-	}
-
-	/**
-	 * @deprecated See {@link #setIgnoreUnknownTags(boolean)} for information.
-	 * @return Always returns false, as this feature has been disabled.
-	 */
-	@Deprecated
-	public boolean isIgnoreUnkownTags() {
-		return false;
+		/** If true, the field is serialized with chunked encoding and is forward compatible, meaning safe to read in iterations of
+		 * the class without it if {@link TaggedFieldSerializerConfig#getSkipUnknownTags()}. */
+		boolean annexed() default false;
 	}
 }
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/TimeSerializers.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/TimeSerializers.java	2018-12-20 09:20:46.846804266 +0100
@@ -48,8 +48,7 @@
  *
  * Implementation note: All serialization is inspired by oracles java.time.Ser. */
 public final class TimeSerializers {
-
-	public static void addDefaultSerializers (Kryo kryo) {
+	static public void addDefaultSerializers (Kryo kryo) {
 		if (isClassAvailable("java.time.Duration")) kryo.addDefaultSerializer(Duration.class, new DurationSerializer());
 		if (isClassAvailable("java.time.Instant")) kryo.addDefaultSerializer(Instant.class, new InstantSerializer());
 		if (isClassAvailable("java.time.LocalDate")) kryo.addDefaultSerializer(LocalDate.class, new LocalDateSerializer());
@@ -69,7 +68,7 @@
 		if (isClassAvailable("java.time.Period")) kryo.addDefaultSerializer(Period.class, new PeriodSerializer());
 	}
 
-	private static class DurationSerializer extends Serializer<Duration> {
+	static class DurationSerializer extends Serializer<Duration> {
 		{
 			setImmutable(true);
 		}
@@ -86,7 +85,7 @@
 		}
 	}
 
-	private static class InstantSerializer extends Serializer<Instant> {
+	static class InstantSerializer extends Serializer<Instant> {
 		{
 			setImmutable(true);
 		}
@@ -103,7 +102,7 @@
 		}
 	}
 
-	private static class LocalDateSerializer extends Serializer<LocalDate> {
+	static class LocalDateSerializer extends Serializer<LocalDate> {
 		{
 			setImmutable(true);
 		}
@@ -130,7 +129,7 @@
 		}
 	}
 
-	private static class LocalDateTimeSerializer extends Serializer<LocalDateTime> {
+	static class LocalDateTimeSerializer extends Serializer<LocalDateTime> {
 		{
 			setImmutable(true);
 		}
@@ -147,7 +146,7 @@
 		}
 	}
 
-	private static class LocalTimeSerializer extends Serializer<LocalTime> {
+	static class LocalTimeSerializer extends Serializer<LocalTime> {
 		{
 			setImmutable(true);
 		}
@@ -206,7 +205,7 @@
 		}
 	}
 
-	private static class ZoneOffsetSerializer extends Serializer<ZoneOffset> {
+	static class ZoneOffsetSerializer extends Serializer<ZoneOffset> {
 		{
 			setImmutable(true);
 		}
@@ -234,7 +233,7 @@
 		}
 	}
 
-	private static class ZoneIdSerializer extends Serializer<ZoneId> {
+	static class ZoneIdSerializer extends Serializer<ZoneId> {
 		{
 			setImmutable(true);
 		}
@@ -257,7 +256,7 @@
 		}
 	}
 
-	private static class OffsetTimeSerializer extends Serializer<OffsetTime> {
+	static class OffsetTimeSerializer extends Serializer<OffsetTime> {
 		{
 			setImmutable(true);
 		}
@@ -274,7 +273,7 @@
 		}
 	}
 
-	private static class OffsetDateTimeSerializer extends Serializer<OffsetDateTime> {
+	static class OffsetDateTimeSerializer extends Serializer<OffsetDateTime> {
 		{
 			setImmutable(true);
 		}
@@ -293,7 +292,7 @@
 		}
 	}
 
-	private static class ZonedDateTimeSerializer extends Serializer<ZonedDateTime> {
+	static class ZonedDateTimeSerializer extends Serializer<ZonedDateTime> {
 		{
 			setImmutable(true);
 		}
@@ -312,7 +311,7 @@
 		}
 	}
 
-	private static class YearSerializer extends Serializer<Year> {
+	static class YearSerializer extends Serializer<Year> {
 		{
 			setImmutable(true);
 		}
@@ -326,7 +325,7 @@
 		}
 	}
 
-	private static class YearMonthSerializer extends Serializer<YearMonth> {
+	static class YearMonthSerializer extends Serializer<YearMonth> {
 		{
 			setImmutable(true);
 		}
@@ -343,7 +342,7 @@
 		}
 	}
 
-	private static class MonthDaySerializer extends Serializer<MonthDay> {
+	static class MonthDaySerializer extends Serializer<MonthDay> {
 		{
 			setImmutable(true);
 		}
@@ -360,7 +359,7 @@
 		}
 	}
 
-	private static class PeriodSerializer extends Serializer<Period> {
+	static class PeriodSerializer extends Serializer<Period> {
 		{
 			setImmutable(true);
 		}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/UnsafeCachedFieldFactory.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/UnsafeCachedFieldFactory.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,69 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.serializers;
-
-import java.lang.reflect.Field;
-
-import com.esotericsoftware.kryo.serializers.FieldSerializer.CachedField;
-import com.esotericsoftware.kryo.serializers.FieldSerializer.CachedFieldFactory;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeBooleanField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeByteField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeCharField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeDoubleField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeFloatField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeIntField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeLongField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeObjectField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeShortField;
-import com.esotericsoftware.kryo.serializers.UnsafeCacheFields.UnsafeStringField;
-
-class UnsafeCachedFieldFactory implements CachedFieldFactory {
-	public CachedField createCachedField (Class fieldClass, Field field, FieldSerializer ser) {
-		CachedField cachedField;
-		// Use Unsafe-based serializers
-		if (fieldClass.isPrimitive()) {
-			if (fieldClass == boolean.class)
-				cachedField = new UnsafeBooleanField(field);
-			else if (fieldClass == byte.class)
-				cachedField = new UnsafeByteField(field);
-			else if (fieldClass == char.class)
-				cachedField = new UnsafeCharField(field);
-			else if (fieldClass == short.class)
-				cachedField = new UnsafeShortField(field);
-			else if (fieldClass == int.class)
-				cachedField = new UnsafeIntField(field);
-			else if (fieldClass == long.class)
-				cachedField = new UnsafeLongField(field);
-			else if (fieldClass == float.class)
-				cachedField = new UnsafeFloatField(field);
-			else if (fieldClass == double.class)
-				cachedField = new UnsafeDoubleField(field);
-			else {
-				cachedField = new UnsafeObjectField(ser);
-			}
-		} else if (fieldClass == String.class
-			&& (!ser.kryo.getReferences() || !ser.kryo.getReferenceResolver().useReferences(String.class))) {
-			cachedField = new UnsafeStringField(field);
-		} else {
-			cachedField = new UnsafeObjectField(ser);
-		}
-		return cachedField;
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/UnsafeCacheFields.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/UnsafeCacheFields.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,326 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.serializers;
-
-import static com.esotericsoftware.kryo.util.UnsafeUtil.*;
-
-import java.lang.reflect.Field;
-
-import com.esotericsoftware.kryo.KryoException;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.io.UnsafeInput;
-import com.esotericsoftware.kryo.io.UnsafeMemoryInput;
-import com.esotericsoftware.kryo.io.UnsafeMemoryOutput;
-import com.esotericsoftware.kryo.io.UnsafeOutput;
-import com.esotericsoftware.kryo.serializers.FieldSerializer.CachedField;
-
-import sun.misc.Unsafe;
-
-/*** Implementations of sun.misc.Unsafe-based serializers for fields.
- * 
- * @author Roman Levenstein <romixlev@gmail.com> */
-class UnsafeCacheFields {
-
-	abstract static class UnsafeCachedField extends CachedField {
-		UnsafeCachedField (long offset) {
-			this.offset = offset;
-		}
-	}
-
-	final static class UnsafeIntField extends UnsafeCachedField {
-		public UnsafeIntField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			if (varIntsEnabled)
-				output.writeInt(unsafe().getInt(object, offset), false);
-			else
-				output.writeInt(unsafe().getInt(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			if (varIntsEnabled)
-				unsafe().putInt(object, offset, input.readInt(false));
-			else
-				unsafe().putInt(object, offset, input.readInt());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putInt(copy, offset, unsafe().getInt(original, offset));
-		}
-	}
-
-	final static class UnsafeFloatField extends UnsafeCachedField {
-		public UnsafeFloatField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			output.writeFloat(unsafe().getFloat(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			unsafe().putFloat(object, offset, input.readFloat());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putFloat(copy, offset, unsafe().getFloat(original, offset));
-		}
-	}
-
-	final static class UnsafeShortField extends UnsafeCachedField {
-		public UnsafeShortField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			output.writeShort(unsafe().getShort(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			unsafe().putShort(object, offset, input.readShort());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putShort(copy, offset, unsafe().getShort(original, offset));
-		}
-	}
-
-	final static class UnsafeByteField extends UnsafeCachedField {
-		public UnsafeByteField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			output.writeByte(unsafe().getByte(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			unsafe().putByte(object, offset, input.readByte());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putByte(copy, offset, unsafe().getByte(original, offset));
-		}
-	}
-
-	final static class UnsafeBooleanField extends UnsafeCachedField {
-		public UnsafeBooleanField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			output.writeBoolean(unsafe().getBoolean(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			unsafe().putBoolean(object, offset, input.readBoolean());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putBoolean(copy, offset, unsafe().getBoolean(original, offset));
-		}
-	}
-
-	final static class UnsafeCharField extends UnsafeCachedField {
-		public UnsafeCharField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			output.writeChar(unsafe().getChar(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			unsafe().putChar(object, offset, input.readChar());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putChar(copy, offset, unsafe().getChar(original, offset));
-		}
-	}
-
-	final static class UnsafeLongField extends UnsafeCachedField {
-		public UnsafeLongField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			if (varIntsEnabled)
-				output.writeLong(unsafe().getLong(object, offset), false);
-			else
-				output.writeLong(unsafe().getLong(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			if (varIntsEnabled)
-				unsafe().putLong(object, offset, input.readLong(false));
-			else
-				unsafe().putLong(object, offset, input.readLong());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putLong(copy, offset, unsafe().getLong(original, offset));
-		}
-	}
-
-	final static class UnsafeDoubleField extends UnsafeCachedField {
-		public UnsafeDoubleField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			output.writeDouble(unsafe().getDouble(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			unsafe().putDouble(object, offset, input.readDouble());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putDouble(copy, offset, unsafe().getDouble(original, offset));
-		}
-	}
-
-	final static class UnsafeStringField extends UnsafeCachedField {
-		public UnsafeStringField (Field f) {
-			super(unsafe().objectFieldOffset(f));
-		}
-
-		public void write (Output output, Object object) {
-			output.writeString((String)unsafe().getObject(object, offset));
-		}
-
-		public void read (Input input, Object object) {
-			unsafe().putObject(object, offset, input.readString());
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().putObject(copy, offset, unsafe().getObject(original, offset));
-		}
-	}
-
-	/** Helper class for doing bulk copies of memory regions containing adjacent primitive fields. Should be normally used only
-	 * with Unsafe streams to deliver best performance. */
-	final static class UnsafeRegionField extends UnsafeCachedField {
-		final long len;
-		static final boolean bulkReadsSupported = false;
-
-		public UnsafeRegionField (long offset, long len) {
-			super(offset);
-			this.len = len;
-		}
-
-		final public void write (Output output, Object object) {
-			if (output instanceof UnsafeOutput) {
-				UnsafeOutput unsafeOutput = (UnsafeOutput)output;
-				unsafeOutput.writeBytes(object, offset, len);
-			} else if (output instanceof UnsafeMemoryOutput) {
-				UnsafeMemoryOutput unsafeOutput = (UnsafeMemoryOutput)output;
-				unsafeOutput.writeBytes(object, offset, len);
-			} else {
-				long off;
-				Unsafe unsafe = unsafe();
-				for (off = offset; off < offset + len - 8; off += 8) {
-					output.writeLong(unsafe.getLong(object, off));
-				}
-
-				if (off < offset + len) {
-					for (; off < offset + len; ++off) {
-						output.write(unsafe.getByte(object, off));
-					}
-				}
-			}
-		}
-
-		final public void read (Input input, Object object) {
-			if (bulkReadsSupported && input instanceof UnsafeInput) {
-				UnsafeInput unsafeInput = (UnsafeInput)input;
-				unsafeInput.readBytes(object, offset, len);
-			} else if (bulkReadsSupported && input instanceof UnsafeMemoryInput) {
-				UnsafeMemoryInput unsafeInput = (UnsafeMemoryInput)input;
-				unsafeInput.readBytes(object, offset, len);
-			} else {
-				readSlow(input, object);
-			}
-		}
-
-		/*** This is a fall-back solution for the case that bulk reading of bytes into object memory is not supported.
-		 * Unfortunately, current Oracle JDKs do not allow for bulk reading in this style due to problems with GC.
-		 * 
-		 * @param input
-		 * @param object */
-		private void readSlow (Input input, Object object) {
-			long off;
-			Unsafe unsafe = unsafe();
-			for (off = offset; off < offset + len - 8; off += 8) {
-				unsafe.putLong(object, off, input.readLong());
-			}
-
-			if (off < offset + len) {
-				for (; off < offset + len; ++off) {
-					unsafe.putByte(object, off, input.readByte());
-				}
-			}
-		}
-
-		public void copy (Object original, Object copy) {
-			unsafe().copyMemory(original, offset, copy, offset, len);
-		}
-	}
-
-	final static class UnsafeObjectField extends ObjectField {
-		public UnsafeObjectField (FieldSerializer fieldSerializer) {
-			super(fieldSerializer);
-		}
-
-		public Object getField (Object object) throws IllegalArgumentException, IllegalAccessException {
-			if (offset >= 0) {
-				return unsafe().getObject(object, offset);
-			} else
-				throw new KryoException("Unknown offset");
-		}
-
-		public void setField (Object object, Object value) throws IllegalArgumentException, IllegalAccessException {
-			if (offset != -1)
-				unsafe().putObject(object, offset, value);
-			else
-				throw new KryoException("Unknown offset");
-		}
-
-		public void copy (Object original, Object copy) {
-			try {
-				if (offset != -1) {
-					unsafe().putObject(copy, offset, kryo.copy(unsafe().getObject(original, offset)));
-				} else
-					throw new KryoException("Unknown offset");
-			} catch (KryoException ex) {
-				ex.addTrace(this + " (" + type.getName() + ")");
-				throw ex;
-			} catch (RuntimeException runtimeEx) {
-				KryoException ex = new KryoException(runtimeEx);
-				ex.addTrace(this + " (" + type.getName() + ")");
-				throw ex;
-			}
-		}
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/VersionFieldSerializer.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/serializers/VersionFieldSerializer.java	2018-12-20 09:20:46.850804287 +0100
@@ -40,7 +40,7 @@
  * overhead (a single additional varint) compared to FieldSerializer. Forward compatibility is not supported.
  * @see TaggedFieldSerializer
  * @author Tianyi HE <hty0807@gmail.com> */
-public class VersionFieldSerializer<T> extends FieldSerializer<T> {
+public class VersionFieldSerializer<T> extends FieldSerializer<T, FieldSerializerConfig> {
 	private int typeVersion = 0; // Version of current type.
 	private int[] fieldVersion; // Version of each field.
 	private boolean compatible = true; // Whether current type is compatible with serialized objects with different version.
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/StreamFactory.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/StreamFactory.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,82 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-
-/** Provides input and output streams based on system settings.
- * @author Roman Levenstein <romixlev@gmail.com> */
-public interface StreamFactory {
-
-	/** Creates an uninitialized Input. */
-	public Input getInput ();
-
-	/** Creates a new Input for reading from a byte array.
-	 * @param bufferSize The size of the buffer. An exception is thrown if more bytes than this are read. */
-	public Input getInput (int bufferSize);
-
-	/** Creates a new Input for reading from a byte array.
-	 * @param buffer An exception is thrown if more bytes than this are read. */
-	public Input getInput (byte[] buffer);
-
-	/** Creates a new Input for reading from a byte array.
-	 * @param buffer An exception is thrown if more bytes than this are read. */
-	public Input getInput (byte[] buffer, int offset, int count);
-
-	/** Creates a new Input for reading from an InputStream with a buffer size of 4096. */
-	public Input getInput (InputStream inputStream);
-
-	/** Creates a new Input for reading from an InputStream. */
-	public Input getInput (InputStream inputStream, int bufferSize);
-
-	/** Creates an uninitialized Output. {@link Output#setBuffer(byte[], int)} must be called before the Output is used. */
-	public Output getOutput ();
-
-	/** Creates a new Output for writing to a byte array.
-	 * @param bufferSize The initial and maximum size of the buffer. An exception is thrown if this size is exceeded. */
-	public Output getOutput (int bufferSize);
-
-	/** Creates a new Output for writing to a byte array.
-	 * @param bufferSize The initial size of the buffer.
-	 * @param maxBufferSize The buffer is doubled as needed until it exceeds maxBufferSize and an exception is thrown. Can be -1
-	 *           for no maximum. */
-	public Output getOutput (int bufferSize, int maxBufferSize);
-
-	/** Creates a new Output for writing to a byte array.
-	 * @see Output#setBuffer(byte[]) */
-	public Output getOutput (byte[] buffer);
-
-	/** Creates a new Output for writing to a byte array.
-	 * @see Output#setBuffer(byte[], int) */
-	public Output getOutput (byte[] buffer, int maxBufferSize);
-
-	/** Creates a new Output for writing to an OutputStream. A buffer size of 4096 is used. */
-	public Output getOutput (OutputStream outputStream);
-
-	/** Creates a new Output for writing to an OutputStream. */
-	public Output getOutput (OutputStream outputStream, int bufferSize);
-
-	public void setKryo (Kryo kryo);
-
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/DefaultStreamFactory.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/DefaultStreamFactory.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,104 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.util;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.StreamFactory;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-
-/** StreamFactory which provides usual Input/Output streams, which are present in all versions of Kryo.
- * 
- * @author Roman Levenstein <romixlev@gmail.com> */
-public class DefaultStreamFactory implements StreamFactory {
-
-	@Override
-	public Input getInput () {
-		return new Input();
-	}
-
-	@Override
-	public Input getInput (int bufferSize) {
-		return new Input(bufferSize);
-	}
-
-	@Override
-	public Input getInput (byte[] buffer) {
-		return new Input(buffer);
-	}
-
-	@Override
-	public Input getInput (byte[] buffer, int offset, int count) {
-		return new Input(buffer, offset, count);
-	}
-
-	@Override
-	public Input getInput (InputStream inputStream) {
-		return new Input(inputStream);
-	}
-
-	@Override
-	public Input getInput (InputStream inputStream, int bufferSize) {
-		return new Input(inputStream, bufferSize);
-	}
-
-	@Override
-	public Output getOutput () {
-		return new Output();
-	}
-
-	@Override
-	public Output getOutput (int bufferSize) {
-		return new Output(bufferSize);
-	}
-
-	@Override
-	public Output getOutput (int bufferSize, int maxBufferSize) {
-		return new Output(bufferSize, maxBufferSize);
-	}
-
-	@Override
-	public Output getOutput (byte[] buffer) {
-		return new Output(buffer);
-	}
-
-	@Override
-	public Output getOutput (byte[] buffer, int maxBufferSize) {
-		return new Output(buffer, maxBufferSize);
-	}
-
-	@Override
-	public Output getOutput (OutputStream outputStream) {
-		return new Output(outputStream);
-	}
-
-	@Override
-	public Output getOutput (OutputStream outputStream, int bufferSize) {
-		return new Output(outputStream, bufferSize);
-	}
-
-	@Override
-	public void setKryo (Kryo kryo) {
-	}
-
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/FastestStreamFactory.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/FastestStreamFactory.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,111 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.util;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.StreamFactory;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.io.UnsafeInput;
-import com.esotericsoftware.kryo.io.UnsafeOutput;
-
-/** This StreamFactory tries to provide fastest possible Input/Output streams on a given platform. It may return sun.misc.Unsafe
- * based implementations of streams, which are very fast, but not portable across platforms.
- * 
- * @author Roman Levenstein <romixlev@gmail.com> */
-public class FastestStreamFactory implements StreamFactory {
-
-	static private boolean isUnsafe = UnsafeUtil.unsafe() != null;
-
-	@Override
-	public Input getInput () {
-		return (isUnsafe) ? new UnsafeInput() : new Input();
-	}
-
-	@Override
-	public Input getInput (int bufferSize) {
-		return (isUnsafe) ? new UnsafeInput(bufferSize) : new Input(bufferSize);
-	}
-
-	@Override
-	public Input getInput (byte[] buffer) {
-		return (isUnsafe) ? new UnsafeInput(buffer) : new Input(buffer);
-	}
-
-	@Override
-	public Input getInput (byte[] buffer, int offset, int count) {
-		return (isUnsafe) ? new UnsafeInput(buffer, offset, count) : new Input(buffer, offset, count);
-	}
-
-	@Override
-	public Input getInput (InputStream inputStream) {
-		return (isUnsafe) ? new UnsafeInput(inputStream) : new Input(inputStream);
-	}
-
-	@Override
-	public Input getInput (InputStream inputStream, int bufferSize) {
-		return (isUnsafe) ? new UnsafeInput(inputStream, bufferSize) : new Input(inputStream, bufferSize);
-	}
-
-	@Override
-	public Output getOutput () {
-		return (isUnsafe) ? new UnsafeOutput() : new Output();
-	}
-
-	@Override
-	public Output getOutput (int bufferSize) {
-		return (isUnsafe) ? new UnsafeOutput(bufferSize) : new Output(bufferSize);
-	}
-
-	@Override
-	public Output getOutput (int bufferSize, int maxBufferSize) {
-		return (isUnsafe) ? new UnsafeOutput(bufferSize, maxBufferSize) : new Output(bufferSize, maxBufferSize);
-	}
-
-	@Override
-	public Output getOutput (byte[] buffer) {
-		return (isUnsafe) ? new UnsafeOutput(buffer) : new Output(buffer);
-	}
-
-	@Override
-	public Output getOutput (byte[] buffer, int maxBufferSize) {
-		return (isUnsafe) ? new UnsafeOutput(buffer, maxBufferSize) : new Output(buffer, maxBufferSize);
-	}
-
-	@Override
-	public Output getOutput (OutputStream outputStream) {
-		return (isUnsafe) ? new UnsafeOutput(outputStream) : new Output(outputStream);
-	}
-
-	@Override
-	public Output getOutput (OutputStream outputStream, int bufferSize) {
-		return (isUnsafe) ? new UnsafeOutput(outputStream, bufferSize) : new Output(outputStream, bufferSize);
-	}
-
-	@Override
-	public void setKryo (Kryo kryo) {
-		// Only use Unsafe-based streams if this Kryo instance supports it
-		// isUnsafe = UnsafeUtil.unsafe() != null && kryo.getUnsafe();
-	}
-
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/IdentityMap.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/IdentityMap.java	2018-12-20 09:20:46.850804287 +0100
@@ -24,16 +24,16 @@
  * size is less than 2^16) or 4 hashes (if table size is greater than or equal to 2^16), random walking, and a small stash for
  * problematic keys Null keys are not allowed. Null values are allowed. No allocation is done except when growing the table size.
  * <br>
- * <br>
+ * 4 <br>
  * This map performs very fast get, containsKey, and remove (typically O(1), worst case O(log(n))). Put may be a bit slower,
  * depending on hash collisions. Load factors greater than 0.91 greatly increase the chances the map will have to rehash to the
  * next higher POT size.
  * @author Nathan Sweet */
 public class IdentityMap<K, V> {
 	// primes for hash functions 2, 3, and 4
-	private static final int PRIME2 = 0xbe1f14b1;
-	private static final int PRIME3 = 0xb4b82e39;
-	private static final int PRIME4 = 0xced1c241;
+	static private final int PRIME2 = 0xbe1f14b1;
+	static private final int PRIME3 = 0xb4b82e39;
+	static private final int PRIME4 = 0xced1c241;
 
 	public int size;
 
@@ -45,7 +45,7 @@
 	private int hashShift, mask, threshold;
 	private int stashCapacity;
 	private int pushIterations;
-	private boolean isBigTable;
+	private boolean bigTable;
 
 	private Entries entries;
 	private Values values;
@@ -74,7 +74,7 @@
 		this.loadFactor = loadFactor;
 
 		// big table is when capacity >= 2^16
-		isBigTable = (capacity >>> 16) != 0 ? true : false;
+		bigTable = (capacity >>> 16) != 0 ? true : false;
 
 		threshold = (int)(capacity * loadFactor);
 		mask = capacity - 1;
@@ -91,7 +91,6 @@
 		// avoid getfield opcode
 		K[] keyTable = this.keyTable;
 		int mask = this.mask;
-		boolean isBigTable = this.isBigTable;
 
 		// Check for existing keys.
 		int hashCode = System.identityHashCode(key);
@@ -121,7 +120,7 @@
 
 		int index4 = -1;
 		K key4 = null;
-		if (isBigTable) {
+		if (bigTable) {
 			index4 = hash4(hashCode);
 			key4 = keyTable[index4];
 			if (key4 == key) {
@@ -162,7 +161,7 @@
 			return null;
 		}
 
-		if (isBigTable && key4 == null) {
+		if (bigTable && key4 == null) {
 			keyTable[index4] = key;
 			valueTable[index4] = value;
 			if (size++ >= threshold) resize(capacity << 1);
@@ -206,7 +205,7 @@
 
 		int index4 = -1;
 		K key4 = null;
-		if (isBigTable) {
+		if (bigTable) {
 			index4 = hash4(hashCode);
 			key4 = keyTable[index4];
 			if (key4 == null) {
@@ -226,13 +225,13 @@
 		K[] keyTable = this.keyTable;
 		V[] valueTable = this.valueTable;
 		int mask = this.mask;
-		boolean isBigTable = this.isBigTable;
+		boolean bigTable = this.bigTable;
 
 		// Push keys until an empty bucket is found.
 		K evictedKey;
 		V evictedValue;
 		int i = 0, pushIterations = this.pushIterations;
-		int n = isBigTable ? 4 : 3;
+		int n = bigTable ? 4 : 3;
 		do {
 			// Replace the key and value for one of the hashes.
 			switch (ObjectMap.random.nextInt(n)) {
@@ -291,7 +290,7 @@
 				return;
 			}
 
-			if (isBigTable) {
+			if (bigTable) {
 				index4 = hash4(hashCode);
 				key4 = keyTable[index4];
 				if (key4 == null) {
@@ -334,7 +333,7 @@
 			if (key != keyTable[index]) {
 				index = hash3(hashCode);
 				if (key != keyTable[index]) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (key != keyTable[index]) return getStash(key, null);
 					} else {
@@ -354,7 +353,7 @@
 			if (key != keyTable[index]) {
 				index = hash3(hashCode);
 				if (key != keyTable[index]) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (key != keyTable[index]) return getStash(key, defaultValue);
 					} else {
@@ -402,7 +401,7 @@
 			return oldValue;
 		}
 
-		if (isBigTable) {
+		if (bigTable) {
 			index = hash4(hashCode);
 			if (keyTable[index] == key) {
 				keyTable[index] = null;
@@ -500,7 +499,7 @@
 			if (key != keyTable[index]) {
 				index = hash3(hashCode);
 				if (key != keyTable[index]) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (key != keyTable[index]) return containsKeyStash(key);
 					} else {
@@ -557,7 +556,7 @@
 		pushIterations = Math.max(Math.min(newSize, 8), (int)Math.sqrt(newSize) / 8);
 
 		// big table is when capacity >= 2^16
-		isBigTable = (capacity >>> 16) != 0 ? true : false;
+		bigTable = (capacity >>> 16) != 0 ? true : false;
 
 		K[] oldKeyTable = keyTable;
 		V[] oldValueTable = valueTable;
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/IdentityObjectIntMap.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/IdentityObjectIntMap.java	2018-12-20 09:20:46.850804287 +0100
@@ -30,9 +30,9 @@
  * @author Nathan Sweet */
 public class IdentityObjectIntMap<K> {
 	// primes for hash functions 2, 3, and 4
-	private static final int PRIME2 = 0xbe1f14b1;
-	private static final int PRIME3 = 0xb4b82e39;
-	private static final int PRIME4 = 0xced1c241;
+	static private final int PRIME2 = 0xbe1f14b1;
+	static private final int PRIME3 = 0xb4b82e39;
+	static private final int PRIME4 = 0xced1c241;
 
 	public int size;
 
@@ -44,7 +44,7 @@
 	private int hashShift, mask, threshold;
 	private int stashCapacity;
 	private int pushIterations;
-	private boolean isBigTable;
+	private boolean bigTable;
 
 	/** Creates a new map with an initial capacity of 32 and a load factor of 0.8. This map will hold 25 items before growing the
 	 * backing table. */
@@ -69,7 +69,7 @@
 		this.loadFactor = loadFactor;
 
 		// big table is when capacity >= 2^16
-		isBigTable = (capacity >>> 16) != 0 ? true : false;
+		bigTable = (capacity >>> 16) != 0 ? true : false;
 
 		threshold = (int)(capacity * loadFactor);
 		mask = capacity - 1;
@@ -86,7 +86,6 @@
 		// avoid getfield opcode
 		K[] keyTable = this.keyTable;
 		int mask = this.mask;
-		boolean isBigTable = this.isBigTable;
 
 		// Check for existing keys.
 		int hashCode = System.identityHashCode(key);
@@ -113,7 +112,7 @@
 
 		int index4 = -1;
 		K key4 = null;
-		if (isBigTable) {
+		if (bigTable) {
 			index4 = hash4(hashCode);
 			key4 = keyTable[index4];
 			if (key == key4) {
@@ -152,7 +151,7 @@
 			return;
 		}
 
-		if (isBigTable && key4 == null) {
+		if (bigTable && key4 == null) {
 			keyTable[index4] = key;
 			valueTable[index4] = value;
 			if (size++ >= threshold) resize(capacity << 1);
@@ -195,7 +194,7 @@
 
 		int index4 = -1;
 		K key4 = null;
-		if (isBigTable) {
+		if (bigTable) {
 			index4 = hash4(hashCode);
 			key4 = keyTable[index4];
 			if (key4 == null) {
@@ -215,13 +214,13 @@
 		K[] keyTable = this.keyTable;
 		int[] valueTable = this.valueTable;
 		int mask = this.mask;
-		boolean isBigTable = this.isBigTable;
+		boolean bigTable = this.bigTable;
 
 		// Push keys until an empty bucket is found.
 		K evictedKey;
 		int evictedValue;
 		int i = 0, pushIterations = this.pushIterations;
-		int n = isBigTable ? 4 : 3;
+		int n = bigTable ? 4 : 3;
 		do {
 			// Replace the key and value for one of the hashes.
 			switch (ObjectMap.random.nextInt(n)) {
@@ -280,7 +279,7 @@
 				return;
 			}
 
-			if (isBigTable) {
+			if (bigTable) {
 				index4 = hash4(hashCode);
 				key4 = keyTable[index4];
 				if (key4 == null) {
@@ -324,7 +323,7 @@
 			if (key != keyTable[index]) {
 				index = hash3(hashCode);
 				if (key != keyTable[index]) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (key != keyTable[index]) return getStash(key, defaultValue);
 					} else {
@@ -353,7 +352,7 @@
 			if (key != keyTable[index]) {
 				index = hash3(hashCode);
 				if (key != keyTable[index]) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (key != keyTable[index]) return getAndIncrementStash(key, defaultValue, increment);
 					} else {
@@ -405,7 +404,7 @@
 			return oldValue;
 		}
 
-		if (isBigTable) {
+		if (bigTable) {
 			index = hash4(hashCode);
 			if (key == keyTable[index]) {
 				keyTable[index] = null;
@@ -487,7 +486,7 @@
 			if (key != keyTable[index]) {
 				index = hash3(hashCode);
 				if (key != keyTable[index]) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (key != keyTable[index]) return containsKeyStash(key);
 					} else {
@@ -534,7 +533,7 @@
 		pushIterations = Math.max(Math.min(newSize, 8), (int)Math.sqrt(newSize) / 8);
 
 		// big table is when capacity >= 2^16
-		isBigTable = (capacity >>> 16) != 0 ? true : false;
+		bigTable = (capacity >>> 16) != 0 ? true : false;
 
 		K[] oldKeyTable = keyTable;
 		int[] oldValueTable = valueTable;
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/IntMap.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/IntMap.java	2018-12-20 09:20:46.850804287 +0100
@@ -30,10 +30,10 @@
  * @author Nathan Sweet */
 public class IntMap<V> {
 	// primes for hash functions 2, 3, and 4
-	private static final int PRIME2 = 0xbe1f14b1;
-	private static final int PRIME3 = 0xb4b82e39;
-	private static final int PRIME4 = 0xced1c241;
-	private static final int EMPTY = 0;
+	static private final int PRIME2 = 0xbe1f14b1;
+	static private final int PRIME3 = 0xb4b82e39;
+	static private final int PRIME4 = 0xced1c241;
+	static private final int EMPTY = 0;
 
 	public int size;
 
@@ -47,7 +47,7 @@
 	private int hashShift, mask, threshold;
 	private int stashCapacity;
 	private int pushIterations;
-	private boolean isBigTable;
+	private boolean bigTable;
 
 	/** Creates a new map with an initial capacity of 32 and a load factor of 0.8. This map will hold 25 items before growing the
 	 * backing table. */
@@ -72,7 +72,7 @@
 		this.loadFactor = loadFactor;
 
 		// big table is when capacity >= 2^16
-		isBigTable = (capacity >>> 16) != 0 ? true : false;
+		bigTable = (capacity >>> 16) != 0 ? true : false;
 
 		threshold = (int)(capacity * loadFactor);
 		mask = capacity - 1;
@@ -109,7 +109,6 @@
 		// avoid getfield opcode
 		int[] keyTable = this.keyTable;
 		int mask = this.mask;
-		boolean isBigTable = this.isBigTable;
 
 		// Check for existing keys.
 		int index1 = key & mask;
@@ -138,7 +137,7 @@
 
 		int index4 = -1;
 		int key4 = -1;
-		if (isBigTable) {
+		if (bigTable) {
 			index4 = hash4(key);
 			key4 = keyTable[index4];
 			if (key4 == key) {
@@ -179,7 +178,7 @@
 			return null;
 		}
 
-		if (isBigTable && key4 == EMPTY) {
+		if (bigTable && key4 == EMPTY) {
 			keyTable[index4] = key;
 			valueTable[index4] = value;
 			if (size++ >= threshold) resize(capacity << 1);
@@ -234,7 +233,7 @@
 
 		int index4 = -1;
 		int key4 = -1;
-		if (isBigTable) {
+		if (bigTable) {
 			index4 = hash4(key);
 			key4 = keyTable[index4];
 			if (key4 == EMPTY) {
@@ -254,13 +253,13 @@
 		int[] keyTable = this.keyTable;
 		V[] valueTable = this.valueTable;
 		int mask = this.mask;
-		boolean isBigTable = this.isBigTable;
+		boolean bigTable = this.bigTable;
 
 		// Push keys until an empty bucket is found.
 		int evictedKey;
 		V evictedValue;
 		int i = 0, pushIterations = this.pushIterations;
-		int n = isBigTable ? 4 : 3;
+		int n = bigTable ? 4 : 3;
 		do {
 			// Replace the key and value for one of the hashes.
 			switch (ObjectMap.random.nextInt(n)) {
@@ -318,7 +317,7 @@
 				return;
 			}
 
-			if (isBigTable) {
+			if (bigTable) {
 				index4 = hash4(evictedKey);
 				key4 = keyTable[index4];
 				if (key4 == EMPTY) {
@@ -364,7 +363,7 @@
 			if (keyTable[index] != key) {
 				index = hash3(key);
 				if (keyTable[index] != key) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(key);
 						if (keyTable[index] != key) return getStash(key, null);
 					} else {
@@ -387,7 +386,7 @@
 			if (keyTable[index] != key) {
 				index = hash3(key);
 				if (keyTable[index] != key) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(key);
 						if (keyTable[index] != key) return getStash(key, defaultValue);
 					} else {
@@ -443,7 +442,7 @@
 			return oldValue;
 		}
 
-		if (isBigTable) {
+		if (bigTable) {
 			index = hash4(key);
 			if (keyTable[index] == key) {
 				keyTable[index] = EMPTY;
@@ -548,7 +547,7 @@
 			if (keyTable[index] != key) {
 				index = hash3(key);
 				if (keyTable[index] != key) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(key);
 						if (keyTable[index] != key) return containsKeyStash(key);
 					} else {
@@ -608,7 +607,7 @@
 		pushIterations = Math.max(Math.min(newSize, 8), (int)Math.sqrt(newSize) / 8);
 
 		// big table is when capacity >= 2^16
-		isBigTable = (capacity >>> 16) != 0 ? true : false;
+		bigTable = (capacity >>> 16) != 0 ? true : false;
 
 		int[] oldKeyTable = keyTable;
 		V[] oldValueTable = valueTable;
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/ListReferenceResolver.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/ListReferenceResolver.java	2018-12-20 09:20:46.850804287 +0100
@@ -67,7 +67,7 @@
 		seenObjects.clear();
 	}
 
-	/** Returns false for Boolean, Byte, Character, and Short. */
+	/** Returns false for all primitive wrappers. */
 	public boolean useReferences (Class type) {
 		return !Util.isWrapperClass(type);
 	}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/MapReferenceResolver.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/MapReferenceResolver.java	2018-12-20 09:20:46.850804287 +0100
@@ -24,8 +24,8 @@
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryo.ReferenceResolver;
 
-/** Uses an {@link IdentityObjectIntMap} to track objects that have already been written. This can handle graph with any number of
- * objects, but is slightly slower than {@link ListReferenceResolver} for graphs with few objects.
+/** Uses an {@link IdentityObjectIntMap} to track objects that have already been written. This can handle a graph with any number
+ * of objects, but is slightly slower than {@link ListReferenceResolver} for graphs with few objects.
  * @author Nathan Sweet <misc@n4te.com> */
 public class MapReferenceResolver implements ReferenceResolver {
 	protected Kryo kryo;
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/ObjectMap.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/ObjectMap.java	2018-12-20 09:20:46.850804287 +0100
@@ -34,9 +34,9 @@
  * @author Nathan Sweet */
 public class ObjectMap<K, V> {
 	// primes for hash functions 2, 3, and 4
-	private static final int PRIME2 = 0xbe1f14b1;
-	private static final int PRIME3 = 0xb4b82e39;
-	private static final int PRIME4 = 0xced1c241;
+	static private final int PRIME2 = 0xbe1f14b1;
+	static private final int PRIME3 = 0xb4b82e39;
+	static private final int PRIME4 = 0xced1c241;
 
 	static Random random = new Random();
 
@@ -50,7 +50,7 @@
 	private int hashShift, mask, threshold;
 	private int stashCapacity;
 	private int pushIterations;
-	private boolean isBigTable;
+	private boolean bigTable;
 
 	/** Creates a new map with an initial capacity of 32 and a load factor of 0.8. This map will hold 25 items before growing the
 	 * backing table. */
@@ -75,7 +75,7 @@
 		this.loadFactor = loadFactor;
 
 		// big table is when capacity >= 2^16
-		isBigTable = (capacity >>> 16) != 0 ? true : false;
+		bigTable = (capacity >>> 16) != 0 ? true : false;
 
 		threshold = (int)(capacity * loadFactor);
 		mask = capacity - 1;
@@ -106,7 +106,6 @@
 		// avoid getfield opcode
 		K[] keyTable = this.keyTable;
 		int mask = this.mask;
-		boolean isBigTable = this.isBigTable;
 
 		// Check for existing keys.
 		int hashCode = key.hashCode();
@@ -136,7 +135,7 @@
 
 		int index4 = -1;
 		K key4 = null;
-		if (isBigTable) {
+		if (bigTable) {
 			index4 = hash4(hashCode);
 			key4 = keyTable[index4];
 			if (key.equals(key4)) {
@@ -177,7 +176,7 @@
 			return null;
 		}
 
-		if (isBigTable && key4 == null) {
+		if (bigTable && key4 == null) {
 			keyTable[index4] = key;
 			valueTable[index4] = value;
 			if (size++ >= threshold) resize(capacity << 1);
@@ -227,7 +226,7 @@
 
 		int index4 = -1;
 		K key4 = null;
-		if (isBigTable) {
+		if (bigTable) {
 			index4 = hash4(hashCode);
 			key4 = keyTable[index4];
 			if (key4 == null) {
@@ -247,13 +246,13 @@
 		K[] keyTable = this.keyTable;
 		V[] valueTable = this.valueTable;
 		int mask = this.mask;
-		boolean isBigTable = this.isBigTable;
+		boolean bigTable = this.bigTable;
 
 		// Push keys until an empty bucket is found.
 		K evictedKey;
 		V evictedValue;
 		int i = 0, pushIterations = this.pushIterations;
-		int n = isBigTable ? 4 : 3;
+		int n = bigTable ? 4 : 3;
 		do {
 			// Replace the key and value for one of the hashes.
 			switch (random.nextInt(n)) {
@@ -312,7 +311,7 @@
 				return;
 			}
 
-			if (isBigTable) {
+			if (bigTable) {
 				index4 = hash4(hashCode);
 				key4 = keyTable[index4];
 				if (key4 == null) {
@@ -355,7 +354,7 @@
 			if (!key.equals(keyTable[index])) {
 				index = hash3(hashCode);
 				if (!key.equals(keyTable[index])) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (!key.equals(keyTable[index])) return getStash(key);
 					} else {
@@ -383,7 +382,7 @@
 			if (!key.equals(keyTable[index])) {
 				index = hash3(hashCode);
 				if (!key.equals(keyTable[index])) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (!key.equals(keyTable[index])) return getStash(key, defaultValue);
 					} else {
@@ -431,7 +430,7 @@
 			return oldValue;
 		}
 
-		if (isBigTable) {
+		if (bigTable) {
 			index = hash4(hashCode);
 			if (key.equals(keyTable[index])) {
 				keyTable[index] = null;
@@ -529,7 +528,7 @@
 			if (!key.equals(keyTable[index])) {
 				index = hash3(hashCode);
 				if (!key.equals(keyTable[index])) {
-					if (isBigTable) {
+					if (bigTable) {
 						index = hash4(hashCode);
 						if (!key.equals(keyTable[index])) return containsKeyStash(key);
 					} else {
@@ -586,7 +585,7 @@
 		pushIterations = Math.max(Math.min(newSize, 8), (int)Math.sqrt(newSize) / 8);
 
 		// big table is when capacity >= 2^16
-		isBigTable = (capacity >>> 16) != 0 ? true : false;
+		bigTable = (capacity >>> 16) != 0 ? true : false;
 
 		K[] oldKeyTable = keyTable;
 		V[] oldValueTable = valueTable;
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/UnsafeUtil.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/UnsafeUtil.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,164 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo.util;
-
-import static com.esotericsoftware.minlog.Log.*;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-
-import sun.misc.Cleaner;
-import sun.misc.Unsafe;
-import sun.nio.ch.DirectBuffer;
-
-/** A few utility methods for using @link{sun.misc.Unsafe}, mostly for private use.
- * 
- * Use of Unsafe on Android is forbidden, as Android provides only a very limited functionality for this class compared to the JDK
- * version.
- * 
- * @author Roman Levenstein <romixlev@gmail.com> */
-
-public class UnsafeUtil {
-	final static private Unsafe _unsafe;
-	final static public long byteArrayBaseOffset;
-	final static public long floatArrayBaseOffset;
-	final static public long doubleArrayBaseOffset;
-	final static public long intArrayBaseOffset;
-	final static public long longArrayBaseOffset;
-	final static public long shortArrayBaseOffset;
-	final static public long charArrayBaseOffset;
-
-	// Constructor to be used for creation of ByteBuffers that use preallocated memory regions
-	static Constructor<? extends ByteBuffer> directByteBufferConstr;
-
-	static {
-		Unsafe tmpUnsafe = null;
-		long tmpByteArrayBaseOffset = 0;
-		long tmpFloatArrayBaseOffset = 0;
-		long tmpDoubleArrayBaseOffset = 0;
-		long tmpIntArrayBaseOffset = 0;
-		long tmpLongArrayBaseOffset = 0;
-		long tmpShortArrayBaseOffset = 0;
-		long tmpCharArrayBaseOffset = 0;
-
-		try {
-			if (!Util.IS_ANDROID) {
-				java.lang.reflect.Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
-				field.setAccessible(true);
-				tmpUnsafe = (sun.misc.Unsafe)field.get(null);
-				tmpByteArrayBaseOffset = tmpUnsafe.arrayBaseOffset(byte[].class);
-				tmpCharArrayBaseOffset = tmpUnsafe.arrayBaseOffset(char[].class);
-				tmpShortArrayBaseOffset = tmpUnsafe.arrayBaseOffset(short[].class);
-				tmpIntArrayBaseOffset = tmpUnsafe.arrayBaseOffset(int[].class);
-				tmpFloatArrayBaseOffset = tmpUnsafe.arrayBaseOffset(float[].class);
-				tmpLongArrayBaseOffset = tmpUnsafe.arrayBaseOffset(long[].class);
-				tmpDoubleArrayBaseOffset = tmpUnsafe.arrayBaseOffset(double[].class);
-			} else {
-				if (TRACE) trace("kryo", "Running on Android platform. Use of sun.misc.Unsafe should be disabled");
-			}
-		} catch (java.lang.Exception e) {
-			if (TRACE)
-				trace("kryo", "sun.misc.Unsafe is not accessible or not available. Use of sun.misc.Unsafe should be disabled");
-		}
-
-		byteArrayBaseOffset = tmpByteArrayBaseOffset;
-		charArrayBaseOffset = tmpCharArrayBaseOffset;
-		shortArrayBaseOffset = tmpShortArrayBaseOffset;
-		intArrayBaseOffset = tmpIntArrayBaseOffset;
-		floatArrayBaseOffset = tmpFloatArrayBaseOffset;
-		longArrayBaseOffset = tmpLongArrayBaseOffset;
-		doubleArrayBaseOffset = tmpDoubleArrayBaseOffset;
-		_unsafe = tmpUnsafe;
-	}
-
-	static {
-		ByteBuffer buf = ByteBuffer.allocateDirect(1);
-		try {
-			directByteBufferConstr = buf.getClass().getDeclaredConstructor(long.class, int.class, Object.class);
-			directByteBufferConstr.setAccessible(true);
-		} catch (Exception e) {
-			directByteBufferConstr = null;
-		}
-	}
-
-	/*** Return the sun.misc.Unsafe object. If null is returned, no further Unsafe-related methods are allowed to be invoked from
-	 * UnsafeUtil.
-	 * 
-	 * @return instance of sun.misc.Unsafe or null, if this class is not available or not accessible */
-	final static public Unsafe unsafe () {
-		return _unsafe;
-	}
-
-	/*** Sort the set of lists by their offsets from the object start address.
-	 * 
-	 * @param allFields set of fields to be sorted by their offsets */
-	public static Field[] sortFieldsByOffset (List<Field> allFields) {
-		Field[] allFieldsArray = allFields.toArray(new Field[] {});
-
-		Comparator<Field> fieldOffsetComparator = new Comparator<Field>() {
-			@Override
-			public int compare (Field f1, Field f2) {
-				long offset1 = unsafe().objectFieldOffset(f1);
-				long offset2 = unsafe().objectFieldOffset(f2);
-				if (offset1 < offset2) return -1;
-				if (offset1 == offset2) return 0;
-				return 1;
-			}
-		};
-
-		Arrays.sort(allFieldsArray, fieldOffsetComparator);
-
-		for (Field f : allFields) {
-			if (TRACE) trace("kryo", "Field '" + f.getName() + "' at offset " + unsafe().objectFieldOffset(f));
-		}
-
-		return allFieldsArray;
-	}
-
-	/*** Create a ByteBuffer that uses a provided (off-heap) memory region instead of allocating a new one.
-	 * 
-	 * @param address address of the memory region to be used for a ByteBuffer
-	 * @param size size of the memory region
-	 * @return a new ByteBuffer that uses a provided memory region instead of allocating a new one */
-	final static public ByteBuffer getDirectBufferAt (long address, int size) {
-		if (directByteBufferConstr == null) return null;
-		try {
-			return directByteBufferConstr.newInstance(address, size, null);
-		} catch (Exception e) {
-			throw new RuntimeException("Cannot allocate ByteBuffer at a given address: " + address, e);
-		}
-	}
-
-	/*** Release a direct buffer.
-	 * 
-	 * NOTE: If Cleaner is not accessible due to SecurityManager restrictions, reflection could be used to obtain the "clean"
-	 * method and then invoke it. */
-	static public void releaseBuffer (ByteBuffer niobuffer) {
-		if (niobuffer != null && niobuffer.isDirect()) {
-			Object cleaner = ((DirectBuffer)niobuffer).cleaner();
-			if (cleaner != null) ((Cleaner)cleaner).clean();
-			niobuffer = null;
-		}
-	}
-}
--- kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/Util.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/src/com/esotericsoftware/kryo/util/Util.java	2018-12-20 09:20:46.850804287 +0100
@@ -21,33 +21,22 @@
 
 import static com.esotericsoftware.minlog.Log.*;
 
-import java.util.concurrent.ConcurrentHashMap;
-
 /** A few utility methods, mostly for private use.
  * @author Nathan Sweet <misc@n4te.com> */
 public class Util {
+	static public final boolean isAndroid = "Dalvik".equals(System.getProperty("java.vm.name"));
 
-	static public final boolean IS_ANDROID = "Dalvik".equals(System.getProperty("java.vm.name"));
-
-	/** @deprecated Use {@link #IS_ANDROID} instead. */
-	@Deprecated
-	static public boolean isAndroid = IS_ANDROID;
+	// Maximum reasonable array. See: https://stackoverflow.com/questions/3038392/do-java-arrays-have-a-maximum-size
+	static public final int maxArraySize = Integer.MAX_VALUE - 8;
 
-	private static final ConcurrentHashMap<String, Boolean> classAvailabilities = new ConcurrentHashMap<String, Boolean>();
-
-	public static boolean isClassAvailable (String className) {
-		Boolean result = classAvailabilities.get(className);
-		if (result == null) {
+	static public boolean isClassAvailable (String className) {
 			try {
 				Class.forName(className);
-				result = true;
-			} catch (Exception e) {
+			return true;
+		} catch (Exception ex) {
 				debug("kryo", "Class not available: " + className);
-				result = false;
-			}
-			classAvailabilities.put(className, result);
+			return false;
 		}
-		return result;
 	}
 
 	/** Returns the primitive wrapper class for a primitive class.
@@ -167,16 +156,4 @@
 			elementClass = elementClass.getComponentType();
 		return elementClass;
 	}
-
-	/** Converts an "int" value between endian systems. */
-	static public int swapInt (int i) {
-		return ((i & 0xFF) << 24) | ((i & 0xFF00) << 8) | ((i & 0xFF0000) >> 8) | ((i >> 24) & 0xFF);
-	}
-
-	/** Converts a "long" value between endian systems. */
-	static public long swapLong (long value) {
-		return (((value >> 0) & 0xff) << 56) | (((value >> 8) & 0xff) << 48) | (((value >> 16) & 0xff) << 40)
-			| (((value >> 24) & 0xff) << 32) | (((value >> 32) & 0xff) << 24) | (((value >> 40) & 0xff) << 16)
-			| (((value >> 48) & 0xff) << 8) | (((value >> 56) & 0xff) << 0);
-	}
 }
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/ArraySerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/ArraySerializerTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -33,31 +33,30 @@
 		kryo.register(int[][][].class);
 		kryo.register(String[].class);
 		kryo.register(Object[].class);
-		roundTrip(4, 4, new Object[] {null, null});
-		roundTrip(6, 6, new Object[] {null, "2"});
-		roundTrip(6, 18, new int[] {1, 2, 3, 4});
-		roundTrip(7, 18, new int[] {1, 2, -100, 4});
-		roundTrip(9, 18, new int[] {1, 2, -100, 40000});
-		roundTrip(9, 20, new int[][] {{1, 2}, {100, 4}});
-		roundTrip(11, 22, new int[][] {{1}, {2}, {100}, {4}});
-		roundTrip(13, 24, new int[][][] {{{1}, {2}}, {{100}, {4}}});
-		roundTrip(12, 12, new String[] {"11", "2222", "3", "4"});
-		roundTrip(11, 11, new String[] {"11", "2222", null, "4"});
-		roundTrip(28, 51,
-			new Object[] {new String[] {"11", "2222", null, "4"}, new int[] {1, 2, 3, 4}, new int[][] {{1, 2}, {100, 4}}});
+		roundTrip(4, new Object[] {null, null});
+		roundTrip(6, new Object[] {null, "2"});
+		roundTrip(6, new int[] {1, 2, 3, 4});
+		roundTrip(7, new int[] {1, 2, -100, 4});
+		roundTrip(9, new int[] {1, 2, -100, 40000});
+		roundTrip(9, new int[][] {{1, 2}, {100, 4}});
+		roundTrip(11, new int[][] {{1}, {2}, {100}, {4}});
+		roundTrip(13, new int[][][] {{{1}, {2}}, {{100}, {4}}});
+		roundTrip(12, new String[] {"11", "2222", "3", "4"});
+		roundTrip(11, new String[] {"11", "2222", null, "4"});
+		roundTrip(28, new Object[] {new String[] {"11", "2222", null, "4"}, new int[] {1, 2, 3, 4}, new int[][] {{1, 2}, {100, 4}}});
 
 		ObjectArraySerializer serializer = new ObjectArraySerializer(kryo, String[].class);
 		kryo.register(String[].class, serializer);
 		serializer.setElementsAreSameType(true);
-		roundTrip(11, 11, new String[] {"11", "2222", null, "4"});
+		roundTrip(11, new String[] {"11", "2222", null, "4"});
 		serializer.setElementsAreSameType(false);
-		roundTrip(11, 11, new String[] {"11", "2222", null, "4"});
-		roundTrip(5, 5, new String[] {null, null, null});
-		roundTrip(2, 2, new String[] {});
+		roundTrip(11, new String[] {"11", "2222", null, "4"});
+		roundTrip(5, new String[] {null, null, null});
+		roundTrip(2, new String[] {});
 		serializer.setElementsAreSameType(true);
-		roundTrip(12, 12, new String[] {"11", "2222", "3", "4"});
+		roundTrip(12, new String[] {"11", "2222", "3", "4"});
 		serializer.setElementsCanBeNull(false);
-		roundTrip(12, 12, new String[] {"11", "2222", "3", "4"});
+		roundTrip(12, new String[] {"11", "2222", "3", "4"});
 
 		serializer = new ObjectArraySerializer(kryo, Float[].class);
 		kryo.register(Float[][].class, serializer);
@@ -67,6 +66,6 @@
 		array[1] = null;
 		array[2] = new Float[] {2.0f, 3.0f};
 		array[3] = new Float[] {3.0f};
-		roundTrip(31, 31, array);
+		roundTrip(31, array);
 	}
 }
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/BeanSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/BeanSerializerTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -35,9 +35,9 @@
 		test.setNullField("value");
 		test.setText("123");
 		test.setChild(new TestClass());
-		roundTrip(37, 43, test);
+		roundTrip(37, test);
 		test.setNullField(null);
-		roundTrip(33, 39, test);
+		roundTrip(33, test);
 	}
 
 	static public class TestClass {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/BlowfishSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/BlowfishSerializerTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -29,6 +29,6 @@
 	public void testZip () throws Exception {
 		byte[] key = KeyGenerator.getInstance("Blowfish").generateKey().getEncoded();
 		kryo.register(String.class, new BlowfishSerializer(new StringSerializer(), key));
-		roundTrip(49, 49, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef");
+		roundTrip(49, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef");
 	}
 }
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/CollectionSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/CollectionSerializerTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -40,38 +40,38 @@
 		kryo.register(ArrayList.class);
 		kryo.register(LinkedList.class);
 		kryo.register(CopyOnWriteArrayList.class);
-		roundTrip(11, 11, list("1", "2", "3"));
-		roundTrip(13, 19, list("1", "2", null, 1, 2));
-		roundTrip(15, 24, list("1", "2", null, 1, 2, 5));
-		roundTrip(11, 11, list("1", "2", "3"));
-		roundTrip(11, 11, list("1", "2", "3"));
-		roundTrip(13, 13, list("1", "2", list("3")));
-		roundTrip(13, 13, new LinkedList(list("1", "2", list("3"))));
-		roundTrip(13, 13, new CopyOnWriteArrayList(list("1", "2", list("3"))));
+		roundTrip(11, list("1", "2", "3"));
+		roundTrip(13, list("1", "2", null, 1, 2));
+		roundTrip(15, list("1", "2", null, 1, 2, 5));
+		roundTrip(11, list("1", "2", "3"));
+		roundTrip(11, list("1", "2", "3"));
+		roundTrip(13, list("1", "2", list("3")));
+		roundTrip(13, new LinkedList(list("1", "2", list("3"))));
+		roundTrip(13, new CopyOnWriteArrayList(list("1", "2", list("3"))));
 
 		CollectionSerializer serializer = new CollectionSerializer();
 		kryo.register(ArrayList.class, serializer);
 		kryo.register(LinkedList.class, serializer);
 		kryo.register(CopyOnWriteArrayList.class, serializer);
 		serializer.setElementClass(String.class, kryo.getSerializer(String.class));
-		roundTrip(8, 8, list("1", "2", "3"));
+		roundTrip(8, list("1", "2", "3"));
 		serializer.setElementClass(String.class, new StringSerializer());
-		roundTrip(8, 8, list("1", "2", "3"));
+		roundTrip(8, list("1", "2", "3"));
 		serializer.setElementsCanBeNull(false);
-		roundTrip(8, 8, list("1", "2", "3"));
+		roundTrip(8, list("1", "2", "3"));
 
 		kryo.register(TreeSet.class);
 		TreeSet set = new TreeSet();
 		set.add("1");
 		set.add("2");
-		roundTrip(9, 9, set);
+		roundTrip(9, set);
 
 		kryo.register(KeyThatIsntComparable.class);
 		kryo.register(KeyComparator.class);
 		set = new TreeSet(new KeyComparator());
 		set.add(new KeyThatIsntComparable("1"));
 		set.add(new KeyThatIsntComparable("2"));
-		roundTrip(9, 9, set);
+		roundTrip(9, set);
 
 		kryo.register(TreeSetSubclass.class);
 		set = new TreeSetSubclass<Integer>();
@@ -79,7 +79,7 @@
 		set.add(63);
 		set.add(34);
 		set.add(45);
-		roundTrip(11, 23, set);
+		roundTrip(11, set);
 	}
 
 	static public class TreeSetSubclass<E> extends TreeSet<E> {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/CompatibleFieldSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/CompatibleFieldSerializerTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -27,6 +27,8 @@
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer;
 import com.esotericsoftware.kryo.serializers.FieldSerializer;
+import com.esotericsoftware.kryo.serializers.FieldSerializerConfig;
+
 import org.apache.commons.lang.builder.EqualsBuilder;
 
 /** @author Nathan Sweet <misc@n4te.com> */
@@ -43,7 +45,7 @@
 		kryo.setDefaultSerializer(CompatibleFieldSerializer.class);
 		kryo.register(TestClass.class);
 		kryo.register(AnotherClass.class);
-		roundTrip(107, 107, object1);
+		roundTrip(107, object1);
 	}
 
 	public void testAddedField () throws FileNotFoundException {
@@ -56,7 +58,7 @@
 		serializer.removeField("text");
 		kryo.register(TestClass.class, serializer);
 		kryo.register(AnotherClass.class, new CompatibleFieldSerializer(kryo, AnotherClass.class));
-		roundTrip(80, 80, object1);
+		roundTrip(80, object1);
 
 		kryo.register(TestClass.class, new CompatibleFieldSerializer(kryo, TestClass.class));
 		Object object2 = kryo.readClassAndObject(input);
@@ -107,7 +109,7 @@
 		CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, ClassWithManyFields.class);
 		serializer.removeField("bAdd");
 		kryo.register(ClassWithManyFields.class, serializer);
-		roundTrip(226, 226, object1);
+		roundTrip(226, object1);
 
 		kryo.register(ClassWithManyFields.class, new CompatibleFieldSerializer(kryo, ClassWithManyFields.class));
 		Object object2 = kryo.readClassAndObject(input);
@@ -119,7 +121,7 @@
 		object1.child = new TestClass();
 
 		kryo.register(TestClass.class, new CompatibleFieldSerializer(kryo, TestClass.class));
-		roundTrip(94, 94, object1);
+		roundTrip(94, object1);
 
 		CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, TestClass.class);
 		serializer.removeField("text");
@@ -171,7 +173,7 @@
 		object1.zz = "zzaa";
 
 		kryo.register(ClassWithManyFields.class, new CompatibleFieldSerializer(kryo, ClassWithManyFields.class));
-		roundTrip(236, 236, object1);
+		roundTrip(236, object1);
 
 		CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, ClassWithManyFields.class);
 		serializer.removeField("bAdd");
@@ -238,11 +240,12 @@
 		ExtendedTestClass extendedObject = new ExtendedTestClass();
 
 		// this test would fail with DEFAULT field name strategy
-		kryo.getFieldSerializerConfig().setCachedFieldNameStrategy(FieldSerializer.CachedFieldNameStrategy.EXTENDED);
+		FieldSerializerConfig config = new FieldSerializerConfig();
+		config.setCachedFieldNameStrategy(FieldSerializer.CachedFieldNameStrategy.EXTENDED);
 
-		CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, ExtendedTestClass.class);
+		CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, ExtendedTestClass.class, config);
 		kryo.register(ExtendedTestClass.class, serializer);
-		roundTrip(286, 286, extendedObject);
+		roundTrip(286, extendedObject);
 
 		ExtendedTestClass object2 = (ExtendedTestClass)kryo.readClassAndObject(input);
 		assertEquals(extendedObject, object2);
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/DefaultSerializersTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/DefaultSerializersTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -45,125 +45,124 @@
 	}
 
 	public void testBoolean () {
-		roundTrip(2, 2, true);
-		roundTrip(2, 2, false);
+		roundTrip(2, true);
+		roundTrip(2, false);
 	}
 
 	public void testByte () {
-		roundTrip(2, 2, (byte)1);
-		roundTrip(2, 2, (byte)125);
-		roundTrip(2, 2, (byte)-125);
+		roundTrip(2, (byte)1);
+		roundTrip(2, (byte)125);
+		roundTrip(2, (byte)-125);
 	}
 
 	public void testChar () {
-		roundTrip(3, 3, 'a');
-		roundTrip(3, 3, 'z');
+		roundTrip(3, 'a');
+		roundTrip(3, 'z');
 	}
 
 	public void testDouble () {
-		roundTrip(9, 9, 0d);
-		roundTrip(9, 9, 1234d);
-		roundTrip(9, 9, 1234.5678d);
+		roundTrip(9, 0d);
+		roundTrip(9, 1234d);
+		roundTrip(9, 1234.5678d);
 	}
 
 	public void testFloat () {
-		roundTrip(5, 5, 0f);
-		roundTrip(5, 5, 123f);
-		roundTrip(5, 5, 123.456f);
+		roundTrip(5, 0f);
+		roundTrip(5, 123f);
+		roundTrip(5, 123.456f);
 	}
 
 	public void testInt () {
-		roundTrip(2, 5, 0);
-		roundTrip(2, 5, 63);
-		roundTrip(3, 5, 64);
-		roundTrip(3, 5, 127);
-		roundTrip(3, 5, 128);
-		roundTrip(3, 5, 8191);
-		roundTrip(4, 5, 8192);
-		roundTrip(4, 5, 16383);
-		roundTrip(4, 5, 16384);
-		roundTrip(5, 5, 2097151);
-		roundTrip(4, 5, 1048575);
-		roundTrip(5, 5, 134217727);
-		roundTrip(6, 5, 268435455);
-		roundTrip(6, 5, 134217728);
-		roundTrip(6, 5, 268435456);
-		roundTrip(2, 5, -64);
-		roundTrip(3, 5, -65);
-		roundTrip(3, 5, -8192);
-		roundTrip(4, 5, -1048576);
-		roundTrip(5, 5, -134217728);
-		roundTrip(6, 5, -134217729);
+		roundTrip(2, 0);
+		roundTrip(2, 63);
+		roundTrip(3, 64);
+		roundTrip(3, 127);
+		roundTrip(3, 128);
+		roundTrip(3, 8191);
+		roundTrip(4, 8192);
+		roundTrip(4, 16383);
+		roundTrip(4, 16384);
+		roundTrip(5, 2097151);
+		roundTrip(4, 1048575);
+		roundTrip(5, 134217727);
+		roundTrip(6, 268435455);
+		roundTrip(6, 134217728);
+		roundTrip(6, 268435456);
+		roundTrip(2, -64);
+		roundTrip(3, -65);
+		roundTrip(3, -8192);
+		roundTrip(4, -1048576);
+		roundTrip(5, -134217728);
+		roundTrip(6, -134217729);
 	}
 
 	public void testLong () {
-		roundTrip(2, 9, 0l);
-		roundTrip(2, 9, 63l);
-		roundTrip(3, 9, 64l);
-		roundTrip(3, 9, 127l);
-		roundTrip(3, 9, 128l);
-		roundTrip(3, 9, 8191l);
-		roundTrip(4, 9, 8192l);
-		roundTrip(4, 9, 16383l);
-		roundTrip(4, 9, 16384l);
-		roundTrip(5, 9, 2097151l);
-		roundTrip(4, 9, 1048575l);
-		roundTrip(5, 9, 134217727l);
-		roundTrip(6, 9, 268435455l);
-		roundTrip(6, 9, 134217728l);
-		roundTrip(6, 9, 268435456l);
-		roundTrip(2, 9, -64l);
-		roundTrip(3, 9, -65l);
-		roundTrip(3, 9, -8192l);
-		roundTrip(4, 9, -1048576l);
-		roundTrip(5, 9, -134217728l);
-		roundTrip(6, 9, -134217729l);
-		roundTrip(10, 9, 2368365495612416452l);
-		roundTrip(10, 9, -2368365495612416452l);
+		roundTrip(2, 0l);
+		roundTrip(2, 63l);
+		roundTrip(3, 64l);
+		roundTrip(3, 127l);
+		roundTrip(3, 128l);
+		roundTrip(3, 8191l);
+		roundTrip(4, 8192l);
+		roundTrip(4, 16383l);
+		roundTrip(4, 16384l);
+		roundTrip(5, 2097151l);
+		roundTrip(4, 1048575l);
+		roundTrip(5, 134217727l);
+		roundTrip(6, 268435455l);
+		roundTrip(6, 134217728l);
+		roundTrip(6, 268435456l);
+		roundTrip(2, -64l);
+		roundTrip(3, -65l);
+		roundTrip(3, -8192l);
+		roundTrip(4, -1048576l);
+		roundTrip(5, -134217728l);
+		roundTrip(6, -134217729l);
+		roundTrip(10, 2368365495612416452l);
+		roundTrip(10, -2368365495612416452l);
 	}
 
 	public void testShort () {
-		roundTrip(3, 3, (short)0);
-		roundTrip(3, 3, (short)123);
-		roundTrip(3, 3, (short)123);
-		roundTrip(3, 3, (short)-123);
-		roundTrip(3, 3, (short)250);
-		roundTrip(3, 3, (short)123);
-		roundTrip(3, 3, (short)400);
+		roundTrip(3, (short)0);
+		roundTrip(3, (short)123);
+		roundTrip(3, (short)123);
+		roundTrip(3, (short)-123);
+		roundTrip(3, (short)250);
+		roundTrip(3, (short)123);
+		roundTrip(3, (short)400);
 	}
 
 	public void testString () {
 		kryo = new Kryo();
 		kryo.setRegistrationRequired(true);
-		roundTrip(6, 6, "meow");
-		roundTrip(70, 70, "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef");
+		roundTrip(6, "meow");
+		roundTrip(70, "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef");
 
 		kryo.setReferences(false);
-		roundTrip(5, 5, "meow");
+		roundTrip(5, "meow");
 
-		roundTrip(3, 3, "a");
-		roundTrip(3, 3, "\n");
-		roundTrip(2, 2, "");
-		roundTrip(100, 100,
-			"ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*");
+		roundTrip(3, "a");
+		roundTrip(3, "\n");
+		roundTrip(2, "");
+		roundTrip(100, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*");
 
-		roundTrip(21, 21, "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u7C9F");
+		roundTrip(21, "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u7C9F");
 	}
 
 	public void testVoid () throws InstantiationException, IllegalAccessException {
-		roundTrip(1, 1, (Void)null);
+		roundTrip(1, (Void)null);
 	}
 
 	public void testNull () {
 		kryo = new Kryo();
 		kryo.setRegistrationRequired(true);
 		kryo.register(ArrayList.class);
-		roundTrip(1, 1, null);
+		roundTrip(1, null);
 		testNull(Long.class);
 		testNull(ArrayList.class);
 
 		kryo.setReferences(false);
-		roundTrip(1, 1, null);
+		roundTrip(1, null);
 		testNull(Long.class);
 		testNull(ArrayList.class);
 	}
@@ -177,60 +176,60 @@
 
 	public void testDateSerializer () {
 		kryo.register(Date.class);
-		roundTrip(10, 9, new Date(-1234567));
-		roundTrip(2, 9, new Date(0));
-		roundTrip(4, 9, new Date(1234567));
-		roundTrip(10, 9, new Date(-1234567));
+		roundTrip(10, new Date(-1234567));
+		roundTrip(2, new Date(0));
+		roundTrip(4, new Date(1234567));
+		roundTrip(10, new Date(-1234567));
 
 		kryo.register(java.sql.Date.class);
-		roundTrip(10, 9, new java.sql.Date(Long.MIN_VALUE));
-		roundTrip(2, 9, new java.sql.Date(0));
-		roundTrip(4, 9, new java.sql.Date(1234567));
-		roundTrip(10, 9, new java.sql.Date(Long.MAX_VALUE));
-		roundTrip(10, 9, new java.sql.Date(-1234567));
+		roundTrip(10, new java.sql.Date(Long.MIN_VALUE));
+		roundTrip(2, new java.sql.Date(0));
+		roundTrip(4, new java.sql.Date(1234567));
+		roundTrip(10, new java.sql.Date(Long.MAX_VALUE));
+		roundTrip(10, new java.sql.Date(-1234567));
 
 		kryo.register(java.sql.Time.class);
-		roundTrip(10, 9, new java.sql.Time(Long.MIN_VALUE));
-		roundTrip(2, 9, new java.sql.Time(0));
-		roundTrip(4, 9, new java.sql.Time(1234567));
-		roundTrip(10, 9, new java.sql.Time(Long.MAX_VALUE));
-		roundTrip(10, 9, new java.sql.Time(-1234567));
+		roundTrip(10, new java.sql.Time(Long.MIN_VALUE));
+		roundTrip(2, new java.sql.Time(0));
+		roundTrip(4, new java.sql.Time(1234567));
+		roundTrip(10, new java.sql.Time(Long.MAX_VALUE));
+		roundTrip(10, new java.sql.Time(-1234567));
 
 		kryo.register(java.sql.Timestamp.class);
-		roundTrip(10, 9, new java.sql.Timestamp(Long.MIN_VALUE));
-		roundTrip(2, 9, new java.sql.Timestamp(0));
-		roundTrip(4, 9, new java.sql.Timestamp(1234567));
-		roundTrip(10, 9, new java.sql.Timestamp(Long.MAX_VALUE));
-		roundTrip(10, 9, new java.sql.Timestamp(-1234567));
+		roundTrip(10, new java.sql.Timestamp(Long.MIN_VALUE));
+		roundTrip(2, new java.sql.Timestamp(0));
+		roundTrip(4, new java.sql.Timestamp(1234567));
+		roundTrip(10, new java.sql.Timestamp(Long.MAX_VALUE));
+		roundTrip(10, new java.sql.Timestamp(-1234567));
 	}
 
 	public void testBigDecimalSerializer () {
 		kryo.register(BigDecimal.class);
 		kryo.register(BigDecimalSubclass.class);
-		roundTrip(5, 8, BigDecimal.valueOf(12345, 2));
-		roundTrip(7, 10, new BigDecimal("12345.12345"));
-		roundTrip(4, 7, BigDecimal.ZERO);
-		roundTrip(4, 7, BigDecimal.ONE);
-		roundTrip(4, 7, BigDecimal.TEN);
-		roundTrip(5, 8, new BigDecimalSubclass(new BigInteger("12345"), 2));
-		roundTrip(7, 10, new BigDecimalSubclass("12345.12345"));
+		roundTrip(5, BigDecimal.valueOf(12345, 2));
+		roundTrip(7, new BigDecimal("12345.12345"));
+		roundTrip(4, BigDecimal.ZERO);
+		roundTrip(4, BigDecimal.ONE);
+		roundTrip(4, BigDecimal.TEN);
+		roundTrip(5, new BigDecimalSubclass(new BigInteger("12345"), 2));
+		roundTrip(7, new BigDecimalSubclass("12345.12345"));
 	}
 
 	public void testBigIntegerSerializer () {
 		kryo.register(BigInteger.class);
 		kryo.register(BigIntegerSubclass.class);
-		roundTrip(8, 8, BigInteger.valueOf(1270507903945L));
-		roundTrip(3, 3, BigInteger.ZERO);
-		roundTrip(3, 3, BigInteger.ONE);
-		roundTrip(3, 3, BigInteger.TEN);
-		roundTrip(8, 8, new BigIntegerSubclass("1270507903945"));
+		roundTrip(8, BigInteger.valueOf(1270507903945L));
+		roundTrip(3, BigInteger.ZERO);
+		roundTrip(3, BigInteger.ONE);
+		roundTrip(3, BigInteger.TEN);
+		roundTrip(8, new BigIntegerSubclass("1270507903945"));
 	}
 
 	public void testEnumSerializer () {
 		kryo.register(TestEnum.class);
-		roundTrip(2, 2, TestEnum.a);
-		roundTrip(2, 2, TestEnum.b);
-		roundTrip(2, 2, TestEnum.c);
+		roundTrip(2, TestEnum.a);
+		roundTrip(2, TestEnum.b);
+		roundTrip(2, TestEnum.c);
 
 		kryo = new Kryo();
 		kryo.setRegistrationRequired(false);
@@ -239,33 +238,33 @@
 		// 57 bytes for the class name characters
 		// 1 byte for the reference id
 		// 1 byte for the enum value
-		roundTrip(61, 61, TestEnum.c);
+		roundTrip(61, TestEnum.c);
 	}
 
 	public void testEnumSetSerializer () {
 		kryo.register(EnumSet.class);
 		kryo.register(TestEnum.class);
-		roundTrip(5, 8, EnumSet.of(TestEnum.a, TestEnum.c));
-		roundTrip(4, 7, EnumSet.of(TestEnum.a));
-		roundTrip(6, 9, EnumSet.allOf(TestEnum.class));
+		roundTrip(5, EnumSet.of(TestEnum.a, TestEnum.c));
+		roundTrip(4, EnumSet.of(TestEnum.a));
+		roundTrip(6, EnumSet.allOf(TestEnum.class));
 
 		// Test empty EnumSet
-		roundTrip(3, 6, EnumSet.noneOf(TestEnum.class));
+		roundTrip(3, EnumSet.noneOf(TestEnum.class));
 
 		kryo = new Kryo();
 		kryo.setRegistrationRequired(false);
-		roundTrip(89, 92, EnumSet.of(TestEnum.a, TestEnum.c));
+		roundTrip(89, EnumSet.of(TestEnum.a, TestEnum.c));
 	}
 
 	public void testEnumSerializerWithMethods () {
 		kryo.register(TestEnumWithMethods.class);
-		roundTrip(2, 2, TestEnumWithMethods.a);
-		roundTrip(2, 2, TestEnumWithMethods.b);
-		roundTrip(2, 2, TestEnumWithMethods.c);
+		roundTrip(2, TestEnumWithMethods.a);
+		roundTrip(2, TestEnumWithMethods.b);
+		roundTrip(2, TestEnumWithMethods.c);
 
 		kryo = new Kryo();
 		kryo.setRegistrationRequired(false);
-		roundTrip(76, 76, TestEnumWithMethods.c);
+		roundTrip(76, TestEnumWithMethods.c);
 	}
 
 	public void testCollectionsMethods () {
@@ -277,7 +276,7 @@
 		test.add(Collections.singletonList("meow"));
 		test.add(Collections.singletonMap("moo", 1234));
 		test.add(Collections.singleton(12.34));
-		roundTrip(249, 251, test);
+		roundTrip(249, test);
 	}
 
 	public void testCalendar () {
@@ -285,7 +284,7 @@
 		Calendar calendar = Calendar.getInstance();
 		calendar.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
 		calendar.set(1980, 7, 26, 12, 22, 46);
-		roundTrip(64, 73, calendar);
+		roundTrip(64, calendar);
 	}
 
 	public void testClassSerializer () {
@@ -344,11 +343,11 @@
 		kryo.setRegistrationRequired(true);
 		kryo.register(Locale.class);
 
-		roundTrip(5, 5, Locale.ENGLISH);
-		roundTrip(6, 6, Locale.US);
-		roundTrip(6, 6, Locale.SIMPLIFIED_CHINESE);
-		roundTrip(5, 5, new Locale("es"));
-		roundTrip(16, 16, new Locale("es", "ES", "áéíóú"));
+		roundTrip(5, Locale.ENGLISH);
+		roundTrip(6, Locale.US);
+		roundTrip(6, Locale.SIMPLIFIED_CHINESE);
+		roundTrip(5, new Locale("es"));
+		roundTrip(16, new Locale("es", "ES", "áéíóú"));
 	}
 
 	public void testCharset () {
@@ -358,7 +357,7 @@
 			Charset charset = Charset.forName(cs);
 			kryo.register(charset.getClass());
 			int expectedLength = 1 + cs.length();
-			roundTrip(expectedLength, expectedLength, charset);
+			roundTrip(expectedLength, charset);
 		}
 
 		kryo = new Kryo();
@@ -367,7 +366,7 @@
 		for (String cs : css) {
 			Charset charset = Charset.forName(cs);
 			int expectedLength = 3 + charset.getClass().getName().length() + cs.length();
-			roundTrip(expectedLength, expectedLength, charset);
+			roundTrip(expectedLength, charset);
 		}
 	}
 
@@ -376,8 +375,8 @@
 		kryo.setRegistrationRequired(true);
 		kryo.register(URL.class);
 
-		roundTrip(41, 41, new URL("https://github.com/EsotericSoftware/kryo"));
-		roundTrip(78, 78, new URL("https://github.com:443/EsotericSoftware/kryo/pulls?utf8=%E2%9C%93&q=is%3Apr"));
+		roundTrip(41, new URL("https://github.com/EsotericSoftware/kryo"));
+		roundTrip(78, new URL("https://github.com:443/EsotericSoftware/kryo/pulls?utf8=%E2%9C%93&q=is%3Apr"));
 	}
 
 	public enum TestEnum {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/DeflateSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/DeflateSerializerTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -26,7 +26,7 @@
 public class DeflateSerializerTest extends KryoTestCase {
 	public void testString () {
 		kryo.register(String.class, new DeflateSerializer(new StringSerializer()));
-		roundTrip(15, 15, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef");
+		roundTrip(15, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef");
 	}
 
 	public void testGraph () {
@@ -40,10 +40,10 @@
 		message.type = MessageType.SERVER_UPDATE;
 		message.data = physicsUpdate;
 
-		roundTrip(8, 8, message);
+		roundTrip(8, message);
 	}
 
-	public static class ServerPhysicsUpdate {
+	static public class ServerPhysicsUpdate {
 		public int value;
 
 		public ServerPhysicsUpdate () {
@@ -66,11 +66,11 @@
 		}
 	}
 
-	public static enum MessageType {
+	static public enum MessageType {
 		SERVER_UPDATE
 	}
 
-	public static class Message {
+	static public class Message {
 		public MessageType type;
 		public Object data;
 
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/FieldSerializerGenericsTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/FieldSerializerGenericsTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -13,13 +13,14 @@
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-import com.esotericsoftware.kryo.io.FastOutput;
+import com.esotericsoftware.kryo.SerializerFactory.FieldSerializerFactory;
+import com.esotericsoftware.kryo.io.Output;
 
 @RunWith(Parameterized.class)
 public class FieldSerializerGenericsTest {
 
 	@Parameters(name = "optimizedGenerics_{0}")
-	public static Iterable<?> optimizedGenerics () {
+	static public Iterable<?> optimizedGenerics () {
 		return Arrays.asList(true, false);
 	}
 
@@ -39,10 +40,12 @@
 		foos.add(genFoo1);
 		new FooContainer(foos);
 		Kryo kryo = new Kryo();
-		kryo.getFieldSerializerConfig().setOptimizedGenerics(optimizedGenerics);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setOptimizedGenerics(optimizedGenerics);
+		kryo.setDefaultSerializer(factory);
 		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 
-		kryo.writeObject(new FastOutput(outputStream), genFoo1);
+		kryo.writeObject(new Output(outputStream), genFoo1);
 	}
 
 	@Test
@@ -55,10 +58,12 @@
 		bars.add(genBar1);
 		new GenericBarContainer<GenericBar>(new BarContainer(bars));
 		Kryo kryo = new Kryo();
-		kryo.getFieldSerializerConfig().setOptimizedGenerics(optimizedGenerics);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setOptimizedGenerics(optimizedGenerics);
+		kryo.setDefaultSerializer(factory);
 		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 
-		kryo.writeObject(new FastOutput(outputStream), genBar1);
+		kryo.writeObject(new Output(outputStream), genBar1);
 	}
 
 	static class GenericBarContainer<T extends Bar> {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/FieldSerializerInheritanceTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/FieldSerializerInheritanceTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -21,6 +21,7 @@
 
 import org.junit.Assert;
 
+import com.esotericsoftware.kryo.SerializerFactory.FieldSerializerFactory;
 import com.esotericsoftware.kryo.serializers.FieldSerializer;
 
 /** Created by phamrak on 8.6.2016. */
@@ -31,7 +32,7 @@
 		kryo.setDefaultSerializer(FieldSerializer.class);
 		kryo.register(TestDefault.class);
 
-		roundTrip(17, 17, testDefault);
+		roundTrip(17, testDefault);
 
 		FieldSerializer serializer = (FieldSerializer)kryo.getSerializer(TestDefault.class);
 		assertNotNull(serializer.getField("a"));
@@ -46,7 +47,7 @@
 		kryo.setDefaultSerializer(FieldSerializer.class);
 		kryo.register(TestExtended.class);
 
-		roundTrip(34, 34, testExtended);
+		roundTrip(34, testExtended);
 
 		FieldSerializer serializer = (FieldSerializer)kryo.getSerializer(TestExtended.class);
 
@@ -63,11 +64,12 @@
 		TestExtended testExtended = new TestExtended();
 		((TestDefault)testExtended).a = "someDefaultValue";
 		testExtended.a = "someExtendedValue";
-		kryo.getFieldSerializerConfig().setCachedFieldNameStrategy(FieldSerializer.CachedFieldNameStrategy.EXTENDED);
-		kryo.setDefaultSerializer(FieldSerializer.class);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setCachedFieldNameStrategy(FieldSerializer.CachedFieldNameStrategy.EXTENDED);
+		kryo.setDefaultSerializer(factory);
 		kryo.register(TestExtended.class);
 
-		roundTrip(34, 34, testExtended);
+		roundTrip(34, testExtended);
 
 		FieldSerializer serializer = (FieldSerializer)kryo.getSerializer(TestExtended.class);
 
@@ -90,7 +92,7 @@
 	}
 
 	static public class TestDefault {
-		private String a;
+		String a;
 
 		public String getA () {
 			return a;
@@ -118,7 +120,7 @@
 	}
 
 	static public class TestExtended extends TestDefault {
-		private String a;
+		String a;
 
 		public String getA () {
 			return a;
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/FieldSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/FieldSerializerTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -30,6 +30,7 @@
 
 import org.objenesis.strategy.StdInstantiatorStrategy;
 
+import com.esotericsoftware.kryo.SerializerFactory.FieldSerializerFactory;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
 import com.esotericsoftware.kryo.serializers.CollectionSerializer;
@@ -40,6 +41,7 @@
 import com.esotericsoftware.kryo.serializers.FieldSerializer;
 import com.esotericsoftware.kryo.serializers.FieldSerializer.Bind;
 import com.esotericsoftware.kryo.serializers.FieldSerializer.Optional;
+import com.esotericsoftware.kryo.serializers.FieldSerializerConfig;
 import com.esotericsoftware.kryo.serializers.MapSerializer.BindMap;
 
 /** @author Nathan Sweet <misc@n4te.com> */
@@ -70,16 +72,16 @@
 		test.DoubleField = -0.121231d;
 		test.StringField = "stringvalue";
 		test.byteArrayField = new byte[] {2, 1, 0, -1, -2};
-		roundTrip(78, 88, test);
+		roundTrip(78, test);
 
 		kryo.register(HasStringField.class);
 		test.hasStringField = new HasStringField();
 		FieldSerializer serializer = (FieldSerializer)kryo.getSerializer(DefaultTypes.class);
 		serializer.getField("hasStringField").setCanBeNull(false);
-		roundTrip(79, 89, test);
+		roundTrip(79, test);
 		serializer.setFixedFieldTypes(true);
 		serializer.getField("hasStringField").setCanBeNull(false);
-		roundTrip(78, 88, test);
+		roundTrip(78, test);
 	}
 
 	public void testFieldRemoval () {
@@ -89,25 +91,25 @@
 
 		HasStringField hasStringField = new HasStringField();
 		hasStringField.text = "moo";
-		roundTrip(4, 4, hasStringField);
+		roundTrip(4, hasStringField);
 
 		DefaultTypes test = new DefaultTypes();
 		test.intField = 12;
 		test.StringField = "value";
 		test.CharacterField = 'X';
 		test.child = new DefaultTypes();
-		roundTrip(71, 91, test);
+		roundTrip(71, test);
 
 		supportsCopy = false;
 
 		test.StringField = null;
-		roundTrip(67, 87, test);
+		roundTrip(67, test);
 
 		FieldSerializer serializer = (FieldSerializer)kryo.getSerializer(DefaultTypes.class);
 		serializer.removeField("LongField");
 		serializer.removeField("floatField");
 		serializer.removeField("FloatField");
-		roundTrip(55, 75, test);
+		roundTrip(55, test);
 
 		supportsCopy = true;
 	}
@@ -117,7 +119,7 @@
 		kryo.register(DefaultTypes.class);
 		kryo.register(byte[].class);
 
-		FieldSerializer serializer = new FieldSerializer<IsGeneric>(kryo, IsGeneric.class);
+		FieldSerializer serializer = new FieldSerializer(kryo, IsGeneric.class);
 		serializer.removeField("y");
 		kryo.register(IsGeneric.class, serializer);
 
@@ -125,7 +127,7 @@
 		test.item = new IsGeneric<DefaultTypes>();
 
 		try {
-			roundTrip(5, 11, test);
+			roundTrip(5, test);
 		} catch (KryoException e) {
 			e.printStackTrace();
 			fail("Couldn't serialize generic with a removed field.");
@@ -141,9 +143,9 @@
 		test.hasStringField = new HasStringField();
 		test.child = new DefaultTypes();
 		test.child.hasStringField = new HasStringField();
-		roundTrip(195, 215, test);
+		roundTrip(195, test);
 		test.hasStringField = null;
-		roundTrip(193, 213, test);
+		roundTrip(193, test);
 
 		test = new DefaultTypes();
 		test.booleanField = true;
@@ -166,7 +168,7 @@
 		test.byteArrayField = new byte[] {2, 1, 0, -1, -2};
 
 		kryo = new Kryo();
-		roundTrip(140, 150, test);
+		roundTrip(140, test);
 
 		C c = new C();
 		c.a = new A();
@@ -176,7 +178,7 @@
 		c.d = new D();
 		c.d.e = new E();
 		c.d.e.f = new F();
-		roundTrip(63, 73, c);
+		roundTrip(63, c);
 	}
 
 	public void testReferences () {
@@ -191,12 +193,12 @@
 		c.d.e.f.a = c.a;
 
 		kryo = new Kryo();
-		roundTrip(63, 73, c);
+		roundTrip(63, c);
 		C c2 = (C)object2;
 		assertTrue(c2.a == c2.d.e.f.a);
 
 		// Test reset clears unregistered class names.
-		roundTrip(63, 73, c);
+		roundTrip(63, c);
 		c2 = (C)object2;
 		assertTrue(c2.a == c2.d.e.f.a);
 
@@ -208,7 +210,7 @@
 		kryo.register(D.class);
 		kryo.register(E.class);
 		kryo.register(F.class);
-		roundTrip(15, 25, c);
+		roundTrip(15, c);
 		c2 = (C)object2;
 		assertTrue(c2.a == c2.d.e.f.a);
 	}
@@ -223,13 +225,13 @@
 
 		kryo.register(A.class);
 		kryo.register(B.class);
-		roundTrip(10, 16, a);
+		roundTrip(10, a);
 
 		kryo = new Kryo();
 		kryo.setReferences(false);
 		kryo.register(B.class);
 		kryo.register(A.class);
-		roundTrip(10, 16, a);
+		roundTrip(10, a);
 	}
 
 	public void testExceptionTrace () {
@@ -297,10 +299,10 @@
 			}
 		});
 		SimpleNoDefaultConstructor object1 = new SimpleNoDefaultConstructor(2);
-		roundTrip(2, 5, object1);
+		roundTrip(2, object1);
 
 		kryo.register(ComplexNoDefaultConstructor.class,
-			new FieldSerializer<ComplexNoDefaultConstructor>(kryo, ComplexNoDefaultConstructor.class) {
+			new FieldSerializer<ComplexNoDefaultConstructor, FieldSerializerConfig>(kryo, ComplexNoDefaultConstructor.class) {
 				public void write (Kryo kryo, Output output, ComplexNoDefaultConstructor object) {
 					output.writeString(object.name);
 					super.write(kryo, output, object);
@@ -318,27 +320,27 @@
 		ComplexNoDefaultConstructor object2 = new ComplexNoDefaultConstructor("has no zero arg constructor!");
 		object2.anotherField1 = 1234;
 		object2.anotherField2 = "abcd";
-		roundTrip(35, 37, object2);
+		roundTrip(35, object2);
 	}
 
 	public void testNonNull () {
 		kryo.register(HasNonNull.class);
 		HasNonNull nonNullValue = new HasNonNull();
 		nonNullValue.nonNullText = "moo";
-		roundTrip(4, 4, nonNullValue);
+		roundTrip(4, nonNullValue);
 	}
 
 	public void testDefaultSerializerAnnotation () {
 		kryo = new Kryo();
-		roundTrip(82, 89, new HasDefaultSerializerAnnotation(123));
+		roundTrip(82, new HasDefaultSerializerAnnotation(123));
 	}
 
 	public void testOptionalAnnotation () {
 		kryo = new Kryo();
-		roundTrip(72, 72, new HasOptionalAnnotation());
+		roundTrip(72, new HasOptionalAnnotation());
 		kryo = new Kryo();
 		kryo.getContext().put("smurf", null);
-		roundTrip(73, 76, new HasOptionalAnnotation());
+		roundTrip(73, new HasOptionalAnnotation());
 	}
 
 	public void testCyclicGrgaph () throws Exception {
@@ -348,7 +350,7 @@
 		kryo.register(byte[].class);
 		DefaultTypes test = new DefaultTypes();
 		test.child = test;
-		roundTrip(35, 45, test);
+		roundTrip(35, test);
 	}
 
 	@SuppressWarnings("synthetic-access")
@@ -356,11 +358,11 @@
 		kryo.register(HasArgumentConstructor.class);
 		kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
 		HasArgumentConstructor test = new HasArgumentConstructor("cow");
-		roundTrip(4, 4, test);
+		roundTrip(4, test);
 
 		kryo.register(HasPrivateConstructor.class);
 		test = new HasPrivateConstructor();
-		roundTrip(4, 4, test);
+		roundTrip(4, test);
 	}
 
 	/** This test uses StdInstantiatorStrategy and therefore requires a no-arg constructor. **/
@@ -371,9 +373,8 @@
 		HasPrivateConstructor.invocations = 0;
 
 		kryo.register(HasPrivateConstructor.class);
-		roundTrip(4, 4, test);
-		assertEquals("Default constructor should not be invoked with StdInstantiatorStrategy strategy", 25,
-			HasPrivateConstructor.invocations);
+		roundTrip(4, test);
+		assertEquals("Wrong number of constructor invocations", 10, HasPrivateConstructor.invocations);
 	}
 
 	/** This test uses StdInstantiatorStrategy and should bypass invocation of no-arg constructor, even if it is provided. **/
@@ -385,7 +386,7 @@
 		HasPrivateConstructor.invocations = 0;
 
 		kryo.register(HasPrivateConstructor.class);
-		roundTrip(4, 4, test);
+		roundTrip(4, test);
 		assertEquals("Default constructor should not be invoked with StdInstantiatorStrategy strategy", 0,
 			HasPrivateConstructor.invocations);
 	}
@@ -412,7 +413,9 @@
 	}
 
 	private void testGenericTypes (boolean optimizedGenerics) {
-		kryo.getFieldSerializerConfig().setOptimizedGenerics(optimizedGenerics);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setOptimizedGenerics(optimizedGenerics);
+		kryo.setDefaultSerializer(factory);
 		kryo.setReferences(true);
 		kryo.setRegistrationRequired(true);
 		kryo.register(HasGenerics.class);
@@ -423,8 +426,8 @@
 		// It may happen that classes were registered already befor this function
 		// was called. In this case, invoke the setters on the FieldSerializer
 		// objects directly.
-		FieldSerializer<?> fieldSerializer;
-		fieldSerializer = (FieldSerializer<?>)kryo.getSerializer(HasGenerics.class);
+		FieldSerializer fieldSerializer;
+		fieldSerializer = (FieldSerializer)kryo.getSerializer(HasGenerics.class);
 		fieldSerializer.setOptimizedGenerics(optimizedGenerics);
 
 		HasGenerics test = new HasGenerics();
@@ -448,10 +451,10 @@
 		test.list5 = new ArrayList();
 		test.list5.add("one");
 		test.list5.add("two");
-		roundTrip(optimizedGenerics ? 53 : 56, optimizedGenerics ? 80 : 83, test);
+		roundTrip(optimizedGenerics ? 53 : 56, test);
 		ArrayList[] al = new ArrayList[1];
 		al[0] = new ArrayList(Arrays.asList(new String[] {"A", "B", "S"}));
-		roundTrip(18, 18, al);
+		roundTrip(18, al);
 	}
 
 	public void testRegistration () {
@@ -468,7 +471,7 @@
 		test.CharacterField = 'z';
 		test.byteArrayField = new byte[] {0, 1, 2, 3, 4};
 		test.child = new DefaultTypes();
-		roundTrip(75, 95, test);
+		roundTrip(75, test);
 	}
 
 	public void testTransients () {
@@ -478,7 +481,7 @@
 		objectWithTransients1.anotherField2 = 5;
 		objectWithTransients1.anotherField3 = "Field2";
 
-		FieldSerializer<HasTransients> ser = (FieldSerializer<HasTransients>)kryo.getSerializer(HasTransients.class);
+		FieldSerializer ser = (FieldSerializer)kryo.getSerializer(HasTransients.class);
 		ser.setCopyTransient(false);
 
 		HasTransients objectWithTransients3 = kryo.copy(objectWithTransients1);
@@ -492,14 +495,16 @@
 	}
 
 	public void testTransientsUsingGlobalConfig () {
-		kryo.getFieldSerializerConfig().setCopyTransient(false);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setCopyTransient(false);
+		kryo.setDefaultSerializer(factory);
 		kryo.register(HasTransients.class);
 		HasTransients objectWithTransients1 = new HasTransients();
 		objectWithTransients1.transientField1 = "Test";
 		objectWithTransients1.anotherField2 = 5;
 		objectWithTransients1.anotherField3 = "Field2";
 
-		FieldSerializer<HasTransients> ser = (FieldSerializer<HasTransients>)kryo.getSerializer(HasTransients.class);
+		FieldSerializer ser = (FieldSerializer)kryo.getSerializer(HasTransients.class);
 		HasTransients objectWithTransients3 = kryo.copy(objectWithTransients1);
 		assertTrue("Objects should be different if copy does not include transient fields",
 			!objectWithTransients3.equals(objectWithTransients1));
@@ -522,7 +527,7 @@
 		Input input;
 		byte[] outBytes;
 
-		FieldSerializer<HasTransients> ser = (FieldSerializer<HasTransients>)kryo.getSerializer(HasTransients.class);
+		FieldSerializer<HasTransients, ?> ser = (FieldSerializer)kryo.getSerializer(HasTransients.class);
 		ser.setSerializeTransient(false);
 
 		outputStream = new ByteArrayOutputStream();
@@ -552,7 +557,9 @@
 	}
 
 	public void testSerializeTransientsUsingGlobalConfig () {
-		kryo.getFieldSerializerConfig().setSerializeTransient(false);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setSerializeTransient(false);
+		kryo.setDefaultSerializer(factory);
 		kryo.register(HasTransients.class);
 		HasTransients objectWithTransients1 = new HasTransients();
 		objectWithTransients1.transientField1 = "Test";
@@ -564,7 +571,7 @@
 		Input input;
 		byte[] outBytes;
 
-		FieldSerializer<HasTransients> ser = (FieldSerializer<HasTransients>)kryo.getSerializer(HasTransients.class);
+		FieldSerializer<HasTransients, ?> ser = (FieldSerializer)kryo.getSerializer(HasTransients.class);
 		outputStream = new ByteArrayOutputStream();
 		output = new Output(outputStream);
 		ser.write(kryo, output, objectWithTransients1);
@@ -606,14 +613,14 @@
 		obj1.collection = new ArrayList<long[]>();
 		obj1.collection.add(new long[] {1, 2, 3});
 
-		roundTrip(31, 73, obj1);
+		roundTrip(31, obj1);
 	}
 
 	public void testWronglyAnnotatedCollectionFields () {
 		try {
 			kryo.register(WronglyAnnotatedCollectionFields.class);
 			WronglyAnnotatedCollectionFields obj1 = new WronglyAnnotatedCollectionFields();
-			roundTrip(31, 73, obj1);
+			roundTrip(31, obj1);
 		} catch (RuntimeException e) {
 			Throwable cause = e.getCause().getCause();
 			assertTrue("Exception should complain about a field not implementing java.util.Collection",
@@ -628,7 +635,7 @@
 		try {
 			kryo.register(WronglyAnnotatedMapFields.class);
 			WronglyAnnotatedMapFields obj1 = new WronglyAnnotatedMapFields();
-			roundTrip(31, 73, obj1);
+			roundTrip(31, obj1);
 		} catch (RuntimeException e) {
 			Throwable cause = e.getCause().getCause();
 			assertTrue("Exception should complain about a field not implementing java.util.Map ",
@@ -643,7 +650,7 @@
 		try {
 			kryo.register(MultipleTimesAnnotatedCollectionFields.class);
 			MultipleTimesAnnotatedCollectionFields obj1 = new MultipleTimesAnnotatedCollectionFields();
-			roundTrip(31, 73, obj1);
+			roundTrip(31, obj1);
 		} catch (RuntimeException e) {
 			Throwable cause = e.getCause().getCause();
 			assertTrue("Exception should complain about a field that has a serializer already",
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/GarbageCollectionTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/GarbageCollectionTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -22,8 +22,6 @@
 import java.lang.ref.WeakReference;
 
 import com.esotericsoftware.kryo.util.DefaultClassResolver;
-import com.esotericsoftware.kryo.util.DefaultStreamFactory;
-import com.esotericsoftware.kryo.util.FastestStreamFactory;
 import com.esotericsoftware.kryo.util.MapReferenceResolver;
 
 import junit.framework.TestCase;
@@ -32,18 +30,8 @@
  * 
  * @author Tumi <serverperformance@gmail.com> */
 public class GarbageCollectionTest extends TestCase {
-
-	public void testDefaultStreamFactory () {
-		final DefaultStreamFactory strongRefToStreamFactory = new DefaultStreamFactory();
-		Kryo kryo = new Kryo(new DefaultClassResolver(), new MapReferenceResolver(), strongRefToStreamFactory);
-		WeakReference<Kryo> kryoWeakRef = new WeakReference<Kryo>(kryo);
-		kryo = null; // remove strong ref, now kryo is only weak-reachable
-		reclaim(kryoWeakRef);
-	}
-
-	public void testFastestStreamFactory () {
-		final FastestStreamFactory strongRefToStreamFactory = new FastestStreamFactory();
-		Kryo kryo = new Kryo(new DefaultClassResolver(), new MapReferenceResolver(), strongRefToStreamFactory);
+	public void test () {
+		Kryo kryo = new Kryo(new DefaultClassResolver(), new MapReferenceResolver());
 		WeakReference<Kryo> kryoWeakRef = new WeakReference<Kryo>(kryo);
 		kryo = null; // remove strong ref, now kryo is only weak-reachable
 		reclaim(kryoWeakRef);
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/GenericsTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/GenericsTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -31,6 +31,7 @@
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
+import com.esotericsoftware.kryo.SerializerFactory.FieldSerializerFactory;
 import com.esotericsoftware.kryo.io.Output;
 
 /** @author Nathan Sweet <misc@n4te.com> */
@@ -41,7 +42,7 @@
 	}
 
 	@Parameters(name = "optimizedGenerics_{0}")
-	public static Iterable<?> optimizedGenerics () {
+	static public Iterable<?> optimizedGenerics () {
 		return Arrays.asList(true, false);
 	}
 
@@ -61,22 +62,22 @@
 	public void testGenericClassWithGenericFields () throws Exception {
 		kryo.setReferences(true);
 		kryo.setRegistrationRequired(false);
-		kryo.setAsmEnabled(true);
-		kryo.getFieldSerializerConfig().setOptimizedGenerics(optimizedGenerics);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setOptimizedGenerics(optimizedGenerics);
+		kryo.setDefaultSerializer(factory);
 		kryo.register(BaseGeneric.class);
 
 		List list = Arrays.asList(new SerializableObjectFoo("one"), new SerializableObjectFoo("two"),
 			new SerializableObjectFoo("three"));
 		BaseGeneric<SerializableObjectFoo> bg1 = new BaseGeneric<SerializableObjectFoo>(list);
 
-		roundTrip(108, 108, bg1);
+		roundTrip(108, bg1);
 	}
 
 	@Test
 	public void testNonGenericClassWithGenericSuperclass () throws Exception {
 		kryo.setReferences(true);
 		kryo.setRegistrationRequired(false);
-		kryo.setAsmEnabled(true);
 		kryo.register(BaseGeneric.class);
 		kryo.register(ConcreteClass.class);
 
@@ -84,7 +85,7 @@
 			new SerializableObjectFoo("three"));
 		ConcreteClass cc1 = new ConcreteClass(list);
 
-		roundTrip(108, 108, cc1);
+		roundTrip(108, cc1);
 	}
 
 	// Test for/from https://github.com/EsotericSoftware/kryo/issues/377
@@ -98,7 +99,9 @@
 		LongListHolder o2 = new LongListHolder(Arrays.asList(1L));
 
 		kryo.setRegistrationRequired(false);
-		kryo.getFieldSerializerConfig().setOptimizedGenerics(false);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setOptimizedGenerics(false);
+		kryo.setDefaultSerializer(factory);
 		Output buffer = new Output(512, 4048);
 		kryo.writeClassAndObject(buffer, o1);
 		kryo.writeClassAndObject(buffer, o2);
@@ -108,7 +111,7 @@
 		V getValue ();
 	}
 
-	private static abstract class AbstractValueHolder<V> implements Holder<V> {
+	static private abstract class AbstractValueHolder<V> implements Holder<V> {
 		private final V value;
 
 		AbstractValueHolder (V value) {
@@ -120,26 +123,26 @@
 		}
 	}
 
-	private static abstract class AbstractValueListHolder<V> extends AbstractValueHolder<List<V>> {
+	static private abstract class AbstractValueListHolder<V> extends AbstractValueHolder<List<V>> {
 		AbstractValueListHolder (List<V> value) {
 			super(value);
 		}
 	}
 
-	private static class LongHolder extends AbstractValueHolder<Long> {
+	static private class LongHolder extends AbstractValueHolder<Long> {
 		LongHolder (Long value) {
 			super(value);
 		}
 	}
 
-	private static class LongListHolder extends AbstractValueListHolder<Long> {
+	static private class LongListHolder extends AbstractValueListHolder<Long> {
 		LongListHolder (java.util.List<Long> value) {
 			super(value);
 		}
 	}
 
 	// A simple serializable class.
-	private static class SerializableObjectFoo implements Serializable {
+	static private class SerializableObjectFoo implements Serializable {
 		String name;
 
 		SerializableObjectFoo (String name) {
@@ -163,7 +166,7 @@
 		}
 	}
 
-	private static class BaseGeneric<T extends Serializable> {
+	static private class BaseGeneric<T extends Serializable> {
 
 		// The type of this field cannot be derived from the context.
 		// Therefore, Kryo should consider it to be Object.
@@ -200,7 +203,7 @@
 	}
 
 	// This is a non-generic class with a generic superclass.
-	private static class ConcreteClass2 extends BaseGeneric<SerializableObjectFoo> {
+	static private class ConcreteClass2 extends BaseGeneric<SerializableObjectFoo> {
 		/** Kryo Constructor */
 		ConcreteClass2 () {
 			super();
@@ -211,7 +214,7 @@
 		}
 	}
 
-	private static class ConcreteClass1 extends ConcreteClass2 {
+	static private class ConcreteClass1 extends ConcreteClass2 {
 		/** Kryo Constructor */
 		ConcreteClass1 () {
 			super();
@@ -222,7 +225,7 @@
 		}
 	}
 
-	private static class ConcreteClass extends ConcreteClass1 {
+	static private class ConcreteClass extends ConcreteClass1 {
 		/** Kryo Constructor */
 		ConcreteClass () {
 			super();
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/JavaSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/JavaSerializerTest.java	2018-12-20 09:20:46.850804287 +0100
@@ -27,16 +27,16 @@
 public class JavaSerializerTest extends KryoTestCase {
 	public void testJavaSerializer () {
 		kryo.register(String.class, new JavaSerializer());
-		roundTrip(50, 50, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef");
-		roundTrip(12, 12, "meow");
+		roundTrip(50, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef");
+		roundTrip(12, "meow");
 
 		kryo.register(TestClass.class, new JavaSerializer());
 		TestClass test = new TestClass();
 		test.stringField = "fubar";
 		test.intField = 54321;
-		roundTrip(134, 134, test);
-		roundTrip(134, 134, test);
-		roundTrip(134, 134, test);
+		roundTrip(134, test);
+		roundTrip(134, test);
+		roundTrip(134, test);
 	}
 
 	static public class TestClass implements Serializable {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/KryoTestCase.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/KryoTestCase.java	2018-12-20 09:20:46.850804287 +0100
@@ -30,14 +30,8 @@
 
 import com.esotericsoftware.kryo.io.ByteBufferInput;
 import com.esotericsoftware.kryo.io.ByteBufferOutput;
-import com.esotericsoftware.kryo.io.FastInput;
-import com.esotericsoftware.kryo.io.FastOutput;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.io.UnsafeInput;
-import com.esotericsoftware.kryo.io.UnsafeMemoryInput;
-import com.esotericsoftware.kryo.io.UnsafeMemoryOutput;
-import com.esotericsoftware.kryo.io.UnsafeOutput;
 
 import junit.framework.TestCase;
 
@@ -72,52 +66,7 @@
 		// kryo.useAsmBackend(false);
 	}
 
-	public <T> T roundTrip (int length, int unsafeLength, T object1) {
-
-		roundTripWithStreamFactory(unsafeLength, object1, new StreamFactory() {
-			public Output createOutput (OutputStream os) {
-				return new UnsafeMemoryOutput(os);
-			}
-
-			public Output createOutput (OutputStream os, int size) {
-				return new UnsafeMemoryOutput(os, size);
-			}
-
-			public Output createOutput (int size, int limit) {
-				return new UnsafeMemoryOutput(size, limit);
-			}
-
-			public Input createInput (InputStream os, int size) {
-				return new UnsafeMemoryInput(os, size);
-			}
-
-			public Input createInput (byte[] buffer) {
-				return new UnsafeMemoryInput(buffer);
-			}
-		});
-
-		roundTripWithStreamFactory(unsafeLength, object1, new StreamFactory() {
-			public Output createOutput (OutputStream os) {
-				return new UnsafeOutput(os);
-			}
-
-			public Output createOutput (OutputStream os, int size) {
-				return new UnsafeOutput(os, size);
-			}
-
-			public Output createOutput (int size, int limit) {
-				return new UnsafeOutput(size, limit);
-			}
-
-			public Input createInput (InputStream os, int size) {
-				return new UnsafeInput(os, size);
-			}
-
-			public Input createInput (byte[] buffer) {
-				return new UnsafeInput(buffer);
-			}
-		});
-
+	public <T> T roundTrip (int length, T object1) {
 		roundTripWithStreamFactory(length, object1, new StreamFactory() {
 			public Output createOutput (OutputStream os) {
 				return new ByteBufferOutput(os);
@@ -140,28 +89,6 @@
 			}
 		});
 
-		roundTripWithStreamFactory(unsafeLength, object1, new StreamFactory() {
-			public Output createOutput (OutputStream os) {
-				return new FastOutput(os);
-			}
-
-			public Output createOutput (OutputStream os, int size) {
-				return new FastOutput(os, size);
-			}
-
-			public Output createOutput (int size, int limit) {
-				return new FastOutput(size, limit);
-			}
-
-			public Input createInput (InputStream os, int size) {
-				return new FastInput(os, size);
-			}
-
-			public Input createInput (byte[] buffer) {
-				return new FastInput(buffer);
-			}
-		});
-
 		return roundTripWithStreamFactory(length, object1, new StreamFactory() {
 			public Output createOutput (OutputStream os) {
 				return new Output(os);
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/MapSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/MapSerializerTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -29,6 +29,7 @@
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 
+import com.esotericsoftware.kryo.SerializerFactory.FieldSerializerFactory;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
 import com.esotericsoftware.kryo.serializers.MapSerializer;
@@ -47,9 +48,9 @@
 		HashMap map = new HashMap();
 		map.put("123", "456");
 		map.put("789", "abc");
-		roundTrip(18, 21, map);
-		roundTrip(2, 5, new LinkedHashMap());
-		roundTrip(18, 21, new LinkedHashMap(map));
+		roundTrip(18, map);
+		roundTrip(2, new LinkedHashMap());
+		roundTrip(18, new LinkedHashMap(map));
 
 		MapSerializer serializer = new MapSerializer();
 		kryo.register(HashMap.class, serializer);
@@ -57,9 +58,9 @@
 		serializer.setKeyClass(String.class, kryo.getSerializer(String.class));
 		serializer.setKeysCanBeNull(false);
 		serializer.setValueClass(String.class, kryo.getSerializer(String.class));
-		roundTrip(14, 17, map);
+		roundTrip(14, map);
 		serializer.setValuesCanBeNull(false);
-		roundTrip(14, 17, map);
+		roundTrip(14, map);
 	}
 
 	public void testEmptyHashMap () {
@@ -120,7 +121,7 @@
 		TreeMap map = new TreeMap();
 		map.put("123", "456");
 		map.put("789", "abc");
-		roundTrip(19, 22, map);
+		roundTrip(19, map);
 
 		kryo.register(KeyThatIsntComparable.class);
 		kryo.register(KeyComparator.class);
@@ -131,7 +132,7 @@
 		map.put(key1, "456");
 		key2.value = "1234";
 		map.put(key2, "4567");
-		roundTrip(21, 24, map);
+		roundTrip(21, map);
 
 		kryo.register(TreeMapSubclass.class);
 		map = new TreeMapSubclass<String, Integer>();
@@ -139,7 +140,7 @@
 		map.put("2", 34);
 		map.put("3", 65);
 		map.put("4", 44);
-		roundTrip(24, 38, map);
+		roundTrip(24, map);
 	}
 
 	public void testTreeMapWithReferences () {
@@ -148,7 +149,7 @@
 		TreeMap map = new TreeMap();
 		map.put("123", "456");
 		map.put("789", "abc");
-		roundTrip(24, 27, map);
+		roundTrip(24, map);
 
 		kryo.register(KeyThatIsntComparable.class);
 		kryo.register(KeyComparator.class);
@@ -159,7 +160,7 @@
 		map.put(key1, "456");
 		key2.value = "1234";
 		map.put(key2, "4567");
-		roundTrip(29, 32, map);
+		roundTrip(29, map);
 
 		kryo.register(TreeMapSubclass.class);
 		map = new TreeMapSubclass<String, Integer>();
@@ -167,12 +168,14 @@
 		map.put("2", 34);
 		map.put("3", 65);
 		map.put("4", 44);
-		roundTrip(29, 43, map);
+		roundTrip(29, map);
 	}
 
 	public void testSerializingMapAfterDeserializingMultipleReferencesToSameMap () throws Exception {
 		Kryo kryo = new Kryo();
-		kryo.getFieldSerializerConfig().setOptimizedGenerics(false);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setOptimizedGenerics(false);
+		kryo.setDefaultSerializer(factory);
 		Output output = new Output(4096);
 
 		kryo.writeClassAndObject(output, new HasMultipleReferenceToSameMap());
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/pool/KryoPoolBenchmarkTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/pool/KryoPoolBenchmarkTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -29,15 +29,15 @@
 
 public class KryoPoolBenchmarkTest {
 
-	private static final int WARMUP_ITERATIONS = 10000;
+	static private final int WARMUP_ITERATIONS = 10000;
 
 	/** Number of runs. */
-	private static final int RUN_CNT = 10;
+	static private final int RUN_CNT = 10;
 
 	/** Number of iterations. Set it to something rather big for obtaining meaningful results */
-// private static final int ITER_CNT = 200000;
-	private static final int ITER_CNT = 10000;
-	private static final int SLEEP_BETWEEN_RUNS = 100;
+// static private final int ITER_CNT = 200000;
+	static private final int ITER_CNT = 10000;
+	static private final int SLEEP_BETWEEN_RUNS = 100;
 
 	// not private to prevent the synthetic accessor method
 	static KryoFactory factory = new KryoFactory() {
@@ -130,7 +130,7 @@
 		System.gc();
 	}
 
-	private static class SampleObject {
+	static private class SampleObject {
 		private int intVal;
 		private float floatVal;
 		private Short shortVal;
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/pool/KryoPoolTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/pool/KryoPoolTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -35,7 +35,7 @@
 @RunWith(Parameterized.class)
 public class KryoPoolTest {
 
-	private static KryoFactory factory = new KryoFactory() {
+	static private KryoFactory factory = new KryoFactory() {
 		@Override
 		public Kryo create () {
 			Kryo kryo = new Kryo();
@@ -45,7 +45,7 @@
 	};
 
 	@Parameters
-	public static Collection<Object[]> data () {
+	static public Collection<Object[]> data () {
 		return Arrays.asList(new Object[][] {{new KryoPool.Builder(factory)}, {new KryoPool.Builder(factory).softReferences()}});
 	}
 
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/ReferenceTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/ReferenceTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -95,7 +95,7 @@
 			kryo.register(subList.getClass(), new SubListSerializer());
 
 		}
-		roundTrip(26, 26, subList);
+		roundTrip(26, subList);
 	}
 
 	static public class SubListSerializer extends Serializer<List> {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/ReflectionAssert.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/ReflectionAssert.java	2018-12-20 09:20:46.854804308 +0100
@@ -68,7 +68,7 @@
 	}
 
 	// CHECKSTYLE:OFF
-	private static void assertReflectionEquals (final Object one, final Object another,
+	static private void assertReflectionEquals (final Object one, final Object another,
 		final boolean requireMatchingCollectionClasses, final Map<Object, Object> alreadyChecked, final String path) {
 		if (one == another) {
 			return;
@@ -151,12 +151,12 @@
 
 	} // CHECKSTYLE:ON
 
-	private static boolean isOnlyOneAssignable (final Class<?> checkedClazz, final Object one, final Object another) {
+	static private boolean isOnlyOneAssignable (final Class<?> checkedClazz, final Object one, final Object another) {
 		return checkedClazz.isAssignableFrom(one.getClass()) && !checkedClazz.isAssignableFrom(another.getClass())
 			|| checkedClazz.isAssignableFrom(another.getClass()) && !checkedClazz.isAssignableFrom(one.getClass());
 	}
 
-	private static boolean oneIsAssignable (final Object one, final Object another, final Class<?>... checkedClazzes) {
+	static private boolean oneIsAssignable (final Object one, final Object another, final Class<?>... checkedClazzes) {
 		for (final Class<?> checkedClazz : checkedClazzes) {
 			if (checkedClazz.isAssignableFrom(one.getClass()) || checkedClazz.isAssignableFrom(another.getClass())) {
 				return true;
@@ -169,7 +169,7 @@
 	 * TODO (MG): this assumes same iteration order, which must not be given for sets. There could be a specialized implementation
 	 * for sets.
 	 */
-	private static void assertCollectionEquals (final Collection<?> m1, final Collection<?> m2,
+	static private void assertCollectionEquals (final Collection<?> m1, final Collection<?> m2,
 		final boolean requireMatchingClasses, final Map<Object, Object> alreadyChecked, final String path) {
 		Assert.assertEquals("Collection size does not match for path '" + (StringUtils.isEmpty(path) ? "." : path) + "' - ",
 			m1.size(), m2.size());
@@ -181,7 +181,7 @@
 		}
 	}
 
-	private static void assertMapEquals (final Map<?, ?> m1, final Map<?, ?> m2, final boolean requireMatchingClasses,
+	static private void assertMapEquals (final Map<?, ?> m1, final Map<?, ?> m2, final boolean requireMatchingClasses,
 		final Map<Object, Object> alreadyChecked, final String path) {
 		Assert.assertEquals("Map size does not match for path '" + (StringUtils.isEmpty(path) ? "." : path) + "', map contents:"
 			+ "\nmap1: " + m1 + "\nmap2: " + m2 + "\n", m1.size(), m2.size());
@@ -191,7 +191,7 @@
 		}
 	}
 
-	private static void assertEqualDeclaredFields (final Class<? extends Object> clazz, final Object one, final Object another,
+	static private void assertEqualDeclaredFields (final Class<? extends Object> clazz, final Object one, final Object another,
 		final boolean requireMatchingClasses, final Map<Object, Object> alreadyChecked, final String path) {
 		for (final Field field : clazz.getDeclaredFields()) {
 			field.setAccessible(true);
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/SerializationBenchmarkTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/SerializationBenchmarkTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -30,16 +30,8 @@
 import java.util.Arrays;
 import java.util.concurrent.TimeUnit;
 
-//import org.gridgain.grid.marshaller.GridMarshaller;
-//import org.gridgain.grid.marshaller.optimized.GridOptimizedMarshaller;
-
-import com.esotericsoftware.kryo.io.FastInput;
-import com.esotericsoftware.kryo.io.FastOutput;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.io.UnsafeInput;
-import com.esotericsoftware.kryo.io.UnsafeOutput;
-import com.esotericsoftware.kryo.serializers.FieldSerializer;
 import com.esotericsoftware.minlog.Log;
 
 /*** This test was originally taken from a GridGain blog. It is a compares the speed of serialization using Java serialization,
@@ -47,22 +39,22 @@
  * 
  * @author Roman Levenstein <romixlev@gmail.com> */
 public class SerializationBenchmarkTest extends KryoTestCase {
-	private static final int WARMUP_ITERATIONS = 1000;
+	static private final int WARMUP_ITERATIONS = 1000;
 
 	/** Number of runs. */
-	private static final int RUN_CNT = 1;
+	static private final int RUN_CNT = 1;
 
 	/** Number of iterations. Set it to something rather big for obtaining meaningful results */
-// private static final int ITER_CNT = 200000;
-	private static final int ITER_CNT = 100;
+// static private final int ITER_CNT = 200000;
+	static private final int ITER_CNT = 100;
 
-	private static final int SLEEP_BETWEEN_RUNS = 100;
+	static private final int SLEEP_BETWEEN_RUNS = 100;
 
-	private static final int OUTPUT_BUFFER_SIZE = 4096 * 10 * 4;
+	static private final int OUTPUT_BUFFER_SIZE = 4096 * 10 * 4;
 
 	SampleObject obj = createObject();
 
-	private static SampleObject createObject () {
+	static private SampleObject createObject () {
 		long[] longArr = new long[3000];
 
 		for (int i = 0; i < longArr.length; i++)
@@ -76,7 +68,7 @@
 		return new SampleObject(123, 123.456f, (short)321, longArr, dblArr);
 	}
 
-// public static void main(String[] args) throws Exception {
+// static public void main(String[] args) throws Exception {
 // // Create sample object.
 // SampleObject obj = createObject();
 //
@@ -126,30 +118,6 @@
 		runKryoSerializationWithoutTryCatch(RUN_CNT, ITER_CNT, true);
 	}
 
-	public void testKryoSerializationWithoutTryCatchWithFastStreams () throws Exception {
-		// Warm-up phase: Perform 100000 iterations
-		runKryoSerializationWithoutTryCatchWithFastStreams(1, WARMUP_ITERATIONS, false);
-		runKryoSerializationWithoutTryCatchWithFastStreams(RUN_CNT, ITER_CNT, true);
-	}
-
-	public void testKryoUnsafeSerializationWithoutTryCatch () throws Exception {
-		// Warm-up phase: Perform 100000 iterations
-		runKryoUnsafeSerializationWithoutTryCatch(1, WARMUP_ITERATIONS, false);
-		runKryoUnsafeSerializationWithoutTryCatch(RUN_CNT, ITER_CNT, true);
-	}
-
-	public void testKryoUnsafeSerializationWithoutTryCatchWithoutAsm () throws Exception {
-		// Warm-up phase: Perform 100000 iterations
-		runKryoUnsafeSerializationWithoutTryCatchWithoutAsm(1, WARMUP_ITERATIONS, false);
-		runKryoUnsafeSerializationWithoutTryCatchWithoutAsm(RUN_CNT, ITER_CNT, true);
-	}
-
-	public void testKryoUnsafeSerializationWithoutTryCatchWithoutReferences () throws Exception {
-		// Warm-up phase: Perform 100000 iterations
-		runKryoUnsafeSerializationWithoutTryCatchWithoutReferences(1, WARMUP_ITERATIONS, false);
-		runKryoUnsafeSerializationWithoutTryCatchWithoutReferences(RUN_CNT, ITER_CNT, true);
-	}
-
 	private void runJavaSerialization (final int RUN_CNT, final int ITER_CNT, boolean outputResults) throws Exception {
 		long avgDur = 0;
 		long bestTime = Long.MAX_VALUE;
@@ -430,300 +398,12 @@
 		}
 	}
 
-	private void runKryoSerializationWithoutTryCatchWithFastStreams (final int RUN_CNT, final int ITER_CNT, boolean outputResults)
-		throws Exception {
-		Kryo marsh = new Kryo();
-		marsh.register(SampleObject.class, 40);
-
-		long avgDur = 0;
-		long bestTime = Long.MAX_VALUE;
-
-		byte[] out = new byte[OUTPUT_BUFFER_SIZE];
-
-		for (int i = 0; i < RUN_CNT; i++) {
-			SampleObject newObj = null;
-
-			long start = System.nanoTime();
-
-			for (int j = 0; j < ITER_CNT; j++) {
-
-				Output kryoOut = null;
-
-				kryoOut = new FastOutput(out);
-
-				marsh.writeObject(kryoOut, obj);
-				kryoOut.close();
-				// U.close(kryoOut, null);
-
-				Input kryoIn = null;
-
-				kryoIn = new FastInput(kryoOut.getBuffer(), 0, kryoOut.position());
-
-				newObj = marsh.readObject(kryoIn, SampleObject.class);
-				kryoIn.close();
-				// U.close(kryoIn, null);
-			}
-
-			long dur = System.nanoTime() - start;
-			dur = TimeUnit.NANOSECONDS.toMillis(dur);
-			// Check that unmarshalled object is equal to original one (should
-			// never fail).
-			if (!obj.equals(newObj)) throw new RuntimeException("Unmarshalled object is not equal to original object.");
-			if (outputResults)
-				System.out.format(">>> Kryo serialization without try-catch with fast streams (run %d): %,d ms\n", i + 1, dur);
-
-			avgDur += dur;
-			bestTime = Math.min(bestTime, dur);
-			systemCleanupAfterRun();
-		}
-
-		avgDur /= RUN_CNT;
-
-		if (outputResults) {
-			System.out.format("\n>>> Kryo serialization without try-catch with fast streams (average): %,d ms\n\n", avgDur);
-			System.out.format("\n>>> Kryo serialization without try-catch with fast streams (best time): %,d ms\n\n", bestTime);
-		}
-	}
-
-	private void runKryoUnsafeSerializationWithoutTryCatch (final int RUN_CNT, final int ITER_CNT, boolean outputResults)
-		throws Exception {
-		Kryo marsh = new Kryo();
-		marsh.setRegistrationRequired(true);
-		marsh.register(double[].class, 30);
-		marsh.register(long[].class, 31);
-		// Explicitly tell to use Unsafe-based serializer
-		marsh.register(SampleObject.class, new FieldSerializer<SampleObject>(marsh, SampleObject.class), 40);
-
-		// Use fastest possible serialization of object fields
-		FieldSerializer<SampleObject> ser = (FieldSerializer<SampleObject>)marsh.getRegistration(SampleObject.class)
-			.getSerializer();
-		ser.setUseAsm(true);
-
-		long avgDur = 0;
-		long bestTime = Long.MAX_VALUE;
-
-		byte[] out = new byte[OUTPUT_BUFFER_SIZE];
-		for (int i = 0; i < RUN_CNT; i++) {
-			SampleObject newObj = null;
-
-			long start = System.nanoTime();
-
-			for (int j = 0; j < ITER_CNT; j++) {
-
-				Output kryoOut = null;
-
-				kryoOut = new UnsafeOutput(out);
-
-				marsh.writeObject(kryoOut, obj);
-				kryoOut.close();
-				// U.close(kryoOut, null);
-
-				Input kryoIn = null;
-
-				kryoIn = new UnsafeInput(kryoOut.getBuffer(), 0, kryoOut.position());
-
-				newObj = marsh.readObject(kryoIn, SampleObject.class);
-				kryoIn.close();
-				// U.close(kryoIn, null);
-			}
-
-			long dur = System.nanoTime() - start;
-			dur = TimeUnit.NANOSECONDS.toMillis(dur);
-			// Check that unmarshalled object is equal to original one (should
-			// never fail).
-			if (!obj.equals(newObj)) throw new RuntimeException("Unmarshalled object is not equal to original object.");
-
-			if (outputResults) System.out.format(">>> Kryo unsafe serialization without try-catch (run %d): %,d ms\n", i + 1, dur);
-
-			avgDur += dur;
-			bestTime = Math.min(bestTime, dur);
-			systemCleanupAfterRun();
-		}
-
-		avgDur /= RUN_CNT;
-
-		if (outputResults) {
-			System.out.format("\n>>> Kryo unsafe serialization without try-catch (average): %,d ms\n\n", avgDur);
-			System.out.format("\n>>> Kryo unsafe serialization without try-catch (best time): %,d ms\n\n", bestTime);
-		}
-	}
-
-	private void runKryoUnsafeSerializationWithoutTryCatchWithoutAsm (final int RUN_CNT, final int ITER_CNT, boolean outputResults)
-		throws Exception {
-		Kryo marsh = new Kryo();
-		marsh.setRegistrationRequired(true);
-		marsh.register(double[].class, 30);
-		marsh.register(long[].class, 31);
-		// Explicitly tell to use Unsafe-based serializer
-		marsh.register(SampleObject.class, new FieldSerializer<SampleObject>(marsh, SampleObject.class), 40);
-
-// // Use fastest possible serialization of object fields
-// FieldSerializer<SampleObject> ser = (FieldSerializer<SampleObject>) marsh.getRegistration(SampleObject.class).getSerializer();
-// ser.setUseAsm(false);
-
-		long avgDur = 0;
-		long bestTime = Long.MAX_VALUE;
-
-		byte[] out = new byte[OUTPUT_BUFFER_SIZE];
-		for (int i = 0; i < RUN_CNT; i++) {
-			SampleObject newObj = null;
-
-			long start = System.nanoTime();
-
-			for (int j = 0; j < ITER_CNT; j++) {
-
-				Output kryoOut = null;
-
-				kryoOut = new UnsafeOutput(out);
-
-				marsh.writeObject(kryoOut, obj);
-				kryoOut.close();
-				// U.close(kryoOut, null);
-
-				Input kryoIn = null;
-
-				kryoIn = new UnsafeInput(kryoOut.getBuffer(), 0, kryoOut.position());
-
-				newObj = marsh.readObject(kryoIn, SampleObject.class);
-				kryoIn.close();
-				// U.close(kryoIn, null);
-			}
-
-			long dur = System.nanoTime() - start;
-			dur = TimeUnit.NANOSECONDS.toMillis(dur);
-			// Check that unmarshalled object is equal to original one (should
-			// never fail).
-			if (!obj.equals(newObj)) throw new RuntimeException("Unmarshalled object is not equal to original object.");
-
-			if (outputResults)
-				System.out.format(">>> Kryo unsafe serialization without try-catch, without ASM (run %d): %,d ms\n", i + 1, dur);
-
-			avgDur += dur;
-			bestTime = Math.min(bestTime, dur);
-			systemCleanupAfterRun();
-		}
-
-		avgDur /= RUN_CNT;
-
-		if (outputResults) {
-			System.out.format("\n>>> Kryo unsafe serialization without try-catch, without ASM (average): %,d ms\n\n", avgDur);
-			System.out.format("\n>>> Kryo unsafe serialization without try-catch, without ASM (best time): %,d ms\n\n", bestTime);
-		}
-
-	}
-
-	private void runKryoUnsafeSerializationWithoutTryCatchWithoutReferences (final int RUN_CNT, final int ITER_CNT,
-		boolean outputResults) throws Exception {
-		Kryo marsh = new Kryo();
-		kryo.setReferences(false);
-		marsh.setRegistrationRequired(true);
-		marsh.register(double[].class, 30);
-		marsh.register(long[].class, 31);
-		// Explicitly tell to use Unsafe-based serializer
-		marsh.register(SampleObject.class, new FieldSerializer<SampleObject>(marsh, SampleObject.class), 40);
-
-		// Use fastest possible serialization of object fields
-		FieldSerializer<SampleObject> ser = (FieldSerializer<SampleObject>)marsh.getRegistration(SampleObject.class)
-			.getSerializer();
-		ser.setUseAsm(false);
-
-		long avgDur = 0;
-		long bestTime = Long.MAX_VALUE;
-
-		for (int i = 0; i < RUN_CNT; i++) {
-			SampleObject newObj = null;
-			byte[] out = new byte[OUTPUT_BUFFER_SIZE];
-
-			long start = System.nanoTime();
-
-			for (int j = 0; j < ITER_CNT; j++) {
-
-				Output kryoOut = null;
-
-				kryoOut = new UnsafeOutput(out);
-
-				marsh.writeObject(kryoOut, obj);
-				kryoOut.close();
-				// U.close(kryoOut, null);
-
-				Input kryoIn = null;
-
-				kryoIn = new UnsafeInput(kryoOut.getBuffer(), 0, kryoOut.position());
-
-				newObj = marsh.readObject(kryoIn, SampleObject.class);
-				kryoIn.close();
-				// U.close(kryoIn, null);
-			}
-
-			long dur = System.nanoTime() - start;
-			dur = TimeUnit.NANOSECONDS.toMillis(dur);
-			// Check that unmarshalled object is equal to original one (should
-			// never fail).
-			if (!obj.equals(newObj)) throw new RuntimeException("Unmarshalled object is not equal to original object.");
-
-			if (outputResults) System.out.format(
-				">>> Kryo unsafe serialization without try-catch, without ASM, without references (run %d): %,d ms\n", i + 1, dur);
-
-			avgDur += dur;
-			bestTime = Math.min(bestTime, dur);
-			systemCleanupAfterRun();
-		}
-
-		avgDur /= RUN_CNT;
-
-		if (outputResults) {
-			System.out.format(
-				"\n>>> Kryo unsafe serialization without try-catch, without ASM, without references (average): %,d ms\n\n", avgDur);
-			System.out.format(
-				"\n>>> Kryo unsafe serialization without try-catch, without ASM, without references (best time): %,d ms\n\n",
-				bestTime);
-		}
-
-	}
-
-// private static long gridGainSerialization()
-// throws Exception {
-// GridMarshaller marsh = new GridOptimizedMarshaller(false,
-// Arrays.asList(SampleObject.class.getName()), null);
-//
-// long avgDur = 0;
-//
-// for (int i = 0; i < RUN_CNT; i++) {
-// SampleObject newObj = null;
-//
-// long start = System.currentTimeMillis();
-//
-// for (int j = 0; j < ITER_CNT; j++)
-// newObj = marsh.unmarshal(marsh.marshal(obj), null);
-//
-// long dur = System.currentTimeMillis() - start;
-//
-// // Check that unmarshalled object is equal to original one (should
-// // never fail).
-// if (!obj.equals(newObj))
-// throw new RuntimeException(
-// "Unmarshalled object is not equal to original object.");
-//
-// System.out.format(">>> GridGain serialization (run %d): %,d ms\n",
-// i + 1, dur);
-//
-// avgDur += dur;
-// }
-//
-// avgDur /= RUN_CNT;
-//
-// System.out.format("\n>>> GridGain serialization (average): %,d ms\n\n",
-// avgDur);
-//
-// return avgDur;
-// }
-
 	protected void setUp () throws Exception {
 		super.setUp();
 		Log.WARN();
 	}
 
-	private static class SampleObject implements Externalizable, KryoSerializable {
+	static private class SampleObject implements Externalizable, KryoSerializable {
 		private int intVal;
 		private float floatVal;
 		private Short shortVal;
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/SerializationCompatTestData.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/SerializationCompatTestData.java	2018-12-20 09:20:46.854804308 +0100
@@ -113,7 +113,7 @@
 		}
 	}
 
-	public static class TestData implements Serializable {
+	static public class TestData implements Serializable {
 
 		private boolean _boolean;
 		private char _char;
@@ -360,7 +360,7 @@
 		return person;
 	}
 
-	public static class Person {
+	static public class Person {
 
 		static enum Gender {
 			MALE, FEMALE
@@ -486,9 +486,9 @@
 
 	}
 
-	public static class Email implements Serializable {
+	static public class Email implements Serializable {
 
-		private static final long serialVersionUID = 1L;
+		static private final long serialVersionUID = 1L;
 
 		private String _name;
 		private String _email;
@@ -563,7 +563,7 @@
 
 	}
 
-	public static class PublicClass {
+	static public class PublicClass {
 		PrivateClass privateClass;
 
 		public PublicClass () {
@@ -584,7 +584,7 @@
 		}
 	}
 
-	private static class PrivateClass {
+	static private class PrivateClass {
 		String foo;
 
 		public PrivateClass (String foo) {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/SerializationCompatTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/SerializationCompatTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -35,16 +35,13 @@
 
 import com.esotericsoftware.kryo.SerializationCompatTestData.TestData;
 import com.esotericsoftware.kryo.SerializationCompatTestData.TestDataJava8;
+import com.esotericsoftware.kryo.SerializerFactory.FieldSerializerFactory;
 import com.esotericsoftware.kryo.io.ByteBufferInput;
 import com.esotericsoftware.kryo.io.ByteBufferOutput;
-import com.esotericsoftware.kryo.io.FastInput;
-import com.esotericsoftware.kryo.io.FastOutput;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.io.UnsafeInput;
-import com.esotericsoftware.kryo.io.UnsafeMemoryInput;
-import com.esotericsoftware.kryo.io.UnsafeMemoryOutput;
-import com.esotericsoftware.kryo.io.UnsafeOutput;
+import com.esotericsoftware.kryo.serializers.FieldSerializer;
+import com.esotericsoftware.kryo.serializers.FieldSerializerConfig;
 import com.esotericsoftware.minlog.Log;
 
 /** Test for serialization compatibility: data serialized with an older version (same major version) must be deserializable with
@@ -72,20 +69,21 @@
  * related tag and run the test (there's nothing here to automate creation of test files for a different version). */
 public class SerializationCompatTest extends KryoTestCase {
 
-	private static final String ENDIANNESS = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ? "le" : "be";
-	private static final int JAVA_VERSION = Integer.parseInt(System.getProperty("java.version").split("\\.")[1]);
-	private static final int EXPECTED_DEFAULT_SERIALIZER_COUNT = JAVA_VERSION < 8 ? 35 : 53;
-	private static final List<TestDataDescription<?>> TEST_DATAS = new ArrayList<TestDataDescription<?>>();
+	static private final String ENDIANNESS = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ? "le" : "be";
+	static private final int JAVA_VERSION = Integer.parseInt(System.getProperty("java.version").split("\\.")[1]);
+	static private final int EXPECTED_DEFAULT_SERIALIZER_COUNT = JAVA_VERSION < 8 ? 35 : 53;
+	static private final List<TestDataDescription<?>> TEST_DATAS = new ArrayList<TestDataDescription<?>>();
 
 	static {
-		TEST_DATAS.add(new TestDataDescription<TestData>("3.0.0", new TestData(), 1865, 1882, 1973, 1990));
-		if (JAVA_VERSION >= 8)
-			TEST_DATAS.add(new TestDataDescription<TestDataJava8>("3.1.0", new TestDataJava8(), 2025, 2042, 2177, 2194));
+		TEST_DATAS.add(new TestDataDescription<TestData>("3.0.0", new TestData(), 1865, 1882));
+		if (JAVA_VERSION >= 8) TEST_DATAS.add(new TestDataDescription<TestDataJava8>("3.1.0", new TestDataJava8(), 2025, 2042));
 	};
 
 	private void setUp (boolean optimizedGenerics) throws Exception {
 		super.setUp();
-		kryo.getFieldSerializerConfig().setOptimizedGenerics(optimizedGenerics);
+		FieldSerializerFactory factory = new FieldSerializerFactory();
+		factory.getConfig().setOptimizedGenerics(optimizedGenerics);
+		kryo.setDefaultSerializer(factory);
 		kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
 		kryo.setReferences(true);
 		kryo.setRegistrationRequired(false);
@@ -131,42 +129,6 @@
 		});
 	}
 
-	public void testFast () throws Exception {
-		runTests("fast", new Function1<File, Input>() {
-			public Input apply (File file) throws FileNotFoundException {
-				return new FastInput(new FileInputStream(file));
-			}
-		}, new Function1<File, Output>() {
-			public Output apply (File file) throws Exception {
-				return new FastOutput(new FileOutputStream(file));
-			}
-		});
-	}
-
-	public void testUnsafe () throws Exception {
-		runTests("unsafe-" + ENDIANNESS, new Function1<File, Input>() {
-			public Input apply (File file) throws FileNotFoundException {
-				return new UnsafeInput(new FileInputStream(file));
-			}
-		}, new Function1<File, Output>() {
-			public Output apply (File file) throws Exception {
-				return new UnsafeOutput(new FileOutputStream(file));
-			}
-		});
-	}
-
-	public void testUnsafeMemory () throws Exception {
-		runTests("unsafeMemory-" + ENDIANNESS, new Function1<File, Input>() {
-			public Input apply (File file) throws FileNotFoundException {
-				return new UnsafeMemoryInput(new FileInputStream(file));
-			}
-		}, new Function1<File, Output>() {
-			public Output apply (File file) throws Exception {
-				return new UnsafeMemoryOutput(new FileOutputStream(file));
-			}
-		});
-	}
-
 	private void runTests (String variant, Function1<File, Input> inputFactory, Function1<File, Output> outputFactory)
 		throws Exception {
 		runTests(true, variant + "-opt-generics", inputFactory, outputFactory);
@@ -211,8 +173,7 @@
 	private void readAndRunTest (TestDataDescription<?> description, boolean optimizedGenerics, Input in)
 		throws FileNotFoundException {
 		TestData actual = kryo.readObject(in, description.testDataClass());
-		roundTrip(optimizedGenerics ? description.lengthOptGenerics : description.lengthNonOptGenerics,
-			optimizedGenerics ? description.unsafeLengthOptGenerics : description.unsafeLengthNonOptGenerics, actual);
+		roundTrip(optimizedGenerics ? description.lengthOptGenerics : description.lengthNonOptGenerics, actual);
 		try {
 			assertReflectionEquals(actual, description.testData);
 		} catch (AssertionError e) {
@@ -224,8 +185,7 @@
 
 	private void runTestAndWrite (TestDataDescription<?> description, boolean optimizedGenerics, Output out)
 		throws FileNotFoundException {
-		roundTrip(optimizedGenerics ? description.lengthOptGenerics : description.lengthNonOptGenerics,
-			optimizedGenerics ? description.unsafeLengthOptGenerics : description.unsafeLengthNonOptGenerics, description.testData);
+		roundTrip(optimizedGenerics ? description.lengthOptGenerics : description.lengthNonOptGenerics, description.testData);
 		kryo.writeObject(out, description.testData);
 	}
 
@@ -242,22 +202,17 @@
 		B apply (A input) throws Exception;
 	}
 
-	private static class TestDataDescription<T extends TestData> {
+	static private class TestDataDescription<T extends TestData> {
 		private final String kryoVersion;
-		private final T testData;
-		private final int lengthOptGenerics;
-		private final int lengthNonOptGenerics;
-		private final int unsafeLengthOptGenerics;
-		private final int unsafeLengthNonOptGenerics;
+		final T testData;
+		final int lengthOptGenerics;
+		final int lengthNonOptGenerics;
 
-		TestDataDescription (String kryoVersion, T testData, int lengthOptGenerics, int lengthNonOptGenerics,
-			int unsafeLengthOptGenerics, int unsafeLengthNonOptGenerics) {
+		TestDataDescription (String kryoVersion, T testData, int lengthOptGenerics, int lengthNonOptGenerics) {
 			this.kryoVersion = kryoVersion;
 			this.testData = testData;
 			this.lengthOptGenerics = lengthOptGenerics;
 			this.lengthNonOptGenerics = lengthNonOptGenerics;
-			this.unsafeLengthOptGenerics = unsafeLengthOptGenerics;
-			this.unsafeLengthNonOptGenerics = unsafeLengthNonOptGenerics;
 		}
 
 		Class<T> testDataClass () {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/EnumNameSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/EnumNameSerializerTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -17,18 +17,18 @@
 
 		// 1 byte for identifying class name,
 		// rest bytes for enum's name
-		roundTrip(6, 6, TestNameEnum.HELLO);
-		roundTrip(5, 5, TestNameEnum.KRYO);
+		roundTrip(6, TestNameEnum.HELLO);
+		roundTrip(5, TestNameEnum.KRYO);
 
-		roundTrip(7, 7, TestAnotherNameEnum.SUNDAY);
-		roundTrip(8, 8, TestAnotherNameEnum.TUESDAY);
+		roundTrip(7, TestAnotherNameEnum.SUNDAY);
+		roundTrip(8, TestAnotherNameEnum.TUESDAY);
 
 		kryo = new Kryo();
 		kryo.addDefaultSerializer(Enum.class, EnumNameSerializer.class);
 		kryo.setRegistrationRequired(false);
 
-		roundTrip(84, 84, TestNameEnum.WORLD);
-		roundTrip(92, 92, TestAnotherNameEnum.MONDAY);
+		roundTrip(84, TestNameEnum.WORLD);
+		roundTrip(92, TestAnotherNameEnum.MONDAY);
 	}
 
 	public void testEnumSetSerializerWithEnumNameSerializer () throws Exception {
@@ -50,22 +50,22 @@
 		assertFalse(enumSet.contains(TestNameEnum.KRYO));
 
 		// empty EnumSet
-		roundTrip(3, 6, EnumSet.noneOf(TestNameEnum.class));
+		roundTrip(3, EnumSet.noneOf(TestNameEnum.class));
 	}
 
 	public void testEnumNameSerializerWithMethods () {
 		kryo.addDefaultSerializer(Enum.class, EnumNameSerializer.class);
 
 		kryo.register(TestNameEnumWithMethods.class);
-		roundTrip(6, 6, TestNameEnumWithMethods.ALPHA);
-		roundTrip(5, 5, TestNameEnumWithMethods.BETA);
+		roundTrip(6, TestNameEnumWithMethods.ALPHA);
+		roundTrip(5, TestNameEnumWithMethods.BETA);
 
 		kryo = new Kryo();
 		kryo.addDefaultSerializer(Enum.class, EnumNameSerializer.class);
 		kryo.setRegistrationRequired(false);
 
-		roundTrip(97, 97, TestNameEnumWithMethods.ALPHA);
-		roundTrip(96, 96, TestNameEnumWithMethods.BETA);
+		roundTrip(97, TestNameEnumWithMethods.ALPHA);
+		roundTrip(96, TestNameEnumWithMethods.BETA);
 	}
 
 	public enum TestNameEnum {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/ExternalizableSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/ExternalizableSerializerTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -40,9 +40,9 @@
 		test.stringField = "fubar";
 		test.intField = 54321;
 
-		roundTrip(11, 11, test);
-		roundTrip(11, 11, test);
-		roundTrip(11, 11, test);
+		roundTrip(11, test);
+		roundTrip(11, test);
+		roundTrip(11, test);
 	}
 
 	public void testDefault () {
@@ -51,9 +51,9 @@
 		TestClass test = new TestClass();
 		test.stringField = "fubar";
 		test.intField = 54321;
-		roundTrip(90, 90, test);
-		roundTrip(90, 90, test);
-		roundTrip(90, 90, test);
+		roundTrip(90, test);
+		roundTrip(90, test);
+		roundTrip(90, test);
 	}
 
 	public void testReadResolve () {
@@ -99,7 +99,7 @@
 		assertEquals(result.get(1), test2);
 	}
 
-	public static class TestClass implements Externalizable {
+	static public class TestClass implements Externalizable {
 		String stringField;
 		int intField;
 
@@ -138,7 +138,7 @@
 		}
 	}
 
-	public static class AnotherTestClass implements Externalizable {
+	static public class AnotherTestClass implements Externalizable {
 		private Date dateField;
 		private long longField;
 
@@ -177,7 +177,7 @@
 		}
 	}
 
-	public static class ReadResolvable implements Externalizable {
+	static public class ReadResolvable implements Externalizable {
 		String value;
 		private Object makeSureNullWorks;
 
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/Java8ClosureSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/Java8ClosureSerializerTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -47,7 +47,7 @@
 
 	public void testSerializeSerializableLambdaWithKryo () throws Exception {
 		Callable<Boolean> doNothing = (Callable<Boolean> & java.io.Serializable)( () -> true);
-		roundTrip(222, 225, doNothing);
+		roundTrip(222, doNothing);
 	}
 
 	// we must override equals as lambdas have no equals check built in...
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/Java8OptionalSerializersTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/Java8OptionalSerializersTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -51,30 +51,30 @@
 
 	@Test
 	public void testOptional () {
-		roundTrip(2, 2, new TestClass(null));
-		roundTrip(3, 3, new TestClass(Optional.<String> empty()));
-		roundTrip(6, 6, new TestClass(Optional.of("foo")));
+		roundTrip(2, new TestClass(null));
+		roundTrip(3, new TestClass(Optional.<String> empty()));
+		roundTrip(6, new TestClass(Optional.of("foo")));
 	}
 
 	@Test
 	public void testOptionalInt () {
-		roundTrip(2, 2, OptionalInt.empty());
-		roundTrip(6, 6, OptionalInt.of(Integer.MIN_VALUE));
-		roundTrip(6, 6, OptionalInt.of(Integer.MAX_VALUE));
+		roundTrip(2, OptionalInt.empty());
+		roundTrip(6, OptionalInt.of(Integer.MIN_VALUE));
+		roundTrip(6, OptionalInt.of(Integer.MAX_VALUE));
 	}
 
 	@Test
 	public void testOptionalLong () {
-		roundTrip(2, 2, OptionalLong.empty());
-		roundTrip(10, 10, OptionalLong.of(Long.MIN_VALUE));
-		roundTrip(10, 10, OptionalLong.of(Long.MAX_VALUE));
+		roundTrip(2, OptionalLong.empty());
+		roundTrip(10, OptionalLong.of(Long.MIN_VALUE));
+		roundTrip(10, OptionalLong.of(Long.MAX_VALUE));
 	}
 
 	@Test
 	public void testOptionalDouble () {
-		roundTrip(2, 2, OptionalDouble.empty());
-		roundTrip(10, 10, OptionalDouble.of(Double.MIN_VALUE));
-		roundTrip(10, 10, OptionalDouble.of(Double.MAX_VALUE));
+		roundTrip(2, OptionalDouble.empty());
+		roundTrip(10, OptionalDouble.of(Double.MIN_VALUE));
+		roundTrip(10, OptionalDouble.of(Double.MAX_VALUE));
 	}
 
 	static class TestClass {
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/Java8TimeSerializersTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/serializers/Java8TimeSerializersTest.java	2018-12-20 09:20:46.858804329 +0100
@@ -67,48 +67,48 @@
 
 	@Test
 	public void testDuration () {
-		roundTrip(14, 13, Duration.ofSeconds(-42, -23));
-		roundTrip(10, 13, Duration.ofSeconds(42, 23));
-		roundTrip(10, 13, Duration.ofSeconds(60 * 60 * 24 * 1000, -999999999));
-		roundTrip(10, 13, Duration.ofSeconds(60 * 60 * 24 * 1000, 1000000001));
+		roundTrip(14, Duration.ofSeconds(-42, -23));
+		roundTrip(10, Duration.ofSeconds(42, 23));
+		roundTrip(10, Duration.ofSeconds(60 * 60 * 24 * 1000, -999999999));
+		roundTrip(10, Duration.ofSeconds(60 * 60 * 24 * 1000, 1000000001));
 	}
 
 	@Test
 	public void testInstant () {
-		roundTrip(7, 13, Instant.ofEpochSecond(42, -23));
-		roundTrip(3, 13, Instant.ofEpochSecond(42, 23));
-		roundTrip(7, 13, Instant.ofEpochSecond(1456662120, -999999999));
-		roundTrip(7, 13, Instant.ofEpochSecond(1456662120, 1000000001));
+		roundTrip(7, Instant.ofEpochSecond(42, -23));
+		roundTrip(3, Instant.ofEpochSecond(42, 23));
+		roundTrip(7, Instant.ofEpochSecond(1456662120, -999999999));
+		roundTrip(7, Instant.ofEpochSecond(1456662120, 1000000001));
 	}
 
 	@Test
 	public void testLocalDate () {
-		roundTrip(8, 7, LocalDate.of(Year.MIN_VALUE, Month.JANUARY, 1));
-		roundTrip(5, 7, LocalDate.of(2015, 12, 31));
-		roundTrip(8, 7, LocalDate.of(Year.MAX_VALUE, Month.DECEMBER, 31));
+		roundTrip(8, LocalDate.of(Year.MIN_VALUE, Month.JANUARY, 1));
+		roundTrip(5, LocalDate.of(2015, 12, 31));
+		roundTrip(8, LocalDate.of(Year.MAX_VALUE, Month.DECEMBER, 31));
 	}
 
 	@Test
 	public void testLocalTime () {
-		roundTrip(2, 2, LocalTime.of(0, 0, 0, 0));
-		roundTrip(2, 2, LocalTime.of(1, 0, 0, 0));
-		roundTrip(3, 3, LocalTime.of(1, 1, 0, 0));
-		roundTrip(4, 4, LocalTime.of(1, 1, 1, 0));
-		roundTrip(5, 8, LocalTime.of(1, 1, 1, 1));
-		roundTrip(9, 8, LocalTime.of(23, 59, 59, 999999999));
+		roundTrip(2, LocalTime.of(0, 0, 0, 0));
+		roundTrip(2, LocalTime.of(1, 0, 0, 0));
+		roundTrip(3, LocalTime.of(1, 1, 0, 0));
+		roundTrip(4, LocalTime.of(1, 1, 1, 0));
+		roundTrip(5, LocalTime.of(1, 1, 1, 1));
+		roundTrip(9, LocalTime.of(23, 59, 59, 999999999));
 	}
 
 	@Test
 	public void testLocalDateTime () {
-		roundTrip(9, 8, LocalDateTime.of(Year.MIN_VALUE, Month.JANUARY, 1, 0, 0, 0, 0));
-		roundTrip(16, 14, LocalDateTime.of(Year.MAX_VALUE, Month.DECEMBER, 31, 23, 59, 59, 999999999));
+		roundTrip(9, LocalDateTime.of(Year.MIN_VALUE, Month.JANUARY, 1, 0, 0, 0, 0));
+		roundTrip(16, LocalDateTime.of(Year.MAX_VALUE, Month.DECEMBER, 31, 23, 59, 59, 999999999));
 	}
 
 	@Test
 	public void testZoneOffset () {
-		roundTrip(2, 2, ZoneOffset.UTC);
-		roundTrip(2, 2, ZoneOffset.MIN);
-		roundTrip(2, 2, ZoneOffset.MAX);
+		roundTrip(2, ZoneOffset.UTC);
+		roundTrip(2, ZoneOffset.MIN);
+		roundTrip(2, ZoneOffset.MAX);
 	}
 
 	@Test
@@ -118,62 +118,61 @@
 
 		// Type 2, offset-style IDs with some form of prefix, such as 'GMT+2' or 'UTC+01:00'.
 		// The recognised prefixes are 'UTC', 'GMT' and 'UT'.
-		roundTrip(10, 10, ZoneId.of("UTC+01:00"));
+		roundTrip(10, ZoneId.of("UTC+01:00"));
 
 		// Type 3, region-based IDs. A region-based ID must be of two or more characters, and not start with
 		// 'UTC', 'GMT', 'UT' '+' or '-'.
-		roundTrip(14, 14, ZoneId.of("Europe/Berlin"));
+		roundTrip(14, ZoneId.of("Europe/Berlin"));
 	}
 
 	@Test
 	public void testOffsetTime () {
-		roundTrip(3, 3, OffsetTime.of(0, 0, 0, 0, ZoneOffset.UTC));
-		roundTrip(3, 3, OffsetTime.of(1, 0, 0, 0, ZoneOffset.UTC));
-		roundTrip(4, 4, OffsetTime.of(1, 1, 0, 0, ZoneOffset.UTC));
-		roundTrip(5, 5, OffsetTime.of(1, 1, 1, 0, ZoneOffset.UTC));
-		roundTrip(6, 9, OffsetTime.of(1, 1, 1, 1, ZoneOffset.UTC));
-		roundTrip(10, 9, OffsetTime.of(23, 59, 59, 999999999, ZoneOffset.UTC));
+		roundTrip(3, OffsetTime.of(0, 0, 0, 0, ZoneOffset.UTC));
+		roundTrip(3, OffsetTime.of(1, 0, 0, 0, ZoneOffset.UTC));
+		roundTrip(4, OffsetTime.of(1, 1, 0, 0, ZoneOffset.UTC));
+		roundTrip(5, OffsetTime.of(1, 1, 1, 0, ZoneOffset.UTC));
+		roundTrip(6, OffsetTime.of(1, 1, 1, 1, ZoneOffset.UTC));
+		roundTrip(10, OffsetTime.of(23, 59, 59, 999999999, ZoneOffset.UTC));
 	}
 
 	@Test
 	public void testOffsetDateTime () {
-		roundTrip(10, 9, OffsetDateTime.of(Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0, 0, 0, ZoneOffset.UTC));
-		roundTrip(17, 15, OffsetDateTime.of(Year.MAX_VALUE, Month.DECEMBER.getValue(), 31, 23, 59, 59, 999999999, ZoneOffset.UTC));
+		roundTrip(10, OffsetDateTime.of(Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0, 0, 0, ZoneOffset.UTC));
+		roundTrip(17, OffsetDateTime.of(Year.MAX_VALUE, Month.DECEMBER.getValue(), 31, 23, 59, 59, 999999999, ZoneOffset.UTC));
 	}
 
 	@Test
 	public void testZonedDateTime () {
-		roundTrip(11, 10, ZonedDateTime.of(Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0, 0, 0, ZoneOffset.UTC));
-		roundTrip(22, 21, ZonedDateTime.of(Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0, 0, 0, ZoneId.of("Europe/Berlin")));
-		roundTrip(29, 27,
-			ZonedDateTime.of(Year.MAX_VALUE, Month.DECEMBER.getValue(), 31, 23, 59, 59, 999999999, ZoneId.of("Europe/Berlin")));
+		roundTrip(11, ZonedDateTime.of(Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0, 0, 0, ZoneOffset.UTC));
+		roundTrip(22, ZonedDateTime.of(Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0, 0, 0, ZoneId.of("Europe/Berlin")));
+		roundTrip(29, ZonedDateTime.of(Year.MAX_VALUE, Month.DECEMBER.getValue(), 31, 23, 59, 59, 999999999, ZoneId.of("Europe/Berlin")));
 	}
 
 	@Test
 	public void testYear () {
-		roundTrip(6, 5, Year.of(Year.MIN_VALUE));
-		roundTrip(6, 5, Year.of(Year.MAX_VALUE));
-		roundTrip(3, 5, Year.of(2016));
+		roundTrip(6, Year.of(Year.MIN_VALUE));
+		roundTrip(6, Year.of(Year.MAX_VALUE));
+		roundTrip(3, Year.of(2016));
 	}
 
 	@Test
 	public void testYearMonth () {
-		roundTrip(7, 6, YearMonth.of(Year.MIN_VALUE, Month.JANUARY));
-		roundTrip(7, 6, YearMonth.of(Year.MAX_VALUE, Month.DECEMBER));
-		roundTrip(4, 6, YearMonth.of(2016, Month.FEBRUARY));
+		roundTrip(7, YearMonth.of(Year.MIN_VALUE, Month.JANUARY));
+		roundTrip(7, YearMonth.of(Year.MAX_VALUE, Month.DECEMBER));
+		roundTrip(4, YearMonth.of(2016, Month.FEBRUARY));
 	}
 
 	@Test
 	public void testMonthDay () {
-		roundTrip(3, 3, MonthDay.of(Month.JANUARY, 1));
-		roundTrip(3, 3, MonthDay.of(Month.DECEMBER, 31));
+		roundTrip(3, MonthDay.of(Month.JANUARY, 1));
+		roundTrip(3, MonthDay.of(Month.DECEMBER, 31));
 	}
 
 	@Test
 	public void testPeriod () {
-		roundTrip(4, 13, Period.ZERO);
-		roundTrip(16, 13, Period.of(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE));
-		roundTrip(16, 13, Period.of(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE));
+		roundTrip(4, Period.ZERO);
+		roundTrip(16, Period.of(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE));
+		roundTrip(16, Period.of(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE));
 	}
 
 }
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/TaggedFieldSerializerTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/TaggedFieldSerializerTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -23,11 +23,11 @@
 import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
 
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.minlog.Log;
 import org.junit.Assert;
 
+import com.esotericsoftware.kryo.SerializerFactory.TaggedFieldSerializerFactory;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
 import com.esotericsoftware.kryo.serializers.TaggedFieldSerializer;
 import com.esotericsoftware.kryo.serializers.TaggedFieldSerializer.Tag;
 
@@ -47,7 +47,7 @@
 		kryo.setDefaultSerializer(TaggedFieldSerializer.class);
 		kryo.register(TestClass.class);
 		kryo.register(AnotherClass.class);
-		TestClass object2 = roundTrip(57, 75, object1);
+		TestClass object2 = roundTrip(57, object1);
 		assertTrue(object2.ignored == 0);
 	}
 
@@ -61,7 +61,7 @@
 		serializer.removeField("text");
 		kryo.register(TestClass.class, serializer);
 		kryo.register(AnotherClass.class, new TaggedFieldSerializer(kryo, AnotherClass.class));
-		roundTrip(39, 55, object1);
+		roundTrip(39, object1);
 
 		kryo.register(TestClass.class, new TaggedFieldSerializer(kryo, TestClass.class));
 		Object object2 = kryo.readClassAndObject(input);
@@ -69,8 +69,9 @@
 	}
 
 	/** Serializes an array with a Class with two tagged fields. Then deserializes it using a serializer that has removed some 
-	 * fields to simulate a past version of the compiled application. An array is used to ensure subsequent bytes in the stream 
-	 * are unaffected.*/
+	 * fields to simulate a past version of the compiled application. An array is used to ensure subsequent bytes in the stream are
+	 * unaffected. */
+	@SuppressWarnings("synthetic-access")
 	public void testForwardCompatibility () {
 		FutureClass futureObject = new FutureClass();
 		futureObject.value = 3;
@@ -89,15 +90,16 @@
 		futureArray[0] = futureObject;
 		futureArray[1] = new TestClass();
 
-		kryo.setDefaultSerializer(TaggedFieldSerializer.class);
-		kryo.getTaggedFieldSerializerConfig().setSkipUnknownTags(true);
+		TaggedFieldSerializerFactory factory = new TaggedFieldSerializerFactory();
+		factory.getConfig().setSkipUnknownTags(true);
+		kryo.setDefaultSerializer(factory);
 		kryo.register(TestClass.class);
 		kryo.register(Object[].class);
-		TaggedFieldSerializer futureSerializer = new TaggedFieldSerializer(kryo, FutureClass.class);
-		futureSerializer.setSkipUnknownTags(true);
+		TaggedFieldSerializer<FutureClass> futureSerializer = new TaggedFieldSerializer(kryo, FutureClass.class);
+		futureSerializer.getConfig().setSkipUnknownTags(true);
 		kryo.register(FutureClass.class, futureSerializer);
 		TaggedFieldSerializer futureSerializer2 = new TaggedFieldSerializer(kryo, FutureClass2.class);
-		futureSerializer2.setSkipUnknownTags(true);
+		futureSerializer.getConfig().setSkipUnknownTags(true);
 		kryo.register(FutureClass2.class, futureSerializer2);
 
 		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
@@ -106,12 +108,12 @@
 		output.flush();
 		byte[] futureArrayData = outStream.toByteArray();
 
-		TaggedFieldSerializer presentSerializer = new TaggedFieldSerializer(kryo, FutureClass.class);
-		presentSerializer.setSkipUnknownTags(true);
+		TaggedFieldSerializer<FutureClass> presentSerializer = new TaggedFieldSerializer(kryo, FutureClass.class);
+		presentSerializer.getConfig().setSkipUnknownTags(true);
 		presentSerializer.removeField("futureString"); // simulate past version of application
 		kryo.register(FutureClass.class, presentSerializer);
-		TaggedFieldSerializer presentSerializer2 = new TaggedFieldSerializer(kryo, FutureClass2.class);
-		presentSerializer2.setSkipUnknownTags(true);
+		TaggedFieldSerializer<FutureClass2> presentSerializer2 = new TaggedFieldSerializer(kryo, FutureClass2.class);
+		presentSerializer2.getConfig().setSkipUnknownTags(true);
 		presentSerializer2.removeField("zzz"); // simulate past version of application
 		presentSerializer2.removeField("fc2"); // simulate past version of application
 		kryo.register(FutureClass2.class, presentSerializer2);
@@ -130,7 +132,9 @@
 	public void testInvalidTagValue () {
 		Kryo newKryo = new Kryo();
 		newKryo.setReferences(true);
-		newKryo.getTaggedFieldSerializerConfig().setSkipUnknownTags(true);
+		TaggedFieldSerializerFactory factory = new TaggedFieldSerializerFactory();
+		factory.getConfig().setSkipUnknownTags(true);
+		kryo.setDefaultSerializer(factory);
 		newKryo.setDefaultSerializer(TaggedFieldSerializer.class);
 
 		boolean receivedIAE = false;
@@ -177,7 +181,7 @@
 		@Tag(1) String value;
 	}
 
-	private static class FutureClass {
+	static private class FutureClass {
 		@Tag(0) public Integer value;
 		@Tag(1) public FutureClass2 futureClass2;
 		@Tag(value=2, annexed = true) public String futureString = "unchanged";
@@ -216,7 +220,7 @@
 		}
 	}
 	
-	private static class FutureClass2 {
+	static private class FutureClass2 {
 		@Tag(0) public String text = "something";
 		@Tag(1) public int moo = 120;
 		@Tag(2) public long moo2 = 1234120;
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/TestKryoMain1.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/TestKryoMain1.java	2018-12-20 09:20:46.854804308 +0100
@@ -12,7 +12,7 @@
 
 public class TestKryoMain1 {
 
-	public static void main (String[] args) throws IOException {
+	static public void main (String[] args) throws IOException {
 		Log.TRACE();
 
 		Kryo kryo = new Kryo();
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/TestKryoMainNate.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/TestKryoMainNate.java	2018-12-20 09:20:46.854804308 +0100
@@ -12,7 +12,7 @@
 
 public class TestKryoMainNate {
 
-	public static void main (String[] args) throws IOException {
+	static public void main (String[] args) throws IOException {
 		Log.DEBUG();
 
 		Kryo kryo = new Kryo();
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/UnsafeInputOutputTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/UnsafeInputOutputTest.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,832 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Random;
-
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.io.UnsafeInput;
-import com.esotericsoftware.kryo.io.UnsafeOutput;
-
-/** @author Nathan Sweet <misc@n4te.com> */
-public class UnsafeInputOutputTest extends KryoTestCase {
-	public void testOutputStream () throws IOException {
-		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-		UnsafeOutput output = new UnsafeOutput(buffer, 2);
-		output.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26});
-		output.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46});
-		output.writeBytes(new byte[] {51, 52, 53, 54, 55, 56, 57, 58});
-		output.writeBytes(new byte[] {61, 62, 63, 64, 65});
-		output.flush();
-
-		assertEquals(new byte[] { //
-			11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, //
-			31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, //
-			51, 52, 53, 54, 55, 56, 57, 58, //
-			61, 62, 63, 64, 65}, buffer.toByteArray());
-	}
-
-	public void testInputStream () throws IOException {
-		byte[] bytes = new byte[] { //
-			11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, //
-			31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, //
-			51, 52, 53, 54, 55, 56, 57, 58, //
-			61, 62, 63, 64, 65};
-		ByteArrayInputStream buffer = new ByteArrayInputStream(bytes);
-		Input input = new UnsafeInput(buffer, 2);
-		byte[] temp = new byte[1024];
-		int count = input.read(temp, 512, bytes.length);
-		assertEquals(bytes.length, count);
-		byte[] temp2 = new byte[count];
-		System.arraycopy(temp, 512, temp2, 0, count);
-		assertEquals(bytes, temp2);
-
-		input = new UnsafeInput(bytes);
-		count = input.read(temp, 512, 512);
-		assertEquals(bytes.length, count);
-		temp2 = new byte[count];
-		System.arraycopy(temp, 512, temp2, 0, count);
-		assertEquals(bytes, temp2);
-	}
-
-	public void testWriteBytes () throws IOException {
-		UnsafeOutput buffer = new UnsafeOutput(512);
-		buffer.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26});
-		buffer.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46});
-		buffer.writeByte(51);
-		buffer.writeBytes(new byte[] {52, 53, 54, 55, 56, 57, 58});
-		buffer.writeByte(61);
-		buffer.writeByte(62);
-		buffer.writeByte(63);
-		buffer.writeByte(64);
-		buffer.writeByte(65);
-		buffer.flush();
-
-		assertEquals(new byte[] { //
-			11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, //
-			31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, //
-			51, 52, 53, 54, 55, 56, 57, 58, //
-			61, 62, 63, 64, 65}, buffer.toBytes());
-	}
-
-	public void testStrings () throws IOException {
-		runStringTest(new UnsafeOutput(4096));
-		runStringTest(new UnsafeOutput(897));
-		runStringTest(new UnsafeOutput(new ByteArrayOutputStream()));
-
-		UnsafeOutput write = new UnsafeOutput(21);
-		String value = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234";
-		write.writeString(value);
-		Input read = new UnsafeInput(write.toBytes());
-		assertEquals(value, read.readString());
-
-		runStringTest(127);
-		runStringTest(256);
-		runStringTest(1024 * 1023);
-		runStringTest(1024 * 1024);
-		runStringTest(1024 * 1025);
-		runStringTest(1024 * 1026);
-		runStringTest(1024 * 1024 * 2);
-	}
-
-	public void runStringTest (int length) throws IOException {
-		UnsafeOutput write = new UnsafeOutput(1024, -1);
-		StringBuilder buffer = new StringBuilder();
-		for (int i = 0; i < length; i++)
-			buffer.append((char)i);
-
-		String value = buffer.toString();
-		write.writeString(value);
-		write.writeString(value);
-		Input read = new UnsafeInput(write.toBytes());
-		assertEquals(value, read.readString());
-		assertEquals(value, read.readStringBuilder().toString());
-
-		write.clear();
-		write.writeString(buffer);
-		write.writeString(buffer);
-		read = new UnsafeInput(write.toBytes());
-		assertEquals(value, read.readStringBuilder().toString());
-		assertEquals(value, read.readString());
-
-		if (length <= 127) {
-			write.clear();
-			write.writeAscii(value);
-			write.writeAscii(value);
-			read = new UnsafeInput(write.toBytes());
-			assertEquals(value, read.readStringBuilder().toString());
-			assertEquals(value, read.readString());
-		}
-	}
-
-	public void runStringTest (UnsafeOutput write) throws IOException {
-		String value1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*";
-		String value2 = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234";
-
-		write.writeString("");
-		write.writeString("1");
-		write.writeString("22");
-		write.writeString("uno");
-		write.writeString("dos");
-		write.writeString("tres");
-		write.writeString(null);
-		write.writeString(value1);
-		write.writeString(value2);
-		for (int i = 0; i < 127; i++)
-			write.writeString(String.valueOf((char)i));
-		for (int i = 0; i < 127; i++)
-			write.writeString(String.valueOf((char)i) + "abc");
-
-		Input read = new UnsafeInput(write.toBytes());
-		assertEquals("", read.readString());
-		assertEquals("1", read.readString());
-		assertEquals("22", read.readString());
-		assertEquals("uno", read.readString());
-		assertEquals("dos", read.readString());
-		assertEquals("tres", read.readString());
-		assertEquals(null, read.readString());
-		assertEquals(value1, read.readString());
-		assertEquals(value2, read.readString());
-		for (int i = 0; i < 127; i++)
-			assertEquals(String.valueOf((char)i), read.readString());
-		for (int i = 0; i < 127; i++)
-			assertEquals(String.valueOf((char)i) + "abc", read.readString());
-
-		read.rewind();
-		assertEquals("", read.readStringBuilder().toString());
-		assertEquals("1", read.readStringBuilder().toString());
-		assertEquals("22", read.readStringBuilder().toString());
-		assertEquals("uno", read.readStringBuilder().toString());
-		assertEquals("dos", read.readStringBuilder().toString());
-		assertEquals("tres", read.readStringBuilder().toString());
-		assertEquals(null, read.readStringBuilder());
-		assertEquals(value1, read.readStringBuilder().toString());
-		assertEquals(value2, read.readStringBuilder().toString());
-		for (int i = 0; i < 127; i++)
-			assertEquals(String.valueOf((char)i), read.readStringBuilder().toString());
-		for (int i = 0; i < 127; i++)
-			assertEquals(String.valueOf((char)i) + "abc", read.readStringBuilder().toString());
-	}
-
-	public void testCanReadInt () throws IOException {
-		UnsafeOutput write = new UnsafeOutput(new ByteArrayOutputStream());
-
-		Input read = new UnsafeInput(write.toBytes());
-		assertEquals(false, read.canReadInt());
-
-		write.writeVarInt(400, true);
-
-		read = new UnsafeInput(write.toBytes());
-		assertEquals(true, read.canReadInt());
-		read.setLimit(read.limit() - 1);
-		assertEquals(false, read.canReadInt());
-	}
-
-	public void testInts () throws IOException {
-		runIntTest(new UnsafeOutput(4096));
-		runIntTest(new UnsafeOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runIntTest (UnsafeOutput write) throws IOException {
-		write.supportVarInts(false);
-
-		write.writeInt(0);
-		write.writeInt(63);
-		write.writeInt(64);
-		write.writeInt(127);
-		write.writeInt(128);
-		write.writeInt(8192);
-		write.writeInt(16384);
-		write.writeInt(2097151);
-		write.writeInt(1048575);
-		write.writeInt(134217727);
-		write.writeInt(268435455);
-		write.writeInt(134217728);
-		write.writeInt(268435456);
-		write.writeInt(-2097151);
-		write.writeInt(-1048575);
-		write.writeInt(-134217727);
-		write.writeInt(-268435455);
-		write.writeInt(-134217728);
-		write.writeInt(-268435456);
-
-		write.supportVarInts(true);
-
-		assertEquals(1, write.writeInt(0, true));
-		assertEquals(1, write.writeInt(0, false));
-		assertEquals(1, write.writeInt(63, true));
-		assertEquals(1, write.writeInt(63, false));
-		assertEquals(1, write.writeInt(64, true));
-		assertEquals(2, write.writeInt(64, false));
-		assertEquals(1, write.writeInt(127, true));
-		assertEquals(2, write.writeInt(127, false));
-		assertEquals(2, write.writeInt(128, true));
-		assertEquals(2, write.writeInt(128, false));
-		assertEquals(2, write.writeInt(8191, true));
-		assertEquals(2, write.writeInt(8191, false));
-		assertEquals(2, write.writeInt(8192, true));
-		assertEquals(3, write.writeInt(8192, false));
-		assertEquals(2, write.writeInt(16383, true));
-		assertEquals(3, write.writeInt(16383, false));
-		assertEquals(3, write.writeInt(16384, true));
-		assertEquals(3, write.writeInt(16384, false));
-		assertEquals(3, write.writeInt(2097151, true));
-		assertEquals(4, write.writeInt(2097151, false));
-		assertEquals(3, write.writeInt(1048575, true));
-		assertEquals(3, write.writeInt(1048575, false));
-		assertEquals(4, write.writeInt(134217727, true));
-		assertEquals(4, write.writeInt(134217727, false));
-		assertEquals(4, write.writeInt(268435455, true));
-		assertEquals(5, write.writeInt(268435455, false));
-		assertEquals(4, write.writeInt(134217728, true));
-		assertEquals(5, write.writeInt(134217728, false));
-		assertEquals(5, write.writeInt(268435456, true));
-		assertEquals(5, write.writeInt(268435456, false));
-		assertEquals(1, write.writeInt(-64, false));
-		assertEquals(5, write.writeInt(-64, true));
-		assertEquals(2, write.writeInt(-65, false));
-		assertEquals(5, write.writeInt(-65, true));
-		assertEquals(2, write.writeInt(-8192, false));
-		assertEquals(5, write.writeInt(-8192, true));
-		assertEquals(3, write.writeInt(-1048576, false));
-		assertEquals(5, write.writeInt(-1048576, true));
-		assertEquals(4, write.writeInt(-134217728, false));
-		assertEquals(5, write.writeInt(-134217728, true));
-		assertEquals(5, write.writeInt(-134217729, false));
-		assertEquals(5, write.writeInt(-134217729, true));
-		assertEquals(5, write.writeInt(1000000000, false));
-		assertEquals(5, write.writeInt(1000000000, true));
-		assertEquals(5, write.writeInt(Integer.MAX_VALUE - 1, false));
-		assertEquals(5, write.writeInt(Integer.MAX_VALUE - 1, true));
-		assertEquals(5, write.writeInt(Integer.MAX_VALUE, false));
-		assertEquals(5, write.writeInt(Integer.MAX_VALUE, true));
-
-		UnsafeInput read = new UnsafeInput(write.toBytes());
-		assertEquals(0, read.readInt());
-		assertEquals(63, read.readInt());
-		assertEquals(64, read.readInt());
-		assertEquals(127, read.readInt());
-		assertEquals(128, read.readInt());
-		assertEquals(8192, read.readInt());
-		assertEquals(16384, read.readInt());
-		assertEquals(2097151, read.readInt());
-		assertEquals(1048575, read.readInt());
-		assertEquals(134217727, read.readInt());
-		assertEquals(268435455, read.readInt());
-		assertEquals(134217728, read.readInt());
-		assertEquals(268435456, read.readInt());
-		assertEquals(-2097151, read.readInt());
-		assertEquals(-1048575, read.readInt());
-		assertEquals(-134217727, read.readInt());
-		assertEquals(-268435455, read.readInt());
-		assertEquals(-134217728, read.readInt());
-		assertEquals(-268435456, read.readInt());
-		assertEquals(true, read.canReadInt());
-		assertEquals(true, read.canReadInt());
-		assertEquals(true, read.canReadInt());
-
-		read.setVarIntsEnabled(true);
-
-		assertEquals(0, read.readInt(true));
-		assertEquals(0, read.readInt(false));
-		assertEquals(63, read.readInt(true));
-		assertEquals(63, read.readInt(false));
-		assertEquals(64, read.readInt(true));
-		assertEquals(64, read.readInt(false));
-		assertEquals(127, read.readInt(true));
-		assertEquals(127, read.readInt(false));
-		assertEquals(128, read.readInt(true));
-		assertEquals(128, read.readInt(false));
-		assertEquals(8191, read.readInt(true));
-		assertEquals(8191, read.readInt(false));
-		assertEquals(8192, read.readInt(true));
-		assertEquals(8192, read.readInt(false));
-		assertEquals(16383, read.readInt(true));
-		assertEquals(16383, read.readInt(false));
-		assertEquals(16384, read.readInt(true));
-		assertEquals(16384, read.readInt(false));
-		assertEquals(2097151, read.readInt(true));
-		assertEquals(2097151, read.readInt(false));
-		assertEquals(1048575, read.readInt(true));
-		assertEquals(1048575, read.readInt(false));
-		assertEquals(134217727, read.readInt(true));
-		assertEquals(134217727, read.readInt(false));
-		assertEquals(268435455, read.readInt(true));
-		assertEquals(268435455, read.readInt(false));
-		assertEquals(134217728, read.readInt(true));
-		assertEquals(134217728, read.readInt(false));
-		assertEquals(268435456, read.readInt(true));
-		assertEquals(268435456, read.readInt(false));
-		assertEquals(-64, read.readInt(false));
-		assertEquals(-64, read.readInt(true));
-		assertEquals(-65, read.readInt(false));
-		assertEquals(-65, read.readInt(true));
-		assertEquals(-8192, read.readInt(false));
-		assertEquals(-8192, read.readInt(true));
-		assertEquals(-1048576, read.readInt(false));
-		assertEquals(-1048576, read.readInt(true));
-		assertEquals(-134217728, read.readInt(false));
-		assertEquals(-134217728, read.readInt(true));
-		assertEquals(-134217729, read.readInt(false));
-		assertEquals(-134217729, read.readInt(true));
-		assertEquals(1000000000, read.readInt(false));
-		assertEquals(1000000000, read.readInt(true));
-		assertEquals(Integer.MAX_VALUE - 1, read.readInt(false));
-		assertEquals(Integer.MAX_VALUE - 1, read.readInt(true));
-		assertEquals(Integer.MAX_VALUE, read.readInt(false));
-		assertEquals(Integer.MAX_VALUE, read.readInt(true));
-		assertEquals(false, read.canReadInt());
-
-		Random random = new Random();
-		for (int i = 0; i < 10000; i++) {
-			int value = random.nextInt();
-			write.clear();
-			write.writeInt(value);
-			write.writeInt(value, true);
-			write.writeInt(value, false);
-			read.setBuffer(write.toBytes());
-			assertEquals(value, read.readInt());
-			assertEquals(value, read.readInt(true));
-			assertEquals(value, read.readInt(false));
-		}
-	}
-
-	public void testLongs () throws IOException {
-		runLongTest(new UnsafeOutput(4096));
-		runLongTest(new UnsafeOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runLongTest (UnsafeOutput write) throws IOException {
-		write.supportVarInts(false);
-
-		write.writeLong(0);
-		write.writeLong(63);
-		write.writeLong(64);
-		write.writeLong(127);
-		write.writeLong(128);
-		write.writeLong(8192);
-		write.writeLong(16384);
-		write.writeLong(2097151);
-		write.writeLong(1048575);
-		write.writeLong(134217727);
-		write.writeLong(268435455);
-		write.writeLong(134217728);
-		write.writeLong(268435456);
-		write.writeLong(-2097151);
-		write.writeLong(-1048575);
-		write.writeLong(-134217727);
-		write.writeLong(-268435455);
-		write.writeLong(-134217728);
-		write.writeLong(-268435456);
-
-		write.supportVarInts(true);
-
-		assertEquals(1, write.writeLong(0, true));
-		assertEquals(1, write.writeLong(0, false));
-		assertEquals(1, write.writeLong(63, true));
-		assertEquals(1, write.writeLong(63, false));
-		assertEquals(1, write.writeLong(64, true));
-		assertEquals(2, write.writeLong(64, false));
-		assertEquals(1, write.writeLong(127, true));
-		assertEquals(2, write.writeLong(127, false));
-		assertEquals(2, write.writeLong(128, true));
-		assertEquals(2, write.writeLong(128, false));
-		assertEquals(2, write.writeLong(8191, true));
-		assertEquals(2, write.writeLong(8191, false));
-		assertEquals(2, write.writeLong(8192, true));
-		assertEquals(3, write.writeLong(8192, false));
-		assertEquals(2, write.writeLong(16383, true));
-		assertEquals(3, write.writeLong(16383, false));
-		assertEquals(3, write.writeLong(16384, true));
-		assertEquals(3, write.writeLong(16384, false));
-		assertEquals(3, write.writeLong(2097151, true));
-		assertEquals(4, write.writeLong(2097151, false));
-		assertEquals(3, write.writeLong(1048575, true));
-		assertEquals(3, write.writeLong(1048575, false));
-		assertEquals(4, write.writeLong(134217727, true));
-		assertEquals(4, write.writeLong(134217727, false));
-		assertEquals(4, write.writeLong(268435455l, true));
-		assertEquals(5, write.writeLong(268435455l, false));
-		assertEquals(4, write.writeLong(134217728l, true));
-		assertEquals(5, write.writeLong(134217728l, false));
-		assertEquals(5, write.writeLong(268435456l, true));
-		assertEquals(5, write.writeLong(268435456l, false));
-		assertEquals(1, write.writeLong(-64, false));
-		assertEquals(9, write.writeLong(-64, true));
-		assertEquals(2, write.writeLong(-65, false));
-		assertEquals(9, write.writeLong(-65, true));
-		assertEquals(2, write.writeLong(-8192, false));
-		assertEquals(9, write.writeLong(-8192, true));
-		assertEquals(3, write.writeLong(-1048576, false));
-		assertEquals(9, write.writeLong(-1048576, true));
-		assertEquals(4, write.writeLong(-134217728, false));
-		assertEquals(9, write.writeLong(-134217728, true));
-		assertEquals(5, write.writeLong(-134217729, false));
-		assertEquals(9, write.writeLong(-134217729, true));
-
-		UnsafeInput read = new UnsafeInput(write.toBytes());
-		assertEquals(0, read.readLong());
-		assertEquals(63, read.readLong());
-		assertEquals(64, read.readLong());
-		assertEquals(127, read.readLong());
-		assertEquals(128, read.readLong());
-		assertEquals(8192, read.readLong());
-		assertEquals(16384, read.readLong());
-		assertEquals(2097151, read.readLong());
-		assertEquals(1048575, read.readLong());
-		assertEquals(134217727, read.readLong());
-		assertEquals(268435455, read.readLong());
-		assertEquals(134217728, read.readLong());
-		assertEquals(268435456, read.readLong());
-		assertEquals(-2097151, read.readLong());
-		assertEquals(-1048575, read.readLong());
-		assertEquals(-134217727, read.readLong());
-		assertEquals(-268435455, read.readLong());
-		assertEquals(-134217728, read.readLong());
-		assertEquals(-268435456, read.readLong());
-
-		read.setVarIntsEnabled(true);
-
-		assertEquals(0, read.readLong(true));
-		assertEquals(0, read.readLong(false));
-		assertEquals(63, read.readLong(true));
-		assertEquals(63, read.readLong(false));
-		assertEquals(64, read.readLong(true));
-		assertEquals(64, read.readLong(false));
-		assertEquals(127, read.readLong(true));
-		assertEquals(127, read.readLong(false));
-		assertEquals(128, read.readLong(true));
-		assertEquals(128, read.readLong(false));
-		assertEquals(8191, read.readLong(true));
-		assertEquals(8191, read.readLong(false));
-		assertEquals(8192, read.readLong(true));
-		assertEquals(8192, read.readLong(false));
-		assertEquals(16383, read.readLong(true));
-		assertEquals(16383, read.readLong(false));
-		assertEquals(16384, read.readLong(true));
-		assertEquals(16384, read.readLong(false));
-		assertEquals(2097151, read.readLong(true));
-		assertEquals(2097151, read.readLong(false));
-		assertEquals(1048575, read.readLong(true));
-		assertEquals(1048575, read.readLong(false));
-		assertEquals(134217727, read.readLong(true));
-		assertEquals(134217727, read.readLong(false));
-		assertEquals(268435455, read.readLong(true));
-		assertEquals(268435455, read.readLong(false));
-		assertEquals(134217728, read.readLong(true));
-		assertEquals(134217728, read.readLong(false));
-		assertEquals(268435456, read.readLong(true));
-		assertEquals(268435456, read.readLong(false));
-		assertEquals(-64, read.readLong(false));
-		assertEquals(-64, read.readLong(true));
-		assertEquals(-65, read.readLong(false));
-		assertEquals(-65, read.readLong(true));
-		assertEquals(-8192, read.readLong(false));
-		assertEquals(-8192, read.readLong(true));
-		assertEquals(-1048576, read.readLong(false));
-		assertEquals(-1048576, read.readLong(true));
-		assertEquals(-134217728, read.readLong(false));
-		assertEquals(-134217728, read.readLong(true));
-		assertEquals(-134217729, read.readLong(false));
-		assertEquals(-134217729, read.readLong(true));
-
-		Random random = new Random();
-		for (int i = 0; i < 10000; i++) {
-			long value = random.nextLong();
-			write.clear();
-			write.writeLong(value);
-			write.writeLong(value, true);
-			write.writeLong(value, false);
-			read.setBuffer(write.toBytes());
-			assertEquals("Element " + i, value, read.readLong());
-			assertEquals("Element " + i, value, read.readLong(true));
-			assertEquals("Element " + i, value, read.readLong(false));
-		}
-	}
-
-	public void testShorts () throws IOException {
-		runShortTest(new UnsafeOutput(4096));
-		runShortTest(new UnsafeOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runShortTest (UnsafeOutput write) throws IOException {
-		write.writeShort(0);
-		write.writeShort(63);
-		write.writeShort(64);
-		write.writeShort(127);
-		write.writeShort(128);
-		write.writeShort(8192);
-		write.writeShort(16384);
-		write.writeShort(32767);
-		write.writeShort(-63);
-		write.writeShort(-64);
-		write.writeShort(-127);
-		write.writeShort(-128);
-		write.writeShort(-8192);
-		write.writeShort(-16384);
-		write.writeShort(-32768);
-
-		Input read = new UnsafeInput(write.toBytes());
-		assertEquals(0, read.readShort());
-		assertEquals(63, read.readShort());
-		assertEquals(64, read.readShort());
-		assertEquals(127, read.readShort());
-		assertEquals(128, read.readShort());
-		assertEquals(8192, read.readShort());
-		assertEquals(16384, read.readShort());
-		assertEquals(32767, read.readShort());
-		assertEquals(-63, read.readShort());
-		assertEquals(-64, read.readShort());
-		assertEquals(-127, read.readShort());
-		assertEquals(-128, read.readShort());
-		assertEquals(-8192, read.readShort());
-		assertEquals(-16384, read.readShort());
-		assertEquals(-32768, read.readShort());
-	}
-
-	public void testFloats () throws IOException {
-		runFloatTest(new UnsafeOutput(4096));
-		runFloatTest(new UnsafeOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runFloatTest (UnsafeOutput write) throws IOException {
-		write.writeFloat(0);
-		write.writeFloat(63);
-		write.writeFloat(64);
-		write.writeFloat(127);
-		write.writeFloat(128);
-		write.writeFloat(8192);
-		write.writeFloat(16384);
-		write.writeFloat(32767);
-		write.writeFloat(-63);
-		write.writeFloat(-64);
-		write.writeFloat(-127);
-		write.writeFloat(-128);
-		write.writeFloat(-8192);
-		write.writeFloat(-16384);
-		write.writeFloat(-32768);
-		assertEquals(4, write.writeFloat(0, 1000, true));
-		assertEquals(4, write.writeFloat(0, 1000, false));
-		assertEquals(4, write.writeFloat(63, 1000, true));
-		assertEquals(4, write.writeFloat(63, 1000, false));
-		assertEquals(4, write.writeFloat(64, 1000, true));
-		assertEquals(4, write.writeFloat(64, 1000, false));
-		assertEquals(4, write.writeFloat(127, 1000, true));
-		assertEquals(4, write.writeFloat(127, 1000, false));
-		assertEquals(4, write.writeFloat(128, 1000, true));
-		assertEquals(4, write.writeFloat(128, 1000, false));
-		assertEquals(4, write.writeFloat(8191, 1000, true));
-		assertEquals(4, write.writeFloat(8191, 1000, false));
-		assertEquals(4, write.writeFloat(8192, 1000, true));
-		assertEquals(4, write.writeFloat(8192, 1000, false));
-		assertEquals(4, write.writeFloat(16383, 1000, true));
-		assertEquals(4, write.writeFloat(16383, 1000, false));
-		assertEquals(4, write.writeFloat(16384, 1000, true));
-		assertEquals(4, write.writeFloat(16384, 1000, false));
-		assertEquals(4, write.writeFloat(32767, 1000, true));
-		assertEquals(4, write.writeFloat(32767, 1000, false));
-		assertEquals(4, write.writeFloat(-64, 1000, false));
-		assertEquals(4, write.writeFloat(-64, 1000, true));
-		assertEquals(4, write.writeFloat(-65, 1000, false));
-		assertEquals(4, write.writeFloat(-65, 1000, true));
-		assertEquals(4, write.writeFloat(-8192, 1000, false));
-		assertEquals(4, write.writeFloat(-8192, 1000, true));
-
-		Input read = new UnsafeInput(write.toBytes());
-		assertEquals(read.readFloat(), 0f);
-		assertEquals(read.readFloat(), 63f);
-		assertEquals(read.readFloat(), 64f);
-		assertEquals(read.readFloat(), 127f);
-		assertEquals(read.readFloat(), 128f);
-		assertEquals(read.readFloat(), 8192f);
-		assertEquals(read.readFloat(), 16384f);
-		assertEquals(read.readFloat(), 32767f);
-		assertEquals(read.readFloat(), -63f);
-		assertEquals(read.readFloat(), -64f);
-		assertEquals(read.readFloat(), -127f);
-		assertEquals(read.readFloat(), -128f);
-		assertEquals(read.readFloat(), -8192f);
-		assertEquals(read.readFloat(), -16384f);
-		assertEquals(read.readFloat(), -32768f);
-		assertEquals(read.readFloat(1000, true), 0f);
-		assertEquals(read.readFloat(1000, false), 0f);
-		assertEquals(read.readFloat(1000, true), 63f);
-		assertEquals(read.readFloat(1000, false), 63f);
-		assertEquals(read.readFloat(1000, true), 64f);
-		assertEquals(read.readFloat(1000, false), 64f);
-		assertEquals(read.readFloat(1000, true), 127f);
-		assertEquals(read.readFloat(1000, false), 127f);
-		assertEquals(read.readFloat(1000, true), 128f);
-		assertEquals(read.readFloat(1000, false), 128f);
-		assertEquals(read.readFloat(1000, true), 8191f);
-		assertEquals(read.readFloat(1000, false), 8191f);
-		assertEquals(read.readFloat(1000, true), 8192f);
-		assertEquals(read.readFloat(1000, false), 8192f);
-		assertEquals(read.readFloat(1000, true), 16383f);
-		assertEquals(read.readFloat(1000, false), 16383f);
-		assertEquals(read.readFloat(1000, true), 16384f);
-		assertEquals(read.readFloat(1000, false), 16384f);
-		assertEquals(read.readFloat(1000, true), 32767f);
-		assertEquals(read.readFloat(1000, false), 32767f);
-		assertEquals(read.readFloat(1000, false), -64f);
-		assertEquals(read.readFloat(1000, true), -64f);
-		assertEquals(read.readFloat(1000, false), -65f);
-		assertEquals(read.readFloat(1000, true), -65f);
-		assertEquals(read.readFloat(1000, false), -8192f);
-		assertEquals(read.readFloat(1000, true), -8192f);
-	}
-
-	public void testDoubles () throws IOException {
-		runDoubleTest(new UnsafeOutput(4096));
-		runDoubleTest(new UnsafeOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runDoubleTest (UnsafeOutput write) throws IOException {
-		write.writeDouble(0);
-		write.writeDouble(63);
-		write.writeDouble(64);
-		write.writeDouble(127);
-		write.writeDouble(128);
-		write.writeDouble(8192);
-		write.writeDouble(16384);
-		write.writeDouble(32767);
-		write.writeDouble(-63);
-		write.writeDouble(-64);
-		write.writeDouble(-127);
-		write.writeDouble(-128);
-		write.writeDouble(-8192);
-		write.writeDouble(-16384);
-		write.writeDouble(-32768);
-		assertEquals(8, write.writeDouble(0, 1000, true));
-		assertEquals(8, write.writeDouble(0, 1000, false));
-		assertEquals(8, write.writeDouble(63, 1000, true));
-		assertEquals(8, write.writeDouble(63, 1000, false));
-		assertEquals(8, write.writeDouble(64, 1000, true));
-		assertEquals(8, write.writeDouble(64, 1000, false));
-		assertEquals(8, write.writeDouble(127, 1000, true));
-		assertEquals(8, write.writeDouble(127, 1000, false));
-		assertEquals(8, write.writeDouble(128, 1000, true));
-		assertEquals(8, write.writeDouble(128, 1000, false));
-		assertEquals(8, write.writeDouble(8191, 1000, true));
-		assertEquals(8, write.writeDouble(8191, 1000, false));
-		assertEquals(8, write.writeDouble(8192, 1000, true));
-		assertEquals(8, write.writeDouble(8192, 1000, false));
-		assertEquals(8, write.writeDouble(16383, 1000, true));
-		assertEquals(8, write.writeDouble(16383, 1000, false));
-		assertEquals(8, write.writeDouble(16384, 1000, true));
-		assertEquals(8, write.writeDouble(16384, 1000, false));
-		assertEquals(8, write.writeDouble(32767, 1000, true));
-		assertEquals(8, write.writeDouble(32767, 1000, false));
-		assertEquals(8, write.writeDouble(-64, 1000, false));
-		assertEquals(8, write.writeDouble(-64, 1000, true));
-		assertEquals(8, write.writeDouble(-65, 1000, false));
-		assertEquals(8, write.writeDouble(-65, 1000, true));
-		assertEquals(8, write.writeDouble(-8192, 1000, false));
-		assertEquals(8, write.writeDouble(-8192, 1000, true));
-		write.writeDouble(1.23456d);
-
-		Input read = new UnsafeInput(write.toBytes());
-		assertEquals(read.readDouble(), 0d);
-		assertEquals(read.readDouble(), 63d);
-		assertEquals(read.readDouble(), 64d);
-		assertEquals(read.readDouble(), 127d);
-		assertEquals(read.readDouble(), 128d);
-		assertEquals(read.readDouble(), 8192d);
-		assertEquals(read.readDouble(), 16384d);
-		assertEquals(read.readDouble(), 32767d);
-		assertEquals(read.readDouble(), -63d);
-		assertEquals(read.readDouble(), -64d);
-		assertEquals(read.readDouble(), -127d);
-		assertEquals(read.readDouble(), -128d);
-		assertEquals(read.readDouble(), -8192d);
-		assertEquals(read.readDouble(), -16384d);
-		assertEquals(read.readDouble(), -32768d);
-		assertEquals(read.readDouble(1000, true), 0d);
-		assertEquals(read.readDouble(1000, false), 0d);
-		assertEquals(read.readDouble(1000, true), 63d);
-		assertEquals(read.readDouble(1000, false), 63d);
-		assertEquals(read.readDouble(1000, true), 64d);
-		assertEquals(read.readDouble(1000, false), 64d);
-		assertEquals(read.readDouble(1000, true), 127d);
-		assertEquals(read.readDouble(1000, false), 127d);
-		assertEquals(read.readDouble(1000, true), 128d);
-		assertEquals(read.readDouble(1000, false), 128d);
-		assertEquals(read.readDouble(1000, true), 8191d);
-		assertEquals(read.readDouble(1000, false), 8191d);
-		assertEquals(read.readDouble(1000, true), 8192d);
-		assertEquals(read.readDouble(1000, false), 8192d);
-		assertEquals(read.readDouble(1000, true), 16383d);
-		assertEquals(read.readDouble(1000, false), 16383d);
-		assertEquals(read.readDouble(1000, true), 16384d);
-		assertEquals(read.readDouble(1000, false), 16384d);
-		assertEquals(read.readDouble(1000, true), 32767d);
-		assertEquals(read.readDouble(1000, false), 32767d);
-		assertEquals(read.readDouble(1000, false), -64d);
-		assertEquals(read.readDouble(1000, true), -64d);
-		assertEquals(read.readDouble(1000, false), -65d);
-		assertEquals(read.readDouble(1000, true), -65d);
-		assertEquals(read.readDouble(1000, false), -8192d);
-		assertEquals(read.readDouble(1000, true), -8192d);
-		assertEquals(1.23456d, read.readDouble());
-	}
-
-	public void testBooleans () throws IOException {
-		runBooleanTest(new UnsafeOutput(4096));
-		runBooleanTest(new UnsafeOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runBooleanTest (UnsafeOutput write) throws IOException {
-		for (int i = 0; i < 100; i++) {
-			write.writeBoolean(true);
-			write.writeBoolean(false);
-		}
-
-		Input read = new UnsafeInput(write.toBytes());
-		for (int i = 0; i < 100; i++) {
-			assertEquals(true, read.readBoolean());
-			assertEquals(false, read.readBoolean());
-		}
-	}
-
-	public void testChars () throws IOException {
-		runCharTest(new UnsafeOutput(4096));
-		runCharTest(new UnsafeOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runCharTest (UnsafeOutput write) throws IOException {
-		write.writeChar((char)0);
-		write.writeChar((char)63);
-		write.writeChar((char)64);
-		write.writeChar((char)127);
-		write.writeChar((char)128);
-		write.writeChar((char)8192);
-		write.writeChar((char)16384);
-		write.writeChar((char)32767);
-		write.writeChar((char)65535);
-
-		Input read = new UnsafeInput(write.toBytes());
-		assertEquals(0, read.readChar());
-		assertEquals(63, read.readChar());
-		assertEquals(64, read.readChar());
-		assertEquals(127, read.readChar());
-		assertEquals(128, read.readChar());
-		assertEquals(8192, read.readChar());
-		assertEquals(16384, read.readChar());
-		assertEquals(32767, read.readChar());
-		assertEquals(65535, read.readChar());
-	}
-
-	// Check if writing varInts may produce more bytes than expected
-	public void testWriteTooManyBytes () throws IOException {
-		ByteArrayOutputStream os = new ByteArrayOutputStream(1);
-		runVarIntTest(new UnsafeOutput(os, 4), os);
-	}
-
-	private void runVarIntTest (UnsafeOutput write, ByteArrayOutputStream os) throws IOException {
-		write.writeVarInt(0, true);
-		write.writeVarInt(63, true);
-		write.writeVarInt(64, true);
-		write.writeVarInt(65535, true);
-		assertEquals(6, write.total());
-		write.flush();
-		assertEquals(6, os.size());
-
-		Input read = new UnsafeInput(os.toByteArray());
-		assertEquals(0, read.readVarInt(true));
-		assertEquals(63, read.readVarInt(true));
-		assertEquals(64, read.readVarInt(true));
-		assertEquals(65535, read.readVarInt(true));
-		assertEquals(true, read.eof());
-	}
-
-	public void testSimpleVarInt () {
-		final int value = 39117;
-		final Output out = new UnsafeOutput(1024);
-		out.writeVarInt(value, true);
-		out.flush();
-		final Input in = new UnsafeInput(out.toBytes());
-		final int actualValue = in.readVarInt(true);
-		assertEquals(value, actualValue);
-	}
-}
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/UnsafeMemoryInputOutputTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/UnsafeMemoryInputOutputTest.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,828 +0,0 @@
-/* Copyright (c) 2008, Nathan Sweet
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- * 
- * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the distribution.
- * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-package com.esotericsoftware.kryo;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Random;
-
-import com.esotericsoftware.kryo.io.ByteBufferInput;
-import com.esotericsoftware.kryo.io.ByteBufferOutput;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.UnsafeMemoryInput;
-import com.esotericsoftware.kryo.io.UnsafeMemoryOutput;
-import com.esotericsoftware.kryo.util.UnsafeUtil;
-
-/** @author Roman Levenstein <romixlev@gmail.com> */
-public class UnsafeMemoryInputOutputTest extends KryoTestCase {
-
-	public void testByteBufferOutputWithPreallocatedMemory () {
-		long bufAddress = UnsafeUtil.unsafe().allocateMemory(4096);
-		try {
-			ByteBufferOutput outputBuffer = new ByteBufferOutput(bufAddress, 4096);
-			outputBuffer.writeInt(10);
-
-			ByteBufferInput inputBuffer = new ByteBufferInput(outputBuffer.getByteBuffer());
-			inputBuffer.readInt();
-			inputBuffer.release();
-
-			outputBuffer.release();
-			outputBuffer = new UnsafeMemoryOutput(bufAddress, 4096);
-			outputBuffer.writeInt(10);
-
-			inputBuffer = new UnsafeMemoryInput(outputBuffer.getByteBuffer());
-			inputBuffer.readInt();
-			inputBuffer.release();
-			outputBuffer.release();
-		} catch (Throwable t) {
-			System.err.println("Streams with preallocated direct memory are not supported on this JVM");
-			t.printStackTrace();
-		} finally {
-			UnsafeUtil.unsafe().freeMemory(bufAddress);
-		}
-	}
-
-	public void testOutputStream () throws IOException {
-		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-		UnsafeMemoryOutput output = new UnsafeMemoryOutput(buffer, 2);
-		output.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26});
-		output.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46});
-		output.writeBytes(new byte[] {51, 52, 53, 54, 55, 56, 57, 58});
-		output.writeBytes(new byte[] {61, 62, 63, 64, 65});
-		output.flush();
-
-		assertEquals(new byte[] { //
-			11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, //
-			31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, //
-			51, 52, 53, 54, 55, 56, 57, 58, //
-			61, 62, 63, 64, 65}, buffer.toByteArray());
-	}
-
-	public void testInputStream () throws IOException {
-		byte[] bytes = new byte[] { //
-			11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, //
-			31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, //
-			51, 52, 53, 54, 55, 56, 57, 58, //
-			61, 62, 63, 64, 65};
-		ByteArrayInputStream buffer = new ByteArrayInputStream(bytes);
-		Input input = new UnsafeMemoryInput(buffer, 2);
-		byte[] temp = new byte[1024];
-		int count = input.read(temp, 512, bytes.length);
-		assertEquals(bytes.length, count);
-		byte[] temp2 = new byte[count];
-		System.arraycopy(temp, 512, temp2, 0, count);
-		assertEquals(bytes, temp2);
-
-		input = new UnsafeMemoryInput(bytes);
-		count = input.read(temp, 512, 512);
-		assertEquals(bytes.length, count);
-		temp2 = new byte[count];
-		System.arraycopy(temp, 512, temp2, 0, count);
-		assertEquals(bytes, temp2);
-	}
-
-	public void testWriteBytes () throws IOException {
-		UnsafeMemoryOutput buffer = new UnsafeMemoryOutput(512);
-		buffer.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26});
-		buffer.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46});
-		buffer.writeByte(51);
-		buffer.writeBytes(new byte[] {52, 53, 54, 55, 56, 57, 58});
-		buffer.writeByte(61);
-		buffer.writeByte(62);
-		buffer.writeByte(63);
-		buffer.writeByte(64);
-		buffer.writeByte(65);
-		buffer.flush();
-
-		assertEquals(new byte[] { //
-			11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, //
-			31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, //
-			51, 52, 53, 54, 55, 56, 57, 58, //
-			61, 62, 63, 64, 65}, buffer.toBytes());
-	}
-
-	public void testStrings () throws IOException {
-		runStringTest(new UnsafeMemoryOutput(4096));
-		runStringTest(new UnsafeMemoryOutput(897));
-		runStringTest(new UnsafeMemoryOutput(new ByteArrayOutputStream()));
-
-		UnsafeMemoryOutput write = new UnsafeMemoryOutput(21);
-		String value = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234";
-		write.writeString(value);
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(value, read.readString());
-
-		runStringTest(127);
-		runStringTest(256);
-		runStringTest(1024 * 1023);
-		runStringTest(1024 * 1024);
-		runStringTest(1024 * 1025);
-		runStringTest(1024 * 1026);
-		runStringTest(1024 * 1024 * 2);
-	}
-
-	public void runStringTest (int length) throws IOException {
-		UnsafeMemoryOutput write = new UnsafeMemoryOutput(1024, -1);
-		StringBuilder buffer = new StringBuilder();
-		for (int i = 0; i < length; i++)
-			buffer.append((char)i);
-
-		String value = buffer.toString();
-		write.writeString(value);
-		write.writeString(value);
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(value, read.readString());
-		assertEquals(value, read.readStringBuilder().toString());
-
-		write.clear();
-		write.writeString(buffer);
-		write.writeString(buffer);
-		read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(value, read.readStringBuilder().toString());
-		assertEquals(value, read.readString());
-
-		if (length <= 127) {
-			write.clear();
-			write.writeAscii(value);
-			write.writeAscii(value);
-			read = new UnsafeMemoryInput(write.toBytes());
-			assertEquals(value, read.readStringBuilder().toString());
-			assertEquals(value, read.readString());
-		}
-	}
-
-	public void runStringTest (UnsafeMemoryOutput write) throws IOException {
-		String value1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*";
-		String value2 = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234";
-
-		write.writeString("");
-		write.writeString("1");
-		write.writeString("22");
-		write.writeString("uno");
-		write.writeString("dos");
-		write.writeString("tres");
-		write.writeString(null);
-		write.writeString(value1);
-		write.writeString(value2);
-		for (int i = 0; i < 127; i++)
-			write.writeString(String.valueOf((char)i));
-		for (int i = 0; i < 127; i++)
-			write.writeString(String.valueOf((char)i) + "abc");
-
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals("", read.readString());
-		assertEquals("1", read.readString());
-		assertEquals("22", read.readString());
-		assertEquals("uno", read.readString());
-		assertEquals("dos", read.readString());
-		assertEquals("tres", read.readString());
-		assertEquals(null, read.readString());
-		assertEquals(value1, read.readString());
-		assertEquals(value2, read.readString());
-		for (int i = 0; i < 127; i++)
-			assertEquals(String.valueOf((char)i), read.readString());
-		for (int i = 0; i < 127; i++)
-			assertEquals(String.valueOf((char)i) + "abc", read.readString());
-
-		read.rewind();
-		assertEquals("", read.readStringBuilder().toString());
-		assertEquals("1", read.readStringBuilder().toString());
-		assertEquals("22", read.readStringBuilder().toString());
-		assertEquals("uno", read.readStringBuilder().toString());
-		assertEquals("dos", read.readStringBuilder().toString());
-		assertEquals("tres", read.readStringBuilder().toString());
-		assertEquals(null, read.readStringBuilder());
-		assertEquals(value1, read.readStringBuilder().toString());
-		assertEquals(value2, read.readStringBuilder().toString());
-		for (int i = 0; i < 127; i++)
-			assertEquals(String.valueOf((char)i), read.readStringBuilder().toString());
-		for (int i = 0; i < 127; i++)
-			assertEquals(String.valueOf((char)i) + "abc", read.readStringBuilder().toString());
-	}
-
-	public void testCanReadInt () throws IOException {
-		UnsafeMemoryOutput write = new UnsafeMemoryOutput(new ByteArrayOutputStream());
-
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(false, read.canReadInt());
-
-		write.writeVarInt(400, true);
-
-		read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(true, read.canReadInt());
-		read.setLimit(read.limit() - 1);
-		assertEquals(false, read.canReadInt());
-	}
-
-	public void testInts () throws IOException {
-		runIntTest(new UnsafeMemoryOutput(4096));
-		runIntTest(new UnsafeMemoryOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runIntTest (UnsafeMemoryOutput write) throws IOException {
-		write.setVarIntsEnabled(false);
-
-		write.writeInt(0);
-		write.writeInt(63);
-		write.writeInt(64);
-		write.writeInt(127);
-		write.writeInt(128);
-		write.writeInt(8192);
-		write.writeInt(16384);
-		write.writeInt(2097151);
-		write.writeInt(1048575);
-		write.writeInt(134217727);
-		write.writeInt(268435455);
-		write.writeInt(134217728);
-		write.writeInt(268435456);
-		write.writeInt(-2097151);
-		write.writeInt(-1048575);
-		write.writeInt(-134217727);
-		write.writeInt(-268435455);
-		write.writeInt(-134217728);
-		write.writeInt(-268435456);
-
-		write.setVarIntsEnabled(true);
-
-		assertEquals(1, write.writeInt(0, true));
-		assertEquals(1, write.writeInt(0, false));
-		assertEquals(1, write.writeInt(63, true));
-		assertEquals(1, write.writeInt(63, false));
-		assertEquals(1, write.writeInt(64, true));
-		assertEquals(2, write.writeInt(64, false));
-		assertEquals(1, write.writeInt(127, true));
-		assertEquals(2, write.writeInt(127, false));
-		assertEquals(2, write.writeInt(128, true));
-		assertEquals(2, write.writeInt(128, false));
-		assertEquals(2, write.writeInt(8191, true));
-		assertEquals(2, write.writeInt(8191, false));
-		assertEquals(2, write.writeInt(8192, true));
-		assertEquals(3, write.writeInt(8192, false));
-		assertEquals(2, write.writeInt(16383, true));
-		assertEquals(3, write.writeInt(16383, false));
-		assertEquals(3, write.writeInt(16384, true));
-		assertEquals(3, write.writeInt(16384, false));
-		assertEquals(3, write.writeInt(2097151, true));
-		assertEquals(4, write.writeInt(2097151, false));
-		assertEquals(3, write.writeInt(1048575, true));
-		assertEquals(3, write.writeInt(1048575, false));
-		assertEquals(4, write.writeInt(134217727, true));
-		assertEquals(4, write.writeInt(134217727, false));
-		assertEquals(4, write.writeInt(268435455, true));
-		assertEquals(5, write.writeInt(268435455, false));
-		assertEquals(4, write.writeInt(134217728, true));
-		assertEquals(5, write.writeInt(134217728, false));
-		assertEquals(5, write.writeInt(268435456, true));
-		assertEquals(5, write.writeInt(268435456, false));
-		assertEquals(1, write.writeInt(-64, false));
-		assertEquals(5, write.writeInt(-64, true));
-		assertEquals(2, write.writeInt(-65, false));
-		assertEquals(5, write.writeInt(-65, true));
-		assertEquals(2, write.writeInt(-8192, false));
-		assertEquals(5, write.writeInt(-8192, true));
-		assertEquals(3, write.writeInt(-1048576, false));
-		assertEquals(5, write.writeInt(-1048576, true));
-		assertEquals(4, write.writeInt(-134217728, false));
-		assertEquals(5, write.writeInt(-134217728, true));
-		assertEquals(5, write.writeInt(-134217729, false));
-		assertEquals(5, write.writeInt(-134217729, true));
-		assertEquals(5, write.writeInt(1000000000, false));
-		assertEquals(5, write.writeInt(1000000000, true));
-		assertEquals(5, write.writeInt(Integer.MAX_VALUE - 1, false));
-		assertEquals(5, write.writeInt(Integer.MAX_VALUE - 1, true));
-		assertEquals(5, write.writeInt(Integer.MAX_VALUE, false));
-		assertEquals(5, write.writeInt(Integer.MAX_VALUE, true));
-
-		UnsafeMemoryInput read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(0, read.readInt());
-		assertEquals(63, read.readInt());
-		assertEquals(64, read.readInt());
-		assertEquals(127, read.readInt());
-		assertEquals(128, read.readInt());
-		assertEquals(8192, read.readInt());
-		assertEquals(16384, read.readInt());
-		assertEquals(2097151, read.readInt());
-		assertEquals(1048575, read.readInt());
-		assertEquals(134217727, read.readInt());
-		assertEquals(268435455, read.readInt());
-		assertEquals(134217728, read.readInt());
-		assertEquals(268435456, read.readInt());
-		assertEquals(-2097151, read.readInt());
-		assertEquals(-1048575, read.readInt());
-		assertEquals(-134217727, read.readInt());
-		assertEquals(-268435455, read.readInt());
-		assertEquals(-134217728, read.readInt());
-		assertEquals(-268435456, read.readInt());
-		assertEquals(true, read.canReadInt());
-		assertEquals(true, read.canReadInt());
-		assertEquals(true, read.canReadInt());
-
-		read.setVarIntsEnabled(true);
-
-		assertEquals(0, read.readInt(true));
-		assertEquals(0, read.readInt(false));
-		assertEquals(63, read.readInt(true));
-		assertEquals(63, read.readInt(false));
-		assertEquals(64, read.readInt(true));
-		assertEquals(64, read.readInt(false));
-		assertEquals(127, read.readInt(true));
-		assertEquals(127, read.readInt(false));
-		assertEquals(128, read.readInt(true));
-		assertEquals(128, read.readInt(false));
-		assertEquals(8191, read.readInt(true));
-		assertEquals(8191, read.readInt(false));
-		assertEquals(8192, read.readInt(true));
-		assertEquals(8192, read.readInt(false));
-		assertEquals(16383, read.readInt(true));
-		assertEquals(16383, read.readInt(false));
-		assertEquals(16384, read.readInt(true));
-		assertEquals(16384, read.readInt(false));
-		assertEquals(2097151, read.readInt(true));
-		assertEquals(2097151, read.readInt(false));
-		assertEquals(1048575, read.readInt(true));
-		assertEquals(1048575, read.readInt(false));
-		assertEquals(134217727, read.readInt(true));
-		assertEquals(134217727, read.readInt(false));
-		assertEquals(268435455, read.readInt(true));
-		assertEquals(268435455, read.readInt(false));
-		assertEquals(134217728, read.readInt(true));
-		assertEquals(134217728, read.readInt(false));
-		assertEquals(268435456, read.readInt(true));
-		assertEquals(268435456, read.readInt(false));
-		assertEquals(-64, read.readInt(false));
-		assertEquals(-64, read.readInt(true));
-		assertEquals(-65, read.readInt(false));
-		assertEquals(-65, read.readInt(true));
-		assertEquals(-8192, read.readInt(false));
-		assertEquals(-8192, read.readInt(true));
-		assertEquals(-1048576, read.readInt(false));
-		assertEquals(-1048576, read.readInt(true));
-		assertEquals(-134217728, read.readInt(false));
-		assertEquals(-134217728, read.readInt(true));
-		assertEquals(-134217729, read.readInt(false));
-		assertEquals(-134217729, read.readInt(true));
-		assertEquals(1000000000, read.readInt(false));
-		assertEquals(1000000000, read.readInt(true));
-		assertEquals(Integer.MAX_VALUE - 1, read.readInt(false));
-		assertEquals(Integer.MAX_VALUE - 1, read.readInt(true));
-		assertEquals(Integer.MAX_VALUE, read.readInt(false));
-		assertEquals(Integer.MAX_VALUE, read.readInt(true));
-		assertEquals(false, read.canReadInt());
-
-		Random random = new Random();
-		for (int i = 0; i < 10000; i++) {
-			int value = random.nextInt();
-			write.clear();
-			write.writeInt(value);
-			write.writeInt(value, true);
-			write.writeInt(value, false);
-			read.setBuffer(write.toBytes());
-			assertEquals(value, read.readInt());
-			assertEquals(value, read.readInt(true));
-			assertEquals(value, read.readInt(false));
-		}
-	}
-
-	public void testLongs () throws IOException {
-		runLongTest(new UnsafeMemoryOutput(4096));
-		runLongTest(new UnsafeMemoryOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runLongTest (UnsafeMemoryOutput write) throws IOException {
-		write.setVarIntsEnabled(false);
-
-		write.writeLong(0);
-		write.writeLong(63);
-		write.writeLong(64);
-		write.writeLong(127);
-		write.writeLong(128);
-		write.writeLong(8192);
-		write.writeLong(16384);
-		write.writeLong(2097151);
-		write.writeLong(1048575);
-		write.writeLong(134217727);
-		write.writeLong(268435455);
-		write.writeLong(134217728);
-		write.writeLong(268435456);
-		write.writeLong(-2097151);
-		write.writeLong(-1048575);
-		write.writeLong(-134217727);
-		write.writeLong(-268435455);
-		write.writeLong(-134217728);
-		write.writeLong(-268435456);
-
-		write.setVarIntsEnabled(true);
-
-		assertEquals(1, write.writeLong(0, true));
-		assertEquals(1, write.writeLong(0, false));
-		assertEquals(1, write.writeLong(63, true));
-		assertEquals(1, write.writeLong(63, false));
-		assertEquals(1, write.writeLong(64, true));
-		assertEquals(2, write.writeLong(64, false));
-		assertEquals(1, write.writeLong(127, true));
-		assertEquals(2, write.writeLong(127, false));
-		assertEquals(2, write.writeLong(128, true));
-		assertEquals(2, write.writeLong(128, false));
-		assertEquals(2, write.writeLong(8191, true));
-		assertEquals(2, write.writeLong(8191, false));
-		assertEquals(2, write.writeLong(8192, true));
-		assertEquals(3, write.writeLong(8192, false));
-		assertEquals(2, write.writeLong(16383, true));
-		assertEquals(3, write.writeLong(16383, false));
-		assertEquals(3, write.writeLong(16384, true));
-		assertEquals(3, write.writeLong(16384, false));
-		assertEquals(3, write.writeLong(2097151, true));
-		assertEquals(4, write.writeLong(2097151, false));
-		assertEquals(3, write.writeLong(1048575, true));
-		assertEquals(3, write.writeLong(1048575, false));
-		assertEquals(4, write.writeLong(134217727, true));
-		assertEquals(4, write.writeLong(134217727, false));
-		assertEquals(4, write.writeLong(268435455l, true));
-		assertEquals(5, write.writeLong(268435455l, false));
-		assertEquals(4, write.writeLong(134217728l, true));
-		assertEquals(5, write.writeLong(134217728l, false));
-		assertEquals(5, write.writeLong(268435456l, true));
-		assertEquals(5, write.writeLong(268435456l, false));
-		assertEquals(1, write.writeLong(-64, false));
-		assertEquals(9, write.writeLong(-64, true));
-		assertEquals(2, write.writeLong(-65, false));
-		assertEquals(9, write.writeLong(-65, true));
-		assertEquals(2, write.writeLong(-8192, false));
-		assertEquals(9, write.writeLong(-8192, true));
-		assertEquals(3, write.writeLong(-1048576, false));
-		assertEquals(9, write.writeLong(-1048576, true));
-		assertEquals(4, write.writeLong(-134217728, false));
-		assertEquals(9, write.writeLong(-134217728, true));
-		assertEquals(5, write.writeLong(-134217729, false));
-		assertEquals(9, write.writeLong(-134217729, true));
-
-		UnsafeMemoryInput read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(0, read.readLong());
-		assertEquals(63, read.readLong());
-		assertEquals(64, read.readLong());
-		assertEquals(127, read.readLong());
-		assertEquals(128, read.readLong());
-		assertEquals(8192, read.readLong());
-		assertEquals(16384, read.readLong());
-		assertEquals(2097151, read.readLong());
-		assertEquals(1048575, read.readLong());
-		assertEquals(134217727, read.readLong());
-		assertEquals(268435455, read.readLong());
-		assertEquals(134217728, read.readLong());
-		assertEquals(268435456, read.readLong());
-		assertEquals(-2097151, read.readLong());
-		assertEquals(-1048575, read.readLong());
-		assertEquals(-134217727, read.readLong());
-		assertEquals(-268435455, read.readLong());
-		assertEquals(-134217728, read.readLong());
-		assertEquals(-268435456, read.readLong());
-
-		read.setVarIntsEnabled(true);
-
-		assertEquals(0, read.readLong(true));
-		assertEquals(0, read.readLong(false));
-		assertEquals(63, read.readLong(true));
-		assertEquals(63, read.readLong(false));
-		assertEquals(64, read.readLong(true));
-		assertEquals(64, read.readLong(false));
-		assertEquals(127, read.readLong(true));
-		assertEquals(127, read.readLong(false));
-		assertEquals(128, read.readLong(true));
-		assertEquals(128, read.readLong(false));
-		assertEquals(8191, read.readLong(true));
-		assertEquals(8191, read.readLong(false));
-		assertEquals(8192, read.readLong(true));
-		assertEquals(8192, read.readLong(false));
-		assertEquals(16383, read.readLong(true));
-		assertEquals(16383, read.readLong(false));
-		assertEquals(16384, read.readLong(true));
-		assertEquals(16384, read.readLong(false));
-		assertEquals(2097151, read.readLong(true));
-		assertEquals(2097151, read.readLong(false));
-		assertEquals(1048575, read.readLong(true));
-		assertEquals(1048575, read.readLong(false));
-		assertEquals(134217727, read.readLong(true));
-		assertEquals(134217727, read.readLong(false));
-		assertEquals(268435455, read.readLong(true));
-		assertEquals(268435455, read.readLong(false));
-		assertEquals(134217728, read.readLong(true));
-		assertEquals(134217728, read.readLong(false));
-		assertEquals(268435456, read.readLong(true));
-		assertEquals(268435456, read.readLong(false));
-		assertEquals(-64, read.readLong(false));
-		assertEquals(-64, read.readLong(true));
-		assertEquals(-65, read.readLong(false));
-		assertEquals(-65, read.readLong(true));
-		assertEquals(-8192, read.readLong(false));
-		assertEquals(-8192, read.readLong(true));
-		assertEquals(-1048576, read.readLong(false));
-		assertEquals(-1048576, read.readLong(true));
-		assertEquals(-134217728, read.readLong(false));
-		assertEquals(-134217728, read.readLong(true));
-		assertEquals(-134217729, read.readLong(false));
-		assertEquals(-134217729, read.readLong(true));
-
-		Random random = new Random();
-		for (int i = 0; i < 10000; i++) {
-			long value = random.nextLong();
-			write.clear();
-			write.writeLong(value);
-			write.writeLong(value, true);
-			write.writeLong(value, false);
-			read.setBuffer(write.toBytes());
-			assertEquals("Element " + i, value, read.readLong());
-			assertEquals("Element " + i, value, read.readLong(true));
-			assertEquals("Element " + i, value, read.readLong(false));
-		}
-	}
-
-	public void testShorts () throws IOException {
-		runShortTest(new UnsafeMemoryOutput(4096));
-		runShortTest(new UnsafeMemoryOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runShortTest (UnsafeMemoryOutput write) throws IOException {
-		write.writeShort(0);
-		write.writeShort(63);
-		write.writeShort(64);
-		write.writeShort(127);
-		write.writeShort(128);
-		write.writeShort(8192);
-		write.writeShort(16384);
-		write.writeShort(32767);
-		write.writeShort(-63);
-		write.writeShort(-64);
-		write.writeShort(-127);
-		write.writeShort(-128);
-		write.writeShort(-8192);
-		write.writeShort(-16384);
-		write.writeShort(-32768);
-
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(0, read.readShort());
-		assertEquals(63, read.readShort());
-		assertEquals(64, read.readShort());
-		assertEquals(127, read.readShort());
-		assertEquals(128, read.readShort());
-		assertEquals(8192, read.readShort());
-		assertEquals(16384, read.readShort());
-		assertEquals(32767, read.readShort());
-		assertEquals(-63, read.readShort());
-		assertEquals(-64, read.readShort());
-		assertEquals(-127, read.readShort());
-		assertEquals(-128, read.readShort());
-		assertEquals(-8192, read.readShort());
-		assertEquals(-16384, read.readShort());
-		assertEquals(-32768, read.readShort());
-	}
-
-	public void testFloats () throws IOException {
-		runFloatTest(new UnsafeMemoryOutput(4096));
-		runFloatTest(new UnsafeMemoryOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runFloatTest (UnsafeMemoryOutput write) throws IOException {
-		write.writeFloat(0);
-		write.writeFloat(63);
-		write.writeFloat(64);
-		write.writeFloat(127);
-		write.writeFloat(128);
-		write.writeFloat(8192);
-		write.writeFloat(16384);
-		write.writeFloat(32767);
-		write.writeFloat(-63);
-		write.writeFloat(-64);
-		write.writeFloat(-127);
-		write.writeFloat(-128);
-		write.writeFloat(-8192);
-		write.writeFloat(-16384);
-		write.writeFloat(-32768);
-		assertEquals(4, write.writeFloat(0, 1000, true));
-		assertEquals(4, write.writeFloat(0, 1000, false));
-		assertEquals(4, write.writeFloat(63, 1000, true));
-		assertEquals(4, write.writeFloat(63, 1000, false));
-		assertEquals(4, write.writeFloat(64, 1000, true));
-		assertEquals(4, write.writeFloat(64, 1000, false));
-		assertEquals(4, write.writeFloat(127, 1000, true));
-		assertEquals(4, write.writeFloat(127, 1000, false));
-		assertEquals(4, write.writeFloat(128, 1000, true));
-		assertEquals(4, write.writeFloat(128, 1000, false));
-		assertEquals(4, write.writeFloat(8191, 1000, true));
-		assertEquals(4, write.writeFloat(8191, 1000, false));
-		assertEquals(4, write.writeFloat(8192, 1000, true));
-		assertEquals(4, write.writeFloat(8192, 1000, false));
-		assertEquals(4, write.writeFloat(16383, 1000, true));
-		assertEquals(4, write.writeFloat(16383, 1000, false));
-		assertEquals(4, write.writeFloat(16384, 1000, true));
-		assertEquals(4, write.writeFloat(16384, 1000, false));
-		assertEquals(4, write.writeFloat(32767, 1000, true));
-		assertEquals(4, write.writeFloat(32767, 1000, false));
-		assertEquals(4, write.writeFloat(-64, 1000, false));
-		assertEquals(4, write.writeFloat(-64, 1000, true));
-		assertEquals(4, write.writeFloat(-65, 1000, false));
-		assertEquals(4, write.writeFloat(-65, 1000, true));
-		assertEquals(4, write.writeFloat(-8192, 1000, false));
-		assertEquals(4, write.writeFloat(-8192, 1000, true));
-
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(read.readFloat(), 0f);
-		assertEquals(read.readFloat(), 63f);
-		assertEquals(read.readFloat(), 64f);
-		assertEquals(read.readFloat(), 127f);
-		assertEquals(read.readFloat(), 128f);
-		assertEquals(read.readFloat(), 8192f);
-		assertEquals(read.readFloat(), 16384f);
-		assertEquals(read.readFloat(), 32767f);
-		assertEquals(read.readFloat(), -63f);
-		assertEquals(read.readFloat(), -64f);
-		assertEquals(read.readFloat(), -127f);
-		assertEquals(read.readFloat(), -128f);
-		assertEquals(read.readFloat(), -8192f);
-		assertEquals(read.readFloat(), -16384f);
-		assertEquals(read.readFloat(), -32768f);
-		assertEquals(read.readFloat(1000, true), 0f);
-		assertEquals(read.readFloat(1000, false), 0f);
-		assertEquals(read.readFloat(1000, true), 63f);
-		assertEquals(read.readFloat(1000, false), 63f);
-		assertEquals(read.readFloat(1000, true), 64f);
-		assertEquals(read.readFloat(1000, false), 64f);
-		assertEquals(read.readFloat(1000, true), 127f);
-		assertEquals(read.readFloat(1000, false), 127f);
-		assertEquals(read.readFloat(1000, true), 128f);
-		assertEquals(read.readFloat(1000, false), 128f);
-		assertEquals(read.readFloat(1000, true), 8191f);
-		assertEquals(read.readFloat(1000, false), 8191f);
-		assertEquals(read.readFloat(1000, true), 8192f);
-		assertEquals(read.readFloat(1000, false), 8192f);
-		assertEquals(read.readFloat(1000, true), 16383f);
-		assertEquals(read.readFloat(1000, false), 16383f);
-		assertEquals(read.readFloat(1000, true), 16384f);
-		assertEquals(read.readFloat(1000, false), 16384f);
-		assertEquals(read.readFloat(1000, true), 32767f);
-		assertEquals(read.readFloat(1000, false), 32767f);
-		assertEquals(read.readFloat(1000, false), -64f);
-		assertEquals(read.readFloat(1000, true), -64f);
-		assertEquals(read.readFloat(1000, false), -65f);
-		assertEquals(read.readFloat(1000, true), -65f);
-		assertEquals(read.readFloat(1000, false), -8192f);
-		assertEquals(read.readFloat(1000, true), -8192f);
-	}
-
-	public void testDoubles () throws IOException {
-		runDoubleTest(new UnsafeMemoryOutput(4096));
-		runDoubleTest(new UnsafeMemoryOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runDoubleTest (UnsafeMemoryOutput write) throws IOException {
-		write.writeDouble(0);
-		write.writeDouble(63);
-		write.writeDouble(64);
-		write.writeDouble(127);
-		write.writeDouble(128);
-		write.writeDouble(8192);
-		write.writeDouble(16384);
-		write.writeDouble(32767);
-		write.writeDouble(-63);
-		write.writeDouble(-64);
-		write.writeDouble(-127);
-		write.writeDouble(-128);
-		write.writeDouble(-8192);
-		write.writeDouble(-16384);
-		write.writeDouble(-32768);
-		assertEquals(8, write.writeDouble(0, 1000, true));
-		assertEquals(8, write.writeDouble(0, 1000, false));
-		assertEquals(8, write.writeDouble(63, 1000, true));
-		assertEquals(8, write.writeDouble(63, 1000, false));
-		assertEquals(8, write.writeDouble(64, 1000, true));
-		assertEquals(8, write.writeDouble(64, 1000, false));
-		assertEquals(8, write.writeDouble(127, 1000, true));
-		assertEquals(8, write.writeDouble(127, 1000, false));
-		assertEquals(8, write.writeDouble(128, 1000, true));
-		assertEquals(8, write.writeDouble(128, 1000, false));
-		assertEquals(8, write.writeDouble(8191, 1000, true));
-		assertEquals(8, write.writeDouble(8191, 1000, false));
-		assertEquals(8, write.writeDouble(8192, 1000, true));
-		assertEquals(8, write.writeDouble(8192, 1000, false));
-		assertEquals(8, write.writeDouble(16383, 1000, true));
-		assertEquals(8, write.writeDouble(16383, 1000, false));
-		assertEquals(8, write.writeDouble(16384, 1000, true));
-		assertEquals(8, write.writeDouble(16384, 1000, false));
-		assertEquals(8, write.writeDouble(32767, 1000, true));
-		assertEquals(8, write.writeDouble(32767, 1000, false));
-		assertEquals(8, write.writeDouble(-64, 1000, false));
-		assertEquals(8, write.writeDouble(-64, 1000, true));
-		assertEquals(8, write.writeDouble(-65, 1000, false));
-		assertEquals(8, write.writeDouble(-65, 1000, true));
-		assertEquals(8, write.writeDouble(-8192, 1000, false));
-		assertEquals(8, write.writeDouble(-8192, 1000, true));
-		write.writeDouble(1.23456d);
-
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(read.readDouble(), 0d);
-		assertEquals(read.readDouble(), 63d);
-		assertEquals(read.readDouble(), 64d);
-		assertEquals(read.readDouble(), 127d);
-		assertEquals(read.readDouble(), 128d);
-		assertEquals(read.readDouble(), 8192d);
-		assertEquals(read.readDouble(), 16384d);
-		assertEquals(read.readDouble(), 32767d);
-		assertEquals(read.readDouble(), -63d);
-		assertEquals(read.readDouble(), -64d);
-		assertEquals(read.readDouble(), -127d);
-		assertEquals(read.readDouble(), -128d);
-		assertEquals(read.readDouble(), -8192d);
-		assertEquals(read.readDouble(), -16384d);
-		assertEquals(read.readDouble(), -32768d);
-		assertEquals(read.readDouble(1000, true), 0d);
-		assertEquals(read.readDouble(1000, false), 0d);
-		assertEquals(read.readDouble(1000, true), 63d);
-		assertEquals(read.readDouble(1000, false), 63d);
-		assertEquals(read.readDouble(1000, true), 64d);
-		assertEquals(read.readDouble(1000, false), 64d);
-		assertEquals(read.readDouble(1000, true), 127d);
-		assertEquals(read.readDouble(1000, false), 127d);
-		assertEquals(read.readDouble(1000, true), 128d);
-		assertEquals(read.readDouble(1000, false), 128d);
-		assertEquals(read.readDouble(1000, true), 8191d);
-		assertEquals(read.readDouble(1000, false), 8191d);
-		assertEquals(read.readDouble(1000, true), 8192d);
-		assertEquals(read.readDouble(1000, false), 8192d);
-		assertEquals(read.readDouble(1000, true), 16383d);
-		assertEquals(read.readDouble(1000, false), 16383d);
-		assertEquals(read.readDouble(1000, true), 16384d);
-		assertEquals(read.readDouble(1000, false), 16384d);
-		assertEquals(read.readDouble(1000, true), 32767d);
-		assertEquals(read.readDouble(1000, false), 32767d);
-		assertEquals(read.readDouble(1000, false), -64d);
-		assertEquals(read.readDouble(1000, true), -64d);
-		assertEquals(read.readDouble(1000, false), -65d);
-		assertEquals(read.readDouble(1000, true), -65d);
-		assertEquals(read.readDouble(1000, false), -8192d);
-		assertEquals(read.readDouble(1000, true), -8192d);
-		assertEquals(1.23456d, read.readDouble());
-	}
-
-	public void testBooleans () throws IOException {
-		runBooleanTest(new UnsafeMemoryOutput(4096));
-		runBooleanTest(new UnsafeMemoryOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runBooleanTest (UnsafeMemoryOutput write) throws IOException {
-		for (int i = 0; i < 100; i++) {
-			write.writeBoolean(true);
-			write.writeBoolean(false);
-		}
-
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		for (int i = 0; i < 100; i++) {
-			assertEquals(true, read.readBoolean());
-			assertEquals(false, read.readBoolean());
-		}
-	}
-
-	public void testChars () throws IOException {
-		runCharTest(new UnsafeMemoryOutput(4096));
-		runCharTest(new UnsafeMemoryOutput(new ByteArrayOutputStream()));
-	}
-
-	private void runCharTest (UnsafeMemoryOutput write) throws IOException {
-		write.writeChar((char)0);
-		write.writeChar((char)63);
-		write.writeChar((char)64);
-		write.writeChar((char)127);
-		write.writeChar((char)128);
-		write.writeChar((char)8192);
-		write.writeChar((char)16384);
-		write.writeChar((char)32767);
-		write.writeChar((char)65535);
-
-		Input read = new UnsafeMemoryInput(write.toBytes());
-		assertEquals(0, read.readChar());
-		assertEquals(63, read.readChar());
-		assertEquals(64, read.readChar());
-		assertEquals(127, read.readChar());
-		assertEquals(128, read.readChar());
-		assertEquals(8192, read.readChar());
-		assertEquals(16384, read.readChar());
-		assertEquals(32767, read.readChar());
-		assertEquals(65535, read.readChar());
-	}
-}
--- kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/WarnUnregisteredClassesTest.java	2018-03-20 22:00:20.000000000 +0100
+++ kryo-kryo-parent-4.0.2/test/com/esotericsoftware/kryo/WarnUnregisteredClassesTest.java	2018-12-20 09:20:46.854804308 +0100
@@ -20,16 +20,10 @@
 package com.esotericsoftware.kryo;
 
 import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.esotericsoftware.kryo.KryoTestCase.StreamFactory;
-import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.io.UnsafeMemoryInput;
-import com.esotericsoftware.kryo.io.UnsafeMemoryOutput;
 import com.esotericsoftware.minlog.Log;
 import com.esotericsoftware.minlog.Log.Logger;
 
@@ -106,29 +100,8 @@
 	}
 
 	public void write (Kryo kryo, Object object) {
-		StreamFactory sf = new StreamFactory() {
-			public Output createOutput (OutputStream os) {
-				return new UnsafeMemoryOutput(os);
-			}
-
-			public Output createOutput (OutputStream os, int size) {
-				return new UnsafeMemoryOutput(os, size);
-			}
-
-			public Output createOutput (int size, int limit) {
-				return new UnsafeMemoryOutput(size, limit);
-			}
-
-			public Input createInput (InputStream os, int size) {
-				return new UnsafeMemoryInput(os, size);
-			}
-
-			public Input createInput (byte[] buffer) {
-				return new UnsafeMemoryInput(buffer);
-			}
-		};
 		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
-		Output output = sf.createOutput(outStream, 4096);
+		Output output = new Output(outStream, 4096);
 		kryo.writeClassAndObject(output, object);
 		output.flush();
 	}
openSUSE Build Service is sponsored by