Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
client/src/com/aerospike/client/Value.java
### 代码内容：
package com.aerospike.client;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.luaj.vm2.LuaBoolean;
import org.luaj.vm2.LuaDouble;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaNil;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaValue;

import com.aerospike.client.cdt.MapOrder;
import com.aerospike.client.command.Buffer;
import com.aerospike.client.command.ParticleType;
import com.aerospike.client.lua.LuaBytes;
import com.aerospike.client.lua.LuaInstance;
import com.aerospike.client.util.Packer;

/**
 * Polymorphic value classes used to efficiently serialize objects into the wire protocol.
 */
public abstract class Value {
	/**
	 * Null value.
	 */
	public static final Value NULL = NullValue.INSTANCE;

	/**
	 * Infinity value to be used in CDT range comparisons only.
	 */
	public static final Value INFINITY = new InfinityValue();

	/**
	 * Wildcard value to be used in CDT range comparisons only.
	 */
	public static final Value WILDCARD = new WildcardValue();

	/**
	 * Get string or null value instance.
	 */
	public static Value get(String value) {
		return (value == null)? NullValue.INSTANCE : new StringValue(value);
	}

	/**
	 * Get byte array or null value instance.
	 */
	public static Value get(byte[] value) {
		return (value == null)? NullValue.INSTANCE : new BytesValue(value);
	}

	/**
	 * Get byte array with type or null value instance.
	 */
	public static Value get(byte[] value, int type) {
		return (value == null)? NullValue.INSTANCE : new BytesValue(value, type);
	}

	/**
	 * Get byte segment or null value instance.
	 */
	public static Value get(byte[] value, int offset, int length) {
		return (value == null)? NullValue.INSTANCE : new ByteSegmentValue(value, offset, length);
	}

	/**
	 * Get byte segment or null value instance.
	 */
	public static Value get(ByteBuffer bb) {
		return (bb == null)? NullValue.INSTANCE : new BytesValue(bb.array());
	}

	/**
	 * Get byte value instance.
	 */
	public static Value get(byte value) {
		return new ByteValue(value);
	}

	/**
	 * Get integer value instance.
	 */
	public static Value get(int value) {
		return new IntegerValue(value);
	}

	/**
	 * Get long value instance.
	 */
	public static Value get(long value) {
		return new LongValue(value);
	}

	/**
	 * Get double value instance.
	 */
	public static Value get(double value) {
		return new DoubleValue(value);
	}

	/**
	 * Get float value instance.
	 */
	public static Value get(float value) {
		return new FloatValue(value);
	}

	/**
	 * Get boolean value instance.
	 */
	public static Value get(boolean value) {
		return new BooleanValue(value);
	}

	/**
	 * Get list or null value instance.
	 */
	public static Value get(List<?> value) {
		return (value == null)? NullValue.INSTANCE : new ListValue(value);
	}

	/**
	 * Get map or null value instance.
	 */
	public static Value get(Map<?,?> value) {
		return (value == null)? NullValue.INSTANCE : new MapValue(value);
	}

	/**
	 * Get sorted map or null value instance.
	 */
	public static Value get(List<? extends Entry<?,?>> value, MapOrder mapOrder) {
		return (value == null)? NullValue.INSTANCE : new SortedMapValue(value, mapOrder);
	}

	/**
	 * Get value array instance.
	 */
	public static Value get(Value[] value) {
		return (value == null)? NullValue.INSTANCE : new ValueArray(value);
	}

	/**
	 * Get blob or null value instance.
	 */
	public static Value getAsBlob(Object value) {
		return (value == null)? NullValue.INSTANCE : new BlobValue(value);
	}

	/**
	 * Get GeoJSON or null value instance.
	 */
	public static Value getAsGeoJSON(String value) {
		return (value == null)? NullValue.INSTANCE : new GeoJSONValue(value);
	}

	/**
	 * Get HyperLogLog or null value instance.
	 */
	public static Value getAsHLL(byte[] value) {
		return (value == null)? NullValue.INSTANCE : new HLLValue(value);
	}

	/**
	 * Get null value instance.
	 */
	public static Value getAsNull() {
		return NullValue.INSTANCE;
	}

	/**
	 * Determine value given generic object.
	 * This is the slowest of the Value get() methods.
	 * Useful when copying records from one cluster to another.
	 */
	public static Value get(Object value) {
		if (value == null) {
			return NullValue.INSTANCE;
		}

		if (value instanceof Value) {
			return (Value)value;
		}

		if (value instanceof byte[]) {
        	return new BytesValue((byte[])value);
		}

		if (value instanceof String) {
        	return new StringValue((String)value);
		}

		if (value instanceof Integer) {
        	return new IntegerValue((Integer)value);
		}

		if (value instanceof Long) {
        	return new LongValue((Long)value);
		}

		if (value instanceof Double) {
        	return new DoubleValue((Double)value);
		}

		if (value instanceof Float) {
        	return new FloatValue((Float)value);
		}

		if (value instanceof Boolean) {
        	return new BooleanValue((Boolean)value);
		}

		if (value instanceof Byte) {
        	return new ByteValue((byte)value);
		}

		if (value instanceof List<?>) {
        	return new ListValue((List<?>)value);
		}

		if (value instanceof Map<?,?>) {
        	return new MapValue((Map<?,?>)value);
		}

		if (value instanceof ByteBuffer) {
			ByteBuffer bb = (ByteBuffer)value;
        	return new BytesValue(bb.array());
		}

		return new BlobValue(value);
	}

	/**
	 * Get value from Record object. Useful when copying records from one cluster to another.
	 */
	public static Value getFromRecordObject(Object value) {
		return Value.get(value);
	}

	/**
	 * Calculate number of bytes necessary to serialize the value in the wire protocol.
	 */
	public abstract int estimateSize() throws AerospikeException;

	/**
	 * Serialize the value in the wire protocol.
	 */
	public abstract int write(byte[] buffer, int offset) throws AerospikeException;

	/**
	 * Serialize the value using MessagePack.
	 */
	public abstract void pack(Packer packer);

	/**
	 * Validate if value type can be used as a key.
	 * @throws AerospikeException	if type can't be used as a key.
	 */
	public void validateKeyType() throws AerospikeException {
	}

	/**
	 * Get wire protocol value type.
	 */
	public abstract int getType();

	/**
	 * Return original value as an Object.
	 */
	public abstract Object getObject();

	/**
	 * Return value as an Object.
	 */
	public abstract LuaValue getLuaValue(LuaInstance instance);

	/**
	 * Return value as an integer.
	 */
	public int toInteger() {
		return 0;
	}

	/**
	 * Return value as a long.
	 */
	public long toLong() {
		return 0;
	}

	/**
	 * Empty value.
	 */
	public static final class NullValue extends Value {
		public static final NullValue INSTANCE = new NullValue();

		@Override
		public int estimateSize() {
			return 0;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			return 0;
		}

		@Override
		public void pack(Packer packer) {
			packer.packNil();
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: null");
		}

		@Override
		public int getType() {
			return ParticleType.NULL;
		}

		@Override
		public Object getObject() {
			return null;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaNil.NIL;
		}

		@Override
		public String toString() {
			return null;
		}

		@Override
		public boolean equals(Object other) {
			if (other == null) {
				return true;
			}
			return this.getClass().equals(other.getClass());
		}

		@Override
		public final int hashCode() {
			return 0;
		}
	}

	/**
	 * Byte array value.
	 */
	public static final class BytesValue extends Value {
		private final byte[] bytes;
		private final int type;

		public BytesValue(byte[] bytes) {
			this.bytes = bytes;
			this.type = ParticleType.BLOB;
		}

		public BytesValue(byte[] bytes, int type) {
			this.bytes = bytes;
			this.type = type;
		}

		@Override
		public int estimateSize() {
			return bytes.length;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			System.arraycopy(bytes, 0, buffer, offset, bytes.length);
			return bytes.length;
		}

		@Override
		public void pack(Packer packer) {
			packer.packBytes(bytes, type);
		}

		@Override
		public int getType() {
			return type;
		}

		@Override
		public Object getObject() {
			return bytes;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return new LuaBytes(instance, bytes, type);
		}

		@Override
		public String toString() {
			return Buffer.bytesToHexString(bytes);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				Arrays.equals(this.bytes, ((BytesValue)other).bytes));
		}

