package org.infinispan.marshaller.kryo; import java.util.ArrayList; import java.util.List; import java.util.ServiceLoader; import org.infinispan.commons.io.ByteBuffer; import org.infinispan.commons.io.ByteBufferImpl; import org.infinispan.commons.io.ExposedByteArrayOutputStream; import org.infinispan.commons.marshall.AbstractMarshaller; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.pool.KryoFactory; import com.esotericsoftware.kryo.pool.KryoPool; /** * @author Ryan Emerson * @since 9.0 */ public class KryoMarshaller extends AbstractMarshaller { private static final List<SerializerRegistryService> serializerServices = new ArrayList<>(); static { ServiceLoader.load(SerializerRegistryService.class, KryoMarshaller.class.getClassLoader()) .forEach(serializerServices::add); } private final KryoPool pool; public KryoMarshaller() { KryoFactory factory = () -> { Kryo kryo = new Kryo(); serializerServices.forEach(service -> service.register(kryo)); return kryo; }; this.pool = new KryoPool.Builder(factory).softReferences().build(); } @Override public Object objectFromByteBuffer(byte[] bytes, int offset, int length) { return pool.run((kryo) -> { try (Input input = new Input(bytes, offset, length)) { return kryo.readClassAndObject(input); } }); } @Override protected ByteBuffer objectToBuffer(Object obj, int estimatedSize) { return pool.run((kryo) -> { try (Output output = new Output(new ExposedByteArrayOutputStream(estimatedSize), estimatedSize)) { kryo.writeClassAndObject(output, obj); byte[] bytes = output.toBytes(); return new ByteBufferImpl(bytes, 0, bytes.length); } }); } @Override public boolean isMarshallable(Object obj) throws Exception { try { objectToBuffer(obj); return true; } catch (Throwable t) { return false; } } }