		@Override
		public int hashCode() {
			return Arrays.hashCode(bytes);
		}
	}

	/**
	 * Byte segment value.
	 */
	public static final class ByteSegmentValue extends Value {
		private final byte[] bytes;
		private final int offset;
		private final int length;

		public ByteSegmentValue(byte[] bytes, int offset, int length) {
			this.bytes = bytes;
			this.offset = offset;
			this.length = length;
		}

		@Override
		public int estimateSize() {
			return length;

		}

		@Override
		public int write(byte[] buffer, int targetOffset) {
			System.arraycopy(bytes, offset, buffer, targetOffset, length);
			return length;
		}

		@Override
		public void pack(Packer packer) {
			packer.packBytes(bytes, offset, length);
		}

		@Override
		public int getType() {
			return ParticleType.BLOB;
		}

		@Override
		public Object getObject() {
			return this;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaString.valueOf(bytes, offset, length);
		}

		@Override
		public String toString() {
			return Buffer.bytesToHexString(bytes, offset, length);
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == null) {
				return false;
			}

			if (! this.getClass().equals(obj.getClass())) {
				return false;
			}
			ByteSegmentValue other = (ByteSegmentValue)obj;

			if (this.length != other.length) {
				return false;
			}

			for (int i = 0; i < length; i++) {
				if (this.bytes[this.offset + i] != other.bytes[other.offset + i]) {
					return false;
				}
			}
			return true;
		}

		@Override
		public int hashCode() {
	        int result = 1;
	        for (int i = 0; i < length; i++) {
	            result = 31 * result + bytes[offset+i];
	        }
	        return result;
		}

		public byte[] getBytes() {
			return bytes;
		}

		public int getOffset() {
			return offset;
		}

		public int getLength() {
			return length;
		}
	}

	/**
	 * Byte value.
	 */
	public static final class ByteValue extends Value {
		private final byte value;

		public ByteValue(byte value) {
			this.value = value;
		}

		@Override
		public int estimateSize() {
			return 8;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			Buffer.longToBytes(value, buffer, offset);
			return 8;
		}

		@Override
		public void pack(Packer packer) {
			packer.packByte(value);
		}

		@Override
		public int getType() {
			// The server does not natively handle one byte, so store as long (8 byte integer).
			return ParticleType.INTEGER;
		}

		@Override
		public Object getObject() {
			return value;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaInteger.valueOf(value);
		}

		@Override
		public String toString() {
			return Byte.toString(value);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.value == ((ByteValue)other).value);
		}

		@Override
		public int hashCode() {
	        return value;
		}

		@Override
		public int toInteger() {
			return value;
		}

		@Override
		public long toLong() {
			return value;
		}
	}

	/**
	 * String value.
	 */
	public static final class StringValue extends Value {
		private final String value;

		public StringValue(String value) {
			this.value = value;
		}

		@Override
		public int estimateSize() {
			return Buffer.estimateSizeUtf8(value);
		}

		@Override
		public int write(byte[] buffer, int offset) {
			return Buffer.stringToUtf8(value, buffer, offset);
		}

		@Override
		public void pack(Packer packer) {
			packer.packString(value);
		}

		@Override
		public int getType() {
			return ParticleType.STRING;
		}

		@Override
		public Object getObject() {
			return value;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaString.valueOf(value);
		}

		@Override
		public String toString() {
			return value;
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.value.equals(((StringValue)other).value));
		}

		@Override
		public int hashCode() {
	        return value.hashCode();
		}
	}

	/**
	 * Integer value.
	 */
	public static final class IntegerValue extends Value {
		private final int value;

		public IntegerValue(int value) {
			this.value = value;
		}

		@Override
		public int estimateSize() {
			return 8;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			Buffer.longToBytes(value, buffer, offset);
			return 8;
		}

		@Override
		public void pack(Packer packer) {
			packer.packInt(value);
		}

		@Override
		public int getType() {
			return ParticleType.INTEGER;
		}

		@Override
		public Object getObject() {
			return value;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaInteger.valueOf(value);
		}

		@Override
		public String toString() {
			return Integer.toString(value);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.value == ((IntegerValue)other).value);
		}

		@Override
		public int hashCode() {
	        return value;
		}

		@Override
		public int toInteger() {
			return value;
		}

		@Override
		public long toLong() {
			return value;
		}
	}

	/**
	 * Long value.
	 */
	public static final class LongValue extends Value {
		private final long value;

		public LongValue(long value) {
			this.value = value;
		}

		@Override
		public int estimateSize() {
			return 8;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			Buffer.longToBytes(value, buffer, offset);
			return 8;
		}

		@Override
		public void pack(Packer packer) {
			packer.packLong(value);
		}

		@Override
		public int getType() {
			return ParticleType.INTEGER;
		}

		@Override
		public Object getObject() {
			return value;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaInteger.valueOf(value);
		}

		@Override
		public String toString() {
			return Long.toString(value);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.value == ((LongValue)other).value);
		}

		@Override
		public int hashCode() {
	        return (int)(value ^ (value >>> 32));
		}

		@Override
		public int toInteger() {
			return (int)value;
		}

		@Override
		public long toLong() {
			return value;
		}
	}

	/**
	 * Double value.
	 */
	public static final class DoubleValue extends Value {
		private final double value;

		public DoubleValue(double value) {
			this.value = value;
		}

		@Override
		public int estimateSize() {
			return 8;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			Buffer.doubleToBytes(value, buffer, offset);
			return 8;
		}

		@Override
		public void pack(Packer packer) {
			packer.packDouble(value);
		}

		@Override
		public int getType() {
			return ParticleType.DOUBLE;
		}

		@Override
		public Object getObject() {
			return value;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaDouble.valueOf(value);
		}

		@Override
		public String toString() {
			return Double.toString(value);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.value == ((DoubleValue)other).value);
		}

		@Override
		public int hashCode() {
	        long bits = Double.doubleToLongBits(value);
	        return (int)(bits ^ (bits >>> 32));
		}

		@Override
		public int toInteger() {
			return (int)value;
		}

		@Override
		public long toLong() {
			return (long)value;
		}
	}

	/**
	 * Float value.
	 */
	public static final class FloatValue extends Value {
		private final float value;

		public FloatValue(float value) {
			this.value = value;
		}

		@Override
		public int estimateSize() {
			return 8;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			Buffer.doubleToBytes(value, buffer, offset);
			return 8;
		}

		@Override
		public void pack(Packer packer) {
			packer.packFloat(value);
		}

		@Override
		public int getType() {
			return ParticleType.DOUBLE;
		}

		@Override
		public Object getObject() {
			return value;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaDouble.valueOf(value);
		}

		@Override
		public String toString() {
			return Float.toString(value);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.value == ((FloatValue)other).value);
		}

		@Override
		public int hashCode() {
	        return Float.floatToIntBits(value);
		}

		@Override
		public int toInteger() {
			return (int)value;
		}

		@Override
		public long toLong() {
			return (long)value;
		}
	}

	/**
	 * Boolean value.
	 */
	public static final class BooleanValue extends Value {
		private final boolean value;

		public BooleanValue(boolean value) {
			this.value = value;
		}

		@Override
		public int estimateSize() {
			return 8;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			Buffer.longToBytes(value? 1L : 0L, buffer, offset);
			return 8;
		}

		@Override
		public void pack(Packer packer) {
			packer.packBoolean(value);
		}

		@Override
		public int getType() {
			// The server does not natively handle boolean, so store as long (8 byte integer).
			return ParticleType.INTEGER;
		}

		@Override
		public Object getObject() {
			return value;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaBoolean.valueOf(value);
		}

		@Override
		public String toString() {
			return Boolean.toString(value);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.value == ((BooleanValue)other).value);
		}

		@Override
		public int hashCode() {
	        return value ? 1231 : 1237;
		}

		@Override
		public int toInteger() {
			return value? 1 : 0;
		}

		@Override
		public long toLong() {
			return value? 1L : 0L;
		}
	}

	/**
	 * Blob value.
	 */
	public static final class BlobValue extends Value {
		private final Object object;
		private byte[] bytes;

		public BlobValue(Object object) {
			this.object = object;
		}

		@Override
		public int estimateSize() throws AerospikeException.Serialize {
			try {
				ByteArrayOutputStream bstream = new ByteArrayOutputStream();
				ObjectOutputStream ostream = new ObjectOutputStream(bstream);
				ostream.writeObject(object);
				ostream.close();
				bytes = bstream.toByteArray();
				return bytes.length;
			}
			catch (Exception e) {
				throw new AerospikeException.Serialize(e);
			}
		}

		@Override
		public int write(byte[] buffer, int offset) {
			System.arraycopy(bytes, 0, buffer, offset, bytes.length);
			return bytes.length;
		}

		@Override
		public void pack(Packer packer) {
			packer.packBlob(object);
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: jblob");
		}

		@Override
		public int getType() {
			return ParticleType.JBLOB;
		}

		@Override
		public Object getObject() {
			return object;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaString.valueOf(bytes);
		}

		@Override
		public String toString() {
			return Buffer.bytesToHexString(bytes);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.object.equals(((BlobValue)other).object));
		}

		@Override
		public int hashCode() {
	        return object.hashCode();
		}
	}

	/**
	 * GeoJSON value.
	 */
	public static final class GeoJSONValue extends Value {
		private final String value;

		public GeoJSONValue(String value) {
			this.value = value;
		}

		@Override
		public int estimateSize() {
			// flags + ncells + jsonstr
			return 1 + 2 + Buffer.estimateSizeUtf8(value);
		}

		@Override
		public int write(byte[] buffer, int offset) {
			buffer[offset] = 0; // flags
			Buffer.shortToBytes(0, buffer, offset + 1); // ncells
			return 1 + 2 + Buffer.stringToUtf8(value, buffer, offset + 3); // jsonstr
		}

		@Override
		public void pack(Packer packer) {
			packer.packGeoJSON(value);
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: GeoJson");
		}

		@Override
		public int getType() {
			return ParticleType.GEOJSON;
		}

		@Override
		public Object getObject() {
			return value;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaString.valueOf(value);
		}

		@Override
		public String toString() {
			return value;
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.value.equals(((GeoJSONValue)other).value));
		}

		@Override
		public int hashCode() {
	        return value.hashCode();
		}
	}

	/**
	 * HyperLogLog value.
	 */
	public static final class HLLValue extends Value {
		private final byte[] bytes;

		public HLLValue(byte[] bytes) {
			this.bytes = bytes;
		}

		@Override
		public int estimateSize() {
			return bytes.length;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			System.arraycopy(bytes, 0, buffer, offset, bytes.length);
			return bytes.length;
		}

		@Override
		public void pack(Packer packer) {
			packer.packBytes(bytes);
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: HLL");
		}

		@Override
		public int getType() {
			return ParticleType.HLL;
		}

		@Override
		public Object getObject() {
			return bytes;
		}

		public byte[] getBytes() {
			return bytes;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return new LuaBytes(instance, bytes);
		}

		@Override
		public String toString() {
			return Buffer.bytesToHexString(bytes);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				Arrays.equals(this.bytes, ((HLLValue)other).bytes));
		}

		@Override
		public int hashCode() {
			return Arrays.hashCode(bytes);
		}
	}

	/**
	 * Value array.
	 */
	public static final class ValueArray extends Value {
		private final Value[] array;
		private byte[] bytes;

		public ValueArray(Value[] array) {
			this.array = array;
		}

		@Override
		public int estimateSize() throws AerospikeException {
			bytes = Packer.pack(array);
			return bytes.length;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			System.arraycopy(bytes, 0, buffer, offset, bytes.length);
			return bytes.length;
		}

		@Override
		public void pack(Packer packer) {
			packer.packValueArray(array);
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: value[]");
		}

		@Override
		public int getType() {
			return ParticleType.LIST;
		}

		@Override
		public Object getObject() {
			return array;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return instance.getLuaList(array);
		}

		@Override
		public String toString() {
			return Arrays.toString(array);
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				Arrays.equals(this.array, ((ValueArray)other).array));
		}

		@Override
		public int hashCode() {
			return Arrays.hashCode(array);
		}
	}

	/**
	 * List value.
	 */
	public static final class ListValue extends Value {
		private final List<?> list;
		private byte[] bytes;

		public ListValue(List<?> list) {
			this.list = list;
		}

		@Override
		public int estimateSize() throws AerospikeException {
			bytes = Packer.pack(list);
			return bytes.length;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			System.arraycopy(bytes, 0, buffer, offset, bytes.length);
			return bytes.length;
		}

		@Override
		public void pack(Packer packer) {
			packer.packList(list);
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: list");
		}

		@Override
		public int getType() {
			return ParticleType.LIST;
		}

		@Override
		public Object getObject() {
			return list;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return instance.getLuaList(list);
		}

		@Override
		public String toString() {
			return list.toString();
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.list.equals(((ListValue)other).list));
		}

		@Override
		public int hashCode() {
	        return list.hashCode();
		}
	}

	/**
	 * Map value.
	 */
	public static final class MapValue extends Value {
		private final Map<?,?> map;
		private byte[] bytes;

		public MapValue(Map<?,?> map)  {
			this.map = map;
		}

		@Override
		public int estimateSize() throws AerospikeException {
			bytes = Packer.pack(map);
			return bytes.length;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			System.arraycopy(bytes, 0, buffer, offset, bytes.length);
			return bytes.length;
		}

		@Override
		public void pack(Packer packer) {
			packer.packMap(map);
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: map");
		}

		@Override
		public int getType() {
			return ParticleType.MAP;
		}

		@Override
		public Object getObject() {
			return map;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return instance.getLuaMap(map);
		}

		@Override
		public String toString() {
			return map.toString();
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.map.equals(((MapValue)other).map));
		}

		@Override
		public int hashCode() {
	        return map.hashCode();
		}
	}

	/**
	 * Sorted map value.
	 */
	public static final class SortedMapValue extends Value {
		private final List<? extends Entry<?,?>> list;
		private byte[] bytes;
		private final MapOrder order;

		public SortedMapValue(List<? extends Entry<?,?>> list, MapOrder order)  {
			this.list = list;
			this.order = order;
		}

		@Override
		public int estimateSize() throws AerospikeException {
			bytes = Packer.pack(list, order);
			return bytes.length;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			System.arraycopy(bytes, 0, buffer, offset, bytes.length);
			return bytes.length;
		}

		@Override
		public void pack(Packer packer) {
			packer.packMap(list, order);
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: map");
		}

		@Override
		public int getType() {
			return ParticleType.MAP;
		}

		@Override
		public Object getObject() {
			return list;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			return instance.getLuaList(list);
		}

		@Override
		public String toString() {
			return list.toString();
		}

		@Override
		public boolean equals(Object other) {
			if (other == null || ! this.getClass().equals(other.getClass())) {
				return false;
			}
			SortedMapValue o = (SortedMapValue)other;
			return this.order == o.order && this.list.equals(o.list);
		}

		@Override
		public int hashCode() {
	        return list.hashCode();
		}
	}

	/**
	 * Infinity value.
	 */
	public static final class InfinityValue extends Value {
		@Override
		public int estimateSize() {
			return 0;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			return 0;
		}

		@Override
		public void pack(Packer packer) {
			packer.packInfinity();
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: INF");
		}

		@Override
		public int getType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid particle type: INF");
		}

		@Override
		public Object getObject() {
			return null;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid lua type: INF");
		}

		@Override
		public String toString() {
			return "INF";
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
					this.getClass().equals(other.getClass()));
		}

		@Override
		public final int hashCode() {
			return 0;
		}
	}

	/**
	 * Wildcard value.
	 */
	public static final class WildcardValue extends Value {
		@Override
		public int estimateSize() {
			return 0;
		}

		@Override
		public int write(byte[] buffer, int offset) {
			return 0;
		}

		@Override
		public void pack(Packer packer) {
			packer.packWildcard();
		}

		@Override
		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: wildcard");
		}

		@Override
		public int getType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid particle type: wildcard");
		}

		@Override
		public Object getObject() {
			return null;
		}

		@Override
		public LuaValue getLuaValue(LuaInstance instance) {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid lua type: wildcard");
		}

		@Override
		public String toString() {
			return "*";
		}

		@Override
		public boolean equals(Object other) {
			return (other != null &&
					this.getClass().equals(other.getClass()));
		}

		@Override
		public final int hashCode() {
			return 0;
		}
	}
}

## 内容2
### 文件路径：
client/src/com/aerospike/client/command/Buffer.java
### 代码内容：
package com.aerospike.client.command;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.Arrays;

import com.aerospike.client.AerospikeException;
import com.aerospike.client.Value;
import com.aerospike.client.util.Unpacker;

public final class Buffer {

	public static Value bytesToKeyValue(int type, byte[] buf, int offset, int len)
		throws AerospikeException {

		switch (type) {
		case ParticleType.STRING:
			return Value.get(Buffer.utf8ToString(buf, offset, len));

		case ParticleType.INTEGER:
			return bytesToLongValue(buf, offset, len);

		case ParticleType.DOUBLE:
			return new Value.DoubleValue(Buffer.bytesToDouble(buf, offset));

		case ParticleType.BLOB:
			return Value.get(Arrays.copyOfRange(buf, offset, offset+len));

		default:
			return null;
		}
	}

	public static Object bytesToParticle(int type, byte[] buf, int offset, int len)
		throws AerospikeException {

		switch (type) {
		case ParticleType.STRING:
			return Buffer.utf8ToString(buf, offset, len);

		case ParticleType.INTEGER:
			return Buffer.bytesToNumber(buf, offset, len);

		case ParticleType.DOUBLE:
			return Buffer.bytesToDouble(buf, offset);

		case ParticleType.BLOB:
			return Arrays.copyOfRange(buf, offset, offset+len);

		case ParticleType.JBLOB:
			return Buffer.bytesToObject(buf, offset, len);

		case ParticleType.GEOJSON:
			return Buffer.bytesToGeoJSON(buf, offset, len);

		case ParticleType.HLL:
			return Buffer.bytesToHLL(buf, offset, len);

		case ParticleType.LIST:
			return Unpacker.unpackObjectList(buf, offset, len);

		case ParticleType.MAP:
			return Unpacker.unpackObjectMap(buf, offset, len);

		default:
			return null;
		}
	}

	/*
	private static Object parseList(byte[] buf, int offset, int len) throws AerospikeException {
		int limit = offset + len;
		int itemCount = Buffer.bytesToInt(buf, offset);
		offset += 4;
		ArrayList<Object> list = new ArrayList<Object>(itemCount);

		while (offset < limit) {
			int sz = Buffer.bytesToInt(buf, offset);
			offset += 4;
			int type = buf[offset];
			offset++;
			list.add(bytesToParticle(type, buf, offset, sz));
			offset += sz;
		}
		return list;
	}

	private static Object parseMap(byte[] buf, int offset, int len) throws AerospikeException {
		Object key;
		Object value;

		int limit = offset + len;
		int n_items = Buffer.bytesToInt(buf, offset);
		offset += 4;
		HashMap<Object, Object> map = new HashMap<Object, Object>(n_items);

		while (offset < limit) {
			// read out the key
			int sz = Buffer.bytesToInt(buf, offset);
			offset += 4;
			int type = buf[offset];
			offset++;

			key = bytesToParticle(type, buf, offset, len);
			offset += sz;

			// read out the value
			sz = Buffer.bytesToInt(buf, offset);
			offset += 4;
			type = buf[offset];
			offset++;

			value = bytesToParticle(type, buf, offset, len);
			offset += sz;

			map.put(key, value);
		}
		return map;
	}
	*/

	/**
	 * Estimate size of Utf8 encoded bytes without performing the actual encoding.
	 */
	public static int estimateSizeUtf8(String value) {
		if (value == null) {
			return 0;
		}

		int max = value.length();
		int count = 0;

		for (int i = 0; i < max; i++) {
			char ch = value.charAt(i);

			if (ch < 0x80) {
				count++;
			}
			else if (ch < 0x800) {
			    count += 2;
			}
			else if (Character.isHighSurrogate(ch)) {
				count += 4;
				++i;
			} else {
				count += 3;
			}
		}
		return count;
	}

    public static byte[] stringToUtf8(String s) {
		if (s == null || s.length() == 0) {
			return new byte[0];
		}
		int size = estimateSizeUtf8(s);
		byte[] bytes = new byte[size];
		stringToUtf8(s, bytes, 0);
		return bytes;
    }

	/**
	 * Convert input string to UTF-8, copies into buffer (at given offset).
	 * Returns number of bytes in the string.
	 *
     * Java's internal UTF8 conversion is very, very slow.
     * This is, rather amazingly, 8x faster than the to-string method.
	 * Returns the number of bytes this translated into.
     */
    public static int stringToUtf8(String s, byte[] buf, int offset) {
        if (s == null) {
        	return 0;
        }
    	int length = s.length();
        int startOffset = offset;

        for (int i = 0; i < length; i++) {
            int c = s.charAt(i);
            if (c < 0x80) {
                buf[offset++] = (byte) c;
            }
            else if (c < 0x800) {
            	buf[offset++] = (byte)(0xc0 | ((c >> 6)));
            	buf[offset++] = (byte)(0x80 | (c & 0x3f));
            }
            else {
		    	// Encountered a different encoding other than 2-byte UTF8. Let java handle it.
            	try {
		    		byte[] value = s.getBytes("UTF8");
					System.arraycopy(value, 0, buf, startOffset, value.length);
					return value.length;
            	}
            	catch (UnsupportedEncodingException uee) {
            		throw new RuntimeException("UTF8 encoding is not supported.");
            	}
            }
        }
        return offset - startOffset;
    }

    public static String utf8ToString(byte[] buf, int offset, int length) {
    	// A Thread local implementation does not help here, so
    	// allocate character buffer each time.
    	if (length == 0) {
    		return "";
    	}

		char[] charBuffer = new char[length];
    	int charCount = 0;
        int limit = offset + length;
    	int origoffset = offset;

        while (offset < limit ) {
        	int b1 = buf[offset];

        	if (b1 >= 0) {
                charBuffer[charCount++] = (char)b1;
                offset++;
        	}
        	else if ((b1 >> 5) == -2) {
        		int b2 = buf[offset + 1];
        		charBuffer[charCount++] = (char) (((b1 << 6) ^ b2) ^ 0x0f80);
                offset += 2;
        	}
		    else {
		    	// Encountered an UTF encoding which uses more than 2 bytes.
		    	// Use a native function to do the conversion.
		    	try {
		    		return new String(buf, origoffset, length, "UTF8");
		    	}
		    	catch (UnsupportedEncodingException uee) {
            		throw new RuntimeException("UTF8 decoding is not supported.");
		    	}
		    }
        }
        return new String(charBuffer, 0, charCount);
    }

    public static String utf8ToString(byte[] buf, int offset, int length, StringBuilder sb) {
    	if (length == 0) {
    		return "";
    	}

    	// This method is designed to accommodate multiple string conversions on the same
    	// thread, but without the ThreadLocal overhead.  The StringBuilder instance is
    	// created on the stack and passed in each method invocation.
    	sb.setLength(0);
        int limit = offset + length;
    	int origoffset = offset;

        while (offset < limit ) {
            if ((buf[offset] & 0x80) == 0) { // 1 byte
                char c = (char) buf[offset];
                sb.append(c);
                offset++;
            }
            else if ((buf[offset] & 0xE0) == 0xC0) { // 2 bytes
                char c =  (char) (((buf[offset] & 0x1f) << 6) | (buf[offset+1] & 0x3f));
                sb.append(c);
                offset += 2;
            }
		    else {
		    	// Encountered an UTF encoding which uses more than 2 bytes.
		    	// Use a native function to do the conversion.
		    	try {
		    		return new String(buf, origoffset, length, "UTF8");
		    	}
		    	catch (UnsupportedEncodingException uee) {
            		throw new RuntimeException("UTF8 decoding is not supported.");
		    	}
		    }
        }
        return sb.toString();
    }

    /**
     * Convert UTF8 numeric digits to an integer.  Negative integers are not supported.
     *
     * Input format: 1234
     */
    public static int utf8DigitsToInt(byte[] buf, int begin, int end) {
    	int val = 0;
    	int mult = 1;

    	for (int i = end - 1; i >= begin; i--) {
    		val += ((int)buf[i] - 48) * mult;
    		mult *= 10;
    	}
    	return val;
    }

    public static String bytesToHexString(byte[] buf) {
    	if (buf == null || buf.length == 0) {
    		return "";
    	}
		StringBuilder sb = new StringBuilder(buf.length * 2);

		for (int i = 0; i < buf.length; i++) {
    		sb.append(String.format("%02x", buf[i]));
		}
		return sb.toString();
    }

    public static String bytesToHexString(byte[] buf, int offset, int length) {
		StringBuilder sb = new StringBuilder(length * 2);

		for (int i = offset; i < length; i++) {
    		sb.append(String.format("%02x", buf[i]));
		}
		return sb.toString();
    }

    public static Object bytesToObject(byte[] buf, int offset, int length)
		throws AerospikeException.Serialize {

    	if (length <= 0) {
    		return null;
    	}

		try {
			ByteArrayInputStream bastream = new ByteArrayInputStream(buf, offset, length);
			ObjectInputStream oistream = new ObjectInputStream(bastream);
			return oistream.readObject();
		}
		catch (Exception e) {
    		throw new AerospikeException.Serialize(e);
		}
	}

	public static Value bytesToLongValue(byte[] buf, int offset, int len) {
		long val = 0;

		for (int i = 0; i < len; i++) {
			val <<= 8;
			val |= buf[offset+i] & 0xFF;
		}

		return new Value.LongValue(val);
	}

	public static Object bytesToGeoJSON(byte[] buf, int offset, int len) {
		// Ignore the flags for now
		int ncells = bytesToShort(buf, offset + 1);
		int hdrsz = 1 + 2 + (ncells * 8);
		return Value.getAsGeoJSON(Buffer.utf8ToString(buf, offset + hdrsz, len - hdrsz));
	}

	public static Object bytesToHLL(byte[] buf, int offset, int len) {
		byte[] bytes = Arrays.copyOfRange(buf, offset, offset+len);
		return Value.getAsHLL(bytes);
	}

	public static Object bytesToNumber(byte[] buf, int offset, int len) {
		// Server always returns 8 for integer length.
		if (len == 8) {
			return bytesToLong(buf, offset);
		}

		// Handle other lengths just in case server changes.
		if (len == 0) {
			return new Long(0);
		}

		if (len == 4) {
			return new Long(bytesToInt(buf, offset));
		}

		if (len > 8) {
			return bytesToBigInteger(buf, offset, len);
		}

		// Handle variable length integer.
		long val = 0;

		for (int i = 0; i < len; i++) {
			val <<= 8;
			val |= buf[offset+i] & 0xFF;
		}
		return new Long(val);
	}

	public static Object bytesToBigInteger(byte[] buf, int offset, int len) {
		boolean negative = false;

		if ((buf[offset] & 0x80) != 0) {
			negative = true;
			buf[offset] &= 0x7f;
		}
		byte[] bytes = new byte[len];
		System.arraycopy(buf, offset, bytes, 0, len);

		BigInteger big = new BigInteger(bytes);

		if (negative) {
			big = big.negate();
		}
		return big;
	}

	//-------------------------------------------------------
	// 64 bit double conversions.
	//-------------------------------------------------------

	public static double bytesToDouble(byte[] buf, int offset) {
		return Double.longBitsToDouble(bytesToLong(buf, offset));
	}

	public static void doubleToBytes(double v, byte[] buf, int offset) {
		Buffer.longToBytes(Double.doubleToLongBits(v), buf, offset);
	}

	//-------------------------------------------------------
	// 64 bit number conversions.
	//-------------------------------------------------------

    /**
     * Convert long to big endian signed or unsigned 64 bits.
     * The bit pattern will be the same regardless of sign.
     */
	public static void longToBytes(long v, byte[] buf, int offset) {
		buf[offset++] = (byte)(v >>> 56);
		buf[offset++] = (byte)(v >>> 48);
		buf[offset++] = (byte)(v >>> 40);
		buf[offset++] = (byte)(v >>> 32);
		buf[offset++] = (byte)(v >>> 24);
		buf[offset++] = (byte)(v >>> 16);
		buf[offset++] = (byte)(v >>>  8);
		buf[offset]   = (byte)(v >>>  0);
	}

    /**
     * Convert long to little endian signed or unsigned 64 bits.
     * The bit pattern will be the same regardless of sign.
     */
	public static void longToLittleBytes(long v, byte[] buf, int offset) {
		buf[offset++] = (byte)(v >>> 0);
		buf[offset++] = (byte)(v >>> 8);
		buf[offset++] = (byte)(v >>> 16);
		buf[offset++] = (byte)(v >>> 24);
		buf[offset++] = (byte)(v >>> 32);
		buf[offset++] = (byte)(v >>> 40);
		buf[offset++] = (byte)(v >>> 48);
		buf[offset]   = (byte)(v >>> 56);
	}

    /**
     * Convert big endian signed 64 bits to long.
     */
	public static long bytesToLong(byte[] buf, int offset) {
       return (
    		((long)(buf[offset]   & 0xFF) << 56) |
   			((long)(buf[offset+1] & 0xFF) << 48) |
   			((long)(buf[offset+2] & 0xFF) << 40) |
   			((long)(buf[offset+3] & 0xFF) << 32) |
   			((long)(buf[offset+4] & 0xFF) << 24) |
   			((long)(buf[offset+5] & 0xFF) << 16) |
   			((long)(buf[offset+6] & 0xFF) << 8) |
   			((long)(buf[offset+7] & 0xFF) << 0)
   			);
    }

    /**
     * Convert little endian signed 64 bits to long.
     */
    public static long littleBytesToLong(byte[] buf, int offset) {
        return (
			((long)(buf[offset]   & 0xFF) << 0) |
			((long)(buf[offset+1] & 0xFF) << 8) |
			((long)(buf[offset+2] & 0xFF) << 16) |
			((long)(buf[offset+3] & 0xFF) << 24) |
			((long)(buf[offset+4] & 0xFF) << 32) |
			((long)(buf[offset+5] & 0xFF) << 40) |
			((long)(buf[offset+6] & 0xFF) << 48) |
			((long)(buf[offset+7] & 0xFF) << 56)
			);
    }

	//-------------------------------------------------------
	// 32 bit number conversions.
	//-------------------------------------------------------

    /**
     * Convert int to big endian signed or unsigned 32 bits.
     * The bit pattern will be the same regardless of sign.
     */
	public static void intToBytes(int v, byte[] buf, int offset) {
		buf[offset++] = (byte)(v >>> 24);
		buf[offset++] = (byte)(v >>> 16);
		buf[offset++] = (byte)(v >>> 8);
		buf[offset]   = (byte)(v >>> 0);
	}

    /**
     * Convert int to little endian signed or unsigned 32 bits.
     * The bit pattern will be the same regardless of sign.
     */
	public static void intToLittleBytes(int v, byte[] buf, int offset) {
		buf[offset++] = (byte)(v >>> 0);
		buf[offset++] = (byte)(v >>> 8);
		buf[offset++] = (byte)(v >>> 16);
		buf[offset]   = (byte)(v >>> 24);
	}

    /**
     * Convert big endian signed 32 bits to int.
     */
	public static int bytesToInt(byte[] buf, int offset) {
		return (
			((buf[offset]   & 0xFF) << 24) |
			((buf[offset+1] & 0xFF) << 16) |
			((buf[offset+2] & 0xFF) << 8) |
			((buf[offset+3] & 0xFF) << 0)
			);
	}

    /**
     * Convert little endian signed 32 bits to int.
     */
	public static int littleBytesToInt(byte[] buf, int offset) {
		return (
			((buf[offset]   & 0xFF) << 0) |
			((buf[offset+1] & 0xFF) << 8) |
			((buf[offset+2] & 0xFF) << 16) |
			((buf[offset+3] & 0xFF) << 24)
			);
	}

    /**
     * Convert big endian unsigned 32 bits to long.
     */
	public static long bigUnsigned32ToLong(byte[] buf, int offset) {
		return (
			((long)(buf[offset]   & 0xFF) << 24) |
			((long)(buf[offset+1] & 0xFF) << 16) |
			((long)(buf[offset+2] & 0xFF) << 8) |
			((long)(buf[offset+3] & 0xFF) << 0)
			);
	}

	//-------------------------------------------------------
	// 16 bit number conversions.
	//-------------------------------------------------------

    /**
     * Convert int to big endian signed or unsigned 16 bits.
     * The bit pattern will be the same regardless of sign.
     */
    public static void shortToBytes(int v, byte[] buf, int offset) {
        buf[offset++] = (byte)(v >>> 8);
        buf[offset]   = (byte)(v >>> 0);
    }

    /**
     * Convert int to little endian signed or unsigned 16 bits.
     * The bit pattern will be the same regardless of sign.
     */
    public static void shortToLittleBytes(int v, byte[] buf, int offset) {
        buf[offset++] = (byte)(v >>> 0);
        buf[offset]   = (byte)(v >>> 8);
    }

    /**
     * Convert big endian unsigned 16 bits to int.
     */
    public static int bytesToShort(byte[] buf, int offset) {
        return (
			((buf[offset]   & 0xFF) << 8) |
			((buf[offset+1] & 0xFF) << 0)
        	);
    }

    /**
     * Convert little endian unsigned 16 bits to int.
     */
    public static int littleBytesToShort(byte[] buf, int offset) {
        return (
			((buf[offset]   & 0xFF) << 0) |
			((buf[offset+1] & 0xFF) << 8)
			);
    }

    /**
     * Convert big endian signed 16 bits to short.
     */
    public static short bigSigned16ToShort(byte[] buf, int offset) {
        return (short)(
			((buf[offset]   & 0xFF) << 8) |
			((buf[offset+1] & 0xFF) << 0)
        	);
    }

    //-------------------------------------------------------
	// Variable byte number conversions.
	//-------------------------------------------------------

    /**
     *	Encode an integer in variable 7-bit format.
     *	The high bit indicates if more bytes are used.
     *  Return byte size of integer.
     */
    public static int intToVarBytes(int v, byte[] buf, int offset) {
    	int i = offset;

    	while (i < buf.length && v >= 0x80) {
    		buf[i++] = (byte)(v | 0x80);
    		v >>>= 7;
    	}

    	if (i < buf.length) {
    		buf[i++] = (byte)v;
    		return i - offset;
    	}
    	return 0;
    }

    /**
     *	Decode an integer in variable 7-bit format.
     *	The high bit indicates if more bytes are used.
     *  Return value and byte size in array.
     */
    public static int[] varBytesToInt(byte[] buf, int offset) {
		int i = offset;
		int val = 0;
		int shift = 0;
		byte b;

		do {
			b = buf[i++];
			val |= (b & 0x7F) << shift;
			shift += 7;
		} while ((b & 0x80) != 0);

		return new int[] {val, i - offset};
    }
}

## 内容3
### 文件路径：
client/src/com/aerospike/client/util/Packer.java
### 代码内容：
package com.aerospike.client.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.aerospike.client.AerospikeException;
import com.aerospike.client.Value;
import com.aerospike.client.cdt.MapOrder;
import com.aerospike.client.command.Buffer;
import com.aerospike.client.command.ParticleType;

/**
 * Serialize collection objects using MessagePack format specification:
 *
 * https://github.com/msgpack/msgpack/blob/master/spec.md
 */
public final class Packer {

	public static byte[] pack(Value[] val) throws AerospikeException {
		try {
			Packer packer = new Packer();
			packer.packValueArray(val);
			return packer.toByteArray();
		}
		catch (Exception e) {
			throw new AerospikeException.Serialize(e);
		}
	}

	public static byte[] pack(List<?> val) throws AerospikeException {
		try {
			Packer packer = new Packer();
			packer.packList(val);
			return packer.toByteArray();
		}
		catch (Exception e) {
			throw new AerospikeException.Serialize(e);
		}
	}

	public static byte[] pack(Map<?,?> val) throws AerospikeException {
		try {
			Packer packer = new Packer();
			packer.packMap(val);
			return packer.toByteArray();
		}
		catch (Exception e) {
			throw new AerospikeException.Serialize(e);
		}
	}

	public static byte[] pack(List<? extends Entry<?,?>> val, MapOrder order) throws AerospikeException {
		try {
			Packer packer = new Packer();
			packer.packMap(val, order);
			return packer.toByteArray();
		}
		catch (Exception e) {
			throw new AerospikeException.Serialize(e);
		}
	}

	private byte[] buffer;
	private int offset;
	private ArrayList<BufferItem> bufferList;

	public Packer() {
		this.buffer = ThreadLocalData.getBuffer();
	}

	public void packValueArray(Value[] values) {
		packArrayBegin(values.length);
		for (Value value : values) {
			value.pack(this);
		}
	}

	public void packValueList(List<Value> list) {
		packArrayBegin(list.size());
		for (Value value : list) {
			value.pack(this);
		}
	}

	public void packList(List<?> list) {
		packArrayBegin(list.size());
		for (Object obj : list) {
			packObject(obj);
		}
	}

	public void packArrayBegin(int size) {
        if (size < 16) {
        	packByte(0x90 | size);
        }
        else if (size < 65536) {
        	packShort(0xdc, size);
        }
        else {
        	packInt(0xdd, size);
        }
    }

	public void packValueMap(Map<Value,Value> map) {
		packMapBegin(map.size());
		for (Entry<Value,Value> entry : map.entrySet()) {
			entry.getKey().pack(this);
			entry.getValue().pack(this);
		}
	}

	public void packMap(Map<?,?> map) {
		packMapBegin(map.size());
		for (Entry<?,?> entry : map.entrySet()) {
			packObject(entry.getKey());
			packObject(entry.getValue());
		}
	}

	public void packMap(List<? extends Entry<?,?>> list, MapOrder order) {
		int attr = order.attributes;

		if (attr > 0) {
			// Map is sorted.
			packMapBegin(list.size() + 1);
			packByte(0xc7);
			packByte(0);
			packByte(attr);
			packByte(0xc0);
		}
		else {
			packMapBegin(list.size());
		}

		for (Entry<?,?> entry : list) {
			packObject(entry.getKey());
			packObject(entry.getValue());
		}
	}

	public void packMapBegin(int size) {
        if (size < 16) {
        	packByte(0x80 | size);
        }
        else if (size < 65536) {
        	packShort(0xde, size);
        }
        else {
        	packInt(0xdf, size);
        }
    }

	public void packBytes(byte[] b) {
    	packByteArrayBegin(b.length + 1);
    	packByte(ParticleType.BLOB);
    	packByteArray(b, 0, b.length);
    }

	public void packBytes(byte[] b, int type) {
    	packByteArrayBegin(b.length + 1);
    	packByte(type);
    	packByteArray(b, 0, b.length);
    }

	public void packBytes(byte[] b, int offset, int length) {
    	packByteArrayBegin(length + 1);
    	packByte(ParticleType.BLOB);
    	packByteArray(b, offset, length);
	}

	public void packBlob(Object val) throws AerospikeException {
		ByteArrayOutputStream bstream = new ByteArrayOutputStream();

		try {
			ObjectOutputStream ostream = new ObjectOutputStream(bstream);
			ostream.writeObject(val);
			ostream.close();
		}
		catch (IOException ioe) {
			throw new AerospikeException.Serialize(ioe);
		}

		byte[] bytes = bstream.toByteArray();
        packByteArrayBegin(bytes.length + 1);
    	packByte(ParticleType.JBLOB);
    	packByteArray(bytes, 0, bytes.length);
	}

	public void packGeoJSON(String val) {
		byte[] buffer = Buffer.stringToUtf8(val);
		packByteArrayBegin(buffer.length + 1);
		packByte(ParticleType.GEOJSON);
		packByteArray(buffer, 0, buffer.length);
	}

	private void packByteArrayBegin(int size) {
		// Continue to pack byte arrays as strings until all servers/clients
		// have been upgraded to handle new message pack binary type.
		if (size < 32) {
			packByte(0xa0 | size);
		}
		else if (size < 65536) {
			packShort(0xda, size);
		}
		else {
			packInt(0xdb, size);
		}

		// TODO: Replace with this code after all servers/clients
		// have been upgraded to handle new message pack binary type.
		/*
		if (size < 32) {
			packByte(0xa0 | size);
		}
		else if (size < 256) {
			packByte(0xc4, size);
		}
		else if (size < 65536) {
			packShort(0xc5, size);
		}
		else {
			packInt(0xc6, size);
		}*/
	}

	public void packObject(Object obj) {
		if (obj == null) {
			packNil();
			return;
		}

		if (obj instanceof Value) {
			Value value = (Value) obj;
			value.pack(this);
			return;
		}

		if (obj instanceof byte[]) {
			packBytes((byte[]) obj);
			return;
		}

		if (obj instanceof String) {
			packString((String) obj);
			return;
		}

		if (obj instanceof Integer) {
			packInt((Integer) obj);
			return;
		}

		if (obj instanceof Long) {
			packLong((Long) obj);
			return;
		}

		if (obj instanceof Double) {
			packDouble((Double) obj);
			return;
		}

		if (obj instanceof Float) {
			packFloat((Float) obj);
			return;
		}

		if (obj instanceof Boolean) {
			packBoolean((Boolean)obj);
			return;
		}

		if (obj instanceof List<?>) {
			packList((List<?>) obj);
			return;
		}

		if (obj instanceof Map<?,?>) {
			packMap((Map<?,?>) obj);
			return;
		}

		if (obj instanceof ByteBuffer) {
			packByteBuffer((ByteBuffer) obj);
			return;
		}

		packBlob(obj);
	}

	public void packByteBuffer(ByteBuffer bb) {
		byte[] b = bb.array();
		packBytes(b);
	}

	public void packLong(long val) {
    	if (val >= 0L) {
        	if (val < 128L) {
        		packByte((int)val);
        		return;
        	}

        	if (val < 256L) {
        		packByte(0xcc, (int)val);
        		return;
        	}

        	if (val < 65536L) {
        		packShort(0xcd, (int)val);
        		return;
        	}

        	if (val < 4294967296L) {
        		packInt(0xce, (int)val);
        		return;
        	}
        	packLong(0xcf, val);
    	}
    	else {
        	if (val >= -32) {
        		packByte(0xe0 | ((int)val + 32));
        		return;
        	}

        	if (val >= Byte.MIN_VALUE) {
                packByte(0xd0, (int)val);
                return;
        	}

        	if (val >= Short.MIN_VALUE) {
                packShort(0xd1, (int)val);
                return;
        	}

        	if (val >= Integer.MIN_VALUE) {
        		packInt(0xd2, (int)val);
                return;
        	}
        	packLong(0xd3, val);
    	}
    }

    public void packInt(int val) {
    	if (val >= 0) {
        	if (val < 128) {
        		packByte(val);
        		return;
        	}

        	if (val < 256) {
        		packByte(0xcc, val);
        		return;
        	}

        	if (val < 65536) {
        		packShort(0xcd, val);
        		return;
        	}
        	packInt(0xce, val);
    	}
    	else {
        	if (val >= -32) {
        		packByte(0xe0 | (val + 32));
        		return;
        	}

        	if (val >= Byte.MIN_VALUE) {
                packByte(0xd0, val);
                return;
        	}

        	if (val >= Short.MIN_VALUE) {
                packShort(0xd1, val);
                return;
        	}
        	packInt(0xd2, val);
    	}
    }

	public void packString(String val) {
		int size = Buffer.estimateSizeUtf8(val) + 1;

		if (size < 32) {
			packByte(0xa0 | size);
		}
		// TODO: Enable this code after all servers/clients
		// have been upgraded to handle 8 bit string length format.
		/*
		else if (size < 256) {
			packByte(0xd9, size);
		}
		*/
		else if (size < 65536) {
			packShort(0xda, size);
		}
		else {
			packInt(0xdb, size);
		}

		if (offset + size > buffer.length) {
			resize(size);
		}
		buffer[offset++] = (byte)ParticleType.STRING;
		offset += Buffer.stringToUtf8(val, buffer, offset);
	}

	private void packByteArray(byte[] src, int srcOffset, int srcLength) {
       	if (offset + srcLength > buffer.length) {
    		resize(srcLength);
    	}
 		System.arraycopy(src, srcOffset, buffer, offset, srcLength);
		offset += srcLength;
    }

    public void packDouble(double val) {
    	if (offset + 9 > buffer.length) {
    		resize(9);
    	}
    	buffer[offset++] = (byte)0xcb;
    	Buffer.longToBytes(Double.doubleToLongBits(val), buffer, offset);
    	offset += 8;
    }

    public void packFloat(float val) {
    	if (offset + 5 > buffer.length) {
    		resize(5);
    	}
    	buffer[offset++] = (byte)0xca;
    	Buffer.intToBytes(Float.floatToIntBits(val), buffer, offset);
    	offset += 4;
    }

    private void packLong(int type, long val) {
    	if (offset + 9 > buffer.length) {
    		resize(9);
    	}
    	buffer[offset++] = (byte)type;
    	Buffer.longToBytes(val, buffer, offset);
    	offset += 8;
    }

    private void packInt(int type, int val) {
    	if (offset + 5 > buffer.length) {
    		resize(5);
    	}
    	buffer[offset++] = (byte)type;
    	Buffer.intToBytes(val, buffer, offset);
    	offset += 4;
    }

    private void packShort(int type, int val) {
    	if (offset + 3 > buffer.length) {
    		resize(3);
    	}
    	buffer[offset++] = (byte)type;
    	Buffer.shortToBytes(val, buffer, offset);
    	offset += 2;
    }

    public void packRawShort(int val) {
    	// WARNING. This method is not compatible with message pack standard.
    	if (offset + 2 > buffer.length) {
    		resize(2);
    	}
    	Buffer.shortToBytes(val, buffer, offset);
    	offset += 2;
    }

    private void packByte(int type, int val) {
    	if (offset + 2 > buffer.length) {
    		resize(2);
    	}
    	buffer[offset++] = (byte)type;
    	buffer[offset++] = (byte)val;
    }

    public void packBoolean(boolean val) {
    	if (offset + 1 > buffer.length) {
    		resize(1);
    	}

    	if (val) {
    		buffer[offset++] = (byte)0xc3;
    	}
    	else {
    		buffer[offset++] = (byte)0xc2;
    	}
    }

    public void packNil() {
    	if (offset >= buffer.length) {
    		resize(1);
    	}
    	buffer[offset++] = (byte)0xc0;
    }

	public void packInfinity() {
		if (offset + 3 > buffer.length) {
			resize(3);
		}
		buffer[offset++] = (byte)0xd4;
		buffer[offset++] = (byte)0xff;
		buffer[offset++] = (byte)0x01;
	}

	public void packWildcard() {
		if (offset + 3 > buffer.length) {
			resize(3);
		}
		buffer[offset++] = (byte)0xd4;
		buffer[offset++] = (byte)0xff;
		buffer[offset++] = (byte)0x00;
	}

	public void packByte(int val) {
    	if (offset >= buffer.length) {
    		resize(1);
    	}
    	buffer[offset++] = (byte)val;
    }

    private void resize(int size) {
    	if (bufferList == null) {
    		bufferList = new ArrayList<BufferItem>();
    	}
    	bufferList.add(new BufferItem(buffer, offset));

    	if (size < buffer.length) {
    		size = buffer.length;
    	}
    	buffer = new byte[size];
    	offset = 0;
    }

    public byte[] toByteArray() {
    	if (bufferList != null) {
        	int size = offset;
    		for (BufferItem item : bufferList) {
    			size += item.length;
    		}

    		byte[] target = new byte[size];
    		size = 0;
    		for (BufferItem item : bufferList) {
            	System.arraycopy(item.buffer, 0, target, size, item.length);
    			size += item.length;
    		}

    		System.arraycopy(buffer, 0, target, size, offset);
        	return target;
    	}
    	else {
        	byte[] target = new byte[offset];
        	System.arraycopy(buffer, 0, target, 0, offset);
        	return target;
    	}
	}

    private static final class BufferItem {
    	private byte[] buffer;
    	private int length;

    	private BufferItem(byte[] buffer, int length) {
    		this.buffer = buffer;
    		this.length = length;
    	}
    }
}

## 内容4
### 文件路径：
client/src/com/aerospike/client/util/Unpacker.java
### 代码内容：
package com.aerospike.client.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.nio.ByteBuffer;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import com.aerospike.client.AerospikeException;
import com.aerospike.client.Value;
import com.aerospike.client.command.Buffer;
import com.aerospike.client.command.ParticleType;

/**
 * De-serialize collection objects using MessagePack format specification:
 *
 * https://github.com/msgpack/msgpack/blob/master/spec.md
 */
public abstract class Unpacker<T> {

	private final byte[] buffer;
	private int offset;
	private final int length;

	public Unpacker(byte[] buffer, int offset, int length) {
		this.buffer = buffer;
		this.offset = offset;
		this.length = length;
	}

	public final T unpackList() throws AerospikeException {
		if (length <= 0) {
			return getList(new ArrayList<T>(0));
		}

		try {
			int type = buffer[offset++] & 0xff;
			int count;

			if ((type & 0xf0) == 0x90) {
				count = type & 0x0f;
			}
			else if (type == 0xdc) {
				count = Buffer.bytesToShort(buffer, offset);
				offset += 2;
			}
			else if (type == 0xdd) {
				count = Buffer.bytesToInt(buffer, offset);
				offset += 4;
			}
			else {
				return getList(new ArrayList<T>(0));
			}
			return unpackList(count);
		}
		catch (Exception e) {
    		throw new AerospikeException.Serialize(e);
		}
	}

	private T unpackList(int count) throws IOException, ClassNotFoundException {
		if (count <= 0) {
			return getList(new ArrayList<T>(0));
		}

		// Extract first object.
		int mark = offset;
		int size = count;
		T val = unpackObject();

		if (val == null) {
			// Determine if null value is because of an extension type.
			int type = buffer[mark] & 0xff;

			if (type != 0xc0) {  // not nil type
				// Ignore extension type.
				size--;
			}
		}

		ArrayList<T> out = new ArrayList<T>(size);

		if (size == count) {
			out.add(val);
		}

		for (int i = 1; i < count; i++) {
			out.add(unpackObject());
		}
		return getList(out);
	}

	public final T unpackMap() throws AerospikeException {
		if (length <= 0) {
			return getMap(new HashMap<T,T>(0));
		}

		try {
			int type = buffer[offset++] & 0xff;
			int count;

			if ((type & 0xf0) == 0x80) {
				count = type & 0x0f;
			}
			else if (type == 0xde) {
				count = Buffer.bytesToShort(buffer, offset);
				offset += 2;
			}
			else if (type == 0xdf) {
				count = Buffer.bytesToInt(buffer, offset);
				offset += 4;
			}
			else {
				return getMap(new HashMap<T,T>(0));
			}
			return unpackMap(count);
		}
		catch (Exception e) {
    		throw new AerospikeException.Serialize(e);
		}
	}

	private T unpackMap(int count) throws IOException, ClassNotFoundException {
		if (count <= 0) {
			return getMap(new HashMap<T,T>(0));
		}

		// Peek at buffer to determine map type, but do not advance.
		int type = buffer[offset] & 0xff;

		// Check for extension that the server uses.
		if (type == 0xc7) {
			int extensionType = buffer[offset + 1] & 0xff;

			if (extensionType == 0) {
				int mapBits = buffer[offset + 2] & 0xff;

				// Extension is a map type.  Determine which one.
				if ((mapBits & (0x04 | 0x08)) != 0) {
					// Index/rank range result where order needs to be preserved.
					return unpackMapAsList(count);
				}
				else if ((mapBits & 0x01) != 0) {
					// Sorted map
					return unpackTreeMap(count);
				}
			}
		}
		return unpackHashMap(count);
	}

	private T unpackHashMap(int count) throws IOException, ClassNotFoundException {
		HashMap<T,T> map = new HashMap<T,T>(count);

		for (int i = 0; i < count; i++) {
			T key = unpackObject();
			T val = unpackObject();

			if (key != null) {
				map.put(key, val);
			}
		}
		return getMap(map);
	}

	@SuppressWarnings("unchecked")
	private T unpackTreeMap(int count) throws IOException, ClassNotFoundException {
		TreeMap<T,T> map = new TreeMap<T,T>();

		for (int i = 0; i < count; i++) {
			T key = unpackObject();
			T val = unpackObject();

			if (key != null) {
				if (key instanceof byte[]) {
					// TreeMap does not support byte[] keys,
					// so wrap byte[] in a ByteBuffer.
					key = (T)ByteBuffer.wrap((byte[])key);
				}
				map.put(key, val);
			}
		}
		return getMap(map);
	}

	@SuppressWarnings("unchecked")
	private T unpackMapAsList(int count) throws IOException, ClassNotFoundException {
		// Index/rank range result where order needs to be preserved.
		// Store in List<Entry<?,?> to preserve order.
		// The first entry is going to be null (ignored), so use "count - 1" size.
		List<Entry<T,T>> list = new ArrayList<Entry<T,T>>(count - 1);

		for (int i = 0; i < count; i++) {
			T key = unpackObject();
			T val = unpackObject();

			if (key != null) {
				list.add(new AbstractMap.SimpleEntry<T,T>(key, val));
			}
		}
		return getList((List<T>)list);
	}

	private T unpackBlob(int count) throws IOException, ClassNotFoundException {
		int type = buffer[offset++] & 0xff;
		count--;
		T val;

		switch (type) {
		case ParticleType.STRING:
			val = getString(Buffer.utf8ToString(buffer, offset, count));
			break;

		case ParticleType.JBLOB:
			ByteArrayInputStream bastream = new ByteArrayInputStream(buffer, offset, count);
			ObjectInputStream oistream = new ObjectInputStream(bastream);
			val = getJavaBlob(oistream.readObject());
			break;

		case ParticleType.GEOJSON:
			val = getGeoJSON(Buffer.utf8ToString(buffer, offset, count));
			break;

		default:
			val = getBlob(Arrays.copyOfRange(buffer, offset, offset + count));
			break;
		}
		offset += count;
		return val;
	}

	public T unpackObject() throws IOException, ClassNotFoundException {
		int type = buffer[offset++] & 0xff;

		switch (type) {
			case 0xc0: { // nil
				return null;
			}

			case 0xc3: { // boolean true
				return getBoolean(true);
			}

			case 0xc2: { // boolean false
				return getBoolean(false);
			}

			case 0xca: { // float
				float val = Float.intBitsToFloat(Buffer.bytesToInt(buffer, offset));
				offset += 4;
				return getDouble(val);
			}

			case 0xcb: { // double
				double val = Double.longBitsToDouble(Buffer.bytesToLong(buffer, offset));
				offset += 8;
				return getDouble(val);
			}

			case 0xd0: { // signed 8 bit integer
				return getLong(buffer[offset++]);
			}

			case 0xcc: { // unsigned 8 bit integer
				return getLong(buffer[offset++] & 0xff);
			}

			case 0xd1: { // signed 16 bit integer
				short val = Buffer.bigSigned16ToShort(buffer, offset);
				offset += 2;
				return getLong(val);
			}

			case 0xcd: { // unsigned 16 bit integer
				int val = Buffer.bytesToShort(buffer, offset);
				offset += 2;
				return getLong(val);
			}

			case 0xd2: { // signed 32 bit integer
				int val = Buffer.bytesToInt(buffer, offset);
				offset += 4;
				return getLong(val);
			}

			case 0xce: { // unsigned 32 bit integer
				long val = Buffer.bigUnsigned32ToLong(buffer, offset);
				offset += 4;
				return getLong(val);
			}

			case 0xd3: { // signed 64 bit integer
				long val = Buffer.bytesToLong(buffer, offset);
				offset += 8;
				return getLong(val);
			}

			case 0xcf: { // unsigned 64 bit integer
				// Java is constrained to signed longs, so that is the best we can do here.
				long val = Buffer.bytesToLong(buffer, offset);
				offset += 8;
				return getLong(val);
			}

			case 0xc4:
			case 0xd9: { // string/raw bytes with 8 bit header
				int count = buffer[offset++] & 0xff;
				return (T)unpackBlob(count);
			}

			case 0xc5:
			case 0xda: { // string/raw bytes with 16 bit header
				int count = Buffer.bytesToShort(buffer, offset);
				offset += 2;
				return (T)unpackBlob(count);
			}

			case 0xc6:
			case 0xdb: { // string/raw bytes with 32 bit header
				// Java array length is restricted to positive int values (0 - Integer.MAX_VALUE).
				int count = Buffer.bytesToInt(buffer, offset);
				offset += 4;
				return (T)unpackBlob(count);
			}

			case 0xdc: { // list with 16 bit header
				int count = Buffer.bytesToShort(buffer, offset);
				offset += 2;
				return unpackList(count);
			}

			case 0xdd: { // list with 32 bit header
				// Java array length is restricted to positive int values (0 - Integer.MAX_VALUE).
				int count = Buffer.bytesToInt(buffer, offset);
				offset += 4;
				return unpackList(count);
			}

			case 0xde: { // map with 16 bit header
				int count = Buffer.bytesToShort(buffer, offset);
				offset += 2;
				return unpackMap(count);
			}

			case 0xdf: { // map with 32 bit header
				// Java array length is restricted to positive int values (0 - Integer.MAX_VALUE).
				int count = Buffer.bytesToInt(buffer, offset);
				offset += 4;
				return unpackMap(count);
			}

			case 0xd4: { // Skip over type extension with 1 byte
				offset += 1 + 1;
				return null;
			}

			case 0xd5: { // Skip over type extension with 2 bytes
				offset += 1 + 2;
				return null;
			}

			case 0xd6: { // Skip over type extension with 4 bytes
				offset += 1 + 4;
				return null;
			}

			case 0xd7: { // Skip over type extension with 8 bytes
				offset += 1 + 8;
				return null;
			}

			case 0xd8: { // Skip over type extension with 16 bytes
				offset += 1 + 16;
				return null;
			}

			case 0xc7: { // Skip over type extension with 8 bit header and bytes
				int count = buffer[offset] & 0xff;
				offset += count + 1 + 1;
				return null;
			}

			case 0xc8: { // Skip over type extension with 16 bit header and bytes
				int count = Buffer.bytesToShort(buffer, offset);
				offset += count + 1 + 2;
				return null;
			}

			case 0xc9: { // Skip over type extension with 32 bit header and bytes
				int count = Buffer.bytesToInt(buffer, offset);
				offset += count + 1 + 4;
				return null;
			}

			default: {
				if ((type & 0xe0) == 0xa0) { // raw bytes with 8 bit combined header
					return unpackBlob(type & 0x1f);
				}

				if ((type & 0xf0) == 0x80) { // map with 8 bit combined header
					return unpackMap(type & 0x0f);
				}

				if ((type & 0xf0) == 0x90) { // list with 8 bit combined header
					return unpackList(type & 0x0f);
				}

				if (type < 0x80) { // 8 bit combined unsigned integer
		        	return getLong(type);
				}

				if (type >= 0xe0) { // 8 bit combined signed integer
		        	return getLong(type - 0xe0 - 32);
				}
				throw new IOException("Unknown unpack type: " + type);
			}
		}
	}

	protected abstract T getMap(Map<T,T> value);
	protected abstract T getList(List<T> value);
	protected abstract T getJavaBlob(Object value);
	protected abstract T getBlob(byte[] value);
	protected abstract T getString(String value);
	protected abstract T getLong(long value);
	protected abstract T getDouble(double value);
	protected abstract T getBoolean(boolean value);
	protected abstract T getGeoJSON(String value);

	public static Object unpackObjectList(byte[] buffer, int offset, int length) throws AerospikeException {
		ObjectUnpacker unpacker = new ObjectUnpacker(buffer, offset, length);
		return unpacker.unpackList();
	}

	public static Object unpackObjectMap(byte[] buffer, int offset, int length) throws AerospikeException {
		ObjectUnpacker unpacker = new ObjectUnpacker(buffer, offset, length);
		return unpacker.unpackMap();
	}

	public static Object unpackObject(byte[] buffer, int offset, int length) throws AerospikeException {
		try {
			if (length <= 0) {
				return null;
			}
			ObjectUnpacker unpacker = new ObjectUnpacker(buffer, offset, length);
			return unpacker.unpackObject();
		}
		catch (Exception e) {
    		throw new AerospikeException.Serialize(e);
		}
	}

	public static final class ObjectUnpacker extends Unpacker<Object> {

		public ObjectUnpacker(byte[] buffer, int offset, int length) {
			super(buffer, offset, length);
		}

		@Override
		protected Object getMap(Map<Object,Object> value) {
			return value;
		}

		@Override
		protected Object getList(List<Object> value) {
			return value;
		}

		@Override
		protected Object getJavaBlob(Object value) {
			return value;
		}

		@Override
		protected Object getBlob(byte[] value) {
			return value;
		}

		@Override
		protected Object getString(String value) {
			return value;
		}

		@Override
		protected Object getLong(long value) {
			return value;
		}

		@Override
		protected Object getDouble(double value) {
			return value;
		}

		@Override
		protected Object getBoolean(boolean value) {
			return value;
		}

		@Override
		protected Object getGeoJSON(String value) {
			return Value.getAsGeoJSON(value);
		}
	}
}

Output:
【漏洞类型】反序列化漏洞
【严重性】High
【漏洞摘要】反序列化漏洞是指在应用程序中对不受信任的数据进行反序列化操作，可能导致远程代码执行（RCE）或拒绝服务（DoS）攻击。在原始代码中，`Buffer.bytesToObject`、`Packer.packBlob`和`Value.BlobValue.estimateSize`方法使用了Java的`ObjectInputStream`和`ObjectOutputStream`进行序列化和反序列化操作，这使得应用程序容易受到反序列化漏洞的攻击。
【关键代码模式】
- `Buffer.bytesToObject`方法：使用`ObjectInputStream`读取对象。
- `Packer.packBlob`方法：使用`ObjectOutputStream`写入对象。
- `Value.BlobValue.estimateSize`方法：使用`ObjectOutputStream`写入对象。
【修复方法说明】修复方法通过移除`ObjectInputStream`和`ObjectOutputStream`的使用，禁用了Java的运行时序列化和反序列化功能，从而解决问题。最佳实践是避免使用Java的运行时序列化，而改用更安全的序列化格式，如Aerospike的原生类型、protobuf、msgpack、json或xml。