INT-3907: Downgrade to Kryo-2.22

JIRA: https://jira.spring.io/browse/INT-3907

The IO-1.1.x is based on the Kryo-2.22 and can't be upgraded to 3.0.
Therefore we should downgrade.

* Change `PojoCodec` to use `StdInstantiatorStrategy` directly, because the `DefaultInstantiatorStrategy` logic is as a core code of `Kryo`.
* Introduce `org.springframework.integration.codec.kryo.pool` package and copy/paste `com.esotericsoftware.kryo.pool` classes,
 since they have been introduced since Kryo-3.0.
* That copy/paste seemed to me the simplest fix, since the `KryoPool` logic is encapsulated in the `AbstractKryoCodec`
This commit is contained in:
Artem Bilan
2015-12-14 18:15:26 -05:00
committed by Gary Russell
parent 2dfdfee95e
commit a91518c97b
9 changed files with 451 additions and 8 deletions

View File

@@ -106,7 +106,7 @@ subprojects { subproject ->
jsonpathVersion = '0.9.1'
junitVersion = '4.11'
jythonVersion = '2.5.3'
kryoShadedVersion = '3.0.3'
kryoVersion = '2.22'
log4jVersion = '1.2.17'
mockitoVersion = '1.9.5'
mysqlVersion = '5.1.29'
@@ -268,7 +268,7 @@ project('spring-integration-core') {
compile("com.fasterxml.jackson.core:jackson-databind:$jackson2Version", optional)
compile("com.jayway.jsonpath:json-path:$jsonpathVersion", optional)
compile("io.fastjson:boon:$boonVersion", optional)
compile("com.esotericsoftware:kryo-shaded:$kryoShadedVersion", optional)
compile("com.esotericsoftware.kryo:kryo:$kryoVersion", optional)
testCompile ("org.aspectj:aspectjweaver:$aspectjVersion")
testCompile ("net.openhft:chronicle:$chronicleVersion")

View File

@@ -22,14 +22,14 @@ import java.io.InputStream;
import java.io.OutputStream;
import org.springframework.integration.codec.Codec;
import org.springframework.integration.codec.kryo.pool.KryoCallback;
import org.springframework.integration.codec.kryo.pool.KryoFactory;
import org.springframework.integration.codec.kryo.pool.KryoPool;
import org.springframework.util.Assert;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.pool.KryoCallback;
import com.esotericsoftware.kryo.pool.KryoFactory;
import com.esotericsoftware.kryo.pool.KryoPool;
/**
* Base class for {@link Codec}s using {@link Kryo}.

View File

@@ -19,13 +19,12 @@ package org.springframework.integration.codec.kryo;
import java.util.Collections;
import java.util.List;
import org.objenesis.strategy.StdInstantiatorStrategy;
import org.springframework.util.CollectionUtils;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.shaded.org.objenesis.strategy.StdInstantiatorStrategy;
/**
* Kryo Codec that can encode and decode arbitrary types. Classes and associated
@@ -99,7 +98,7 @@ public class PojoCodec extends AbstractKryoCodec {
@Override
protected void configureKryoInstance(Kryo kryo) {
kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
if (this.kryoRegistrar != null) {
this.kryoRegistrar.registerTypes(kryo);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2015 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.codec.kryo.pool;
import com.esotericsoftware.kryo.Kryo;
/**
* Callback to run with a provided kryo instance.
* <p>
* Copied from Kryo 3.0 to facilitate dropping back to 2.22 for Spring IO
* compatibility.
*
* @author Martin Grotzke
*
* @param <T> The type of the result of the interaction with kryo.
*/
public interface KryoCallback<T> {
T execute(Kryo kryo);
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2015 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.codec.kryo.pool;
import com.esotericsoftware.kryo.Kryo;
/**
* Factory to create new configured instances of {@link Kryo}.
* <p>
* Copied from Kryo 3.0 to facilitate dropping back to 2.22 for Spring IO
* compatibility.
*
* @author Martin Grotzke
*/
public interface KryoFactory {
Kryo create();
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright 2015 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.codec.kryo.pool;
import java.lang.ref.SoftReference;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import com.esotericsoftware.kryo.Kryo;
/**
* A simple pool interface for {@link Kryo} instances. Use the {@link KryoPool.Builder} to
* construct a pool instance.
* <p>
* Copied from Kryo 3.0 to facilitate dropping back to 2.22 for Spring IO
* compatibility.
* <p>
* Usage:
* <pre class="code">
* {@code
*
* KryoFactory factory = new KryoFactory() {
* public Kryo create () {
* Kryo kryo = new Kryo();
* // configure kryo instance, customize settings
* return kryo;
* }
* };
* // Simple pool, you might also activate SoftReferences to fight OOMEs.
* KryoPool pool = new KryoPool.Builder(factory).build();
* Kryo kryo = pool.borrow();
* // do s.th. with kryo here, and afterwards release it
* pool.release(kryo);
*
* // or use a callback to work with kryo (pool.run borrows+releases for you)
* String value = pool.run(new KryoCallback<String>() {
* public String execute(Kryo kryo) {
* return kryo.readObject(input, String.class);
* }
* });
*
* }
* </pre>
* @author Martin Grotzke
*/
public interface KryoPool {
/**
* Takes a {@link Kryo} instance from the pool or creates a new one
* (using the factory) if the pool is empty.
* @return the {@link Kryo} instance.
*/
Kryo borrow();
/**
* Returns the given {@link Kryo} instance to the pool.
* @param kryo the {@link Kryo} instance to release.
*/
void release(Kryo kryo);
/**
* Runs the provided {@link KryoCallback} with a {@link Kryo} instance
* from the pool (borrow/release around {@link KryoCallback#execute(Kryo)}).
* @param callback the {@link KryoCallback} to call.
* @param <T> The type of the result of the interaction with kryo.
* @return the result of the interaction with {@link Kryo}.
*/
<T> T run(KryoCallback<T> callback);
/**
* Builder for a {@link KryoPool} instance, constructs a {@link KryoPoolQueueImpl} instance.
*/
class Builder {
private final KryoFactory factory;
private Queue<Kryo> queue = new ConcurrentLinkedQueue<Kryo>();
private boolean softReferences;
public Builder(KryoFactory factory) {
if (factory == null) {
throw new IllegalArgumentException("factory must not be null");
}
this.factory = factory;
}
/**
* Use the given queue for pooling kryo instances (by default a {@link ConcurrentLinkedQueue}
* is used).
* @param queue the queue instance to use.
* @return the Builder instance.
*/
public Builder queue(Queue<Kryo> queue) {
if (queue == null) {
throw new IllegalArgumentException("queue must not be null");
}
this.queue = queue;
return this;
}
/**
* Use {@link SoftReference}s for pooled {@link Kryo} instances, so that
* instances may be garbage collected when there's memory demand (by default
* disabled).
* @return the Builder instance.
*/
public Builder softReferences() {
softReferences = true;
return this;
}
/**
* Build the pool.
* @return the KryoPool instance.
*/
public KryoPool build() {
Queue<Kryo> q = softReferences ? new SoftReferenceQueue(queue) : queue;
return new KryoPoolQueueImpl(factory, q);
}
@Override
public String toString() {
return getClass().getName() + "[queue.class=" + queue.getClass() +
", softReferences=" + softReferences + "]";
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2015 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.codec.kryo.pool;
import java.util.Queue;
import com.esotericsoftware.kryo.Kryo;
/**
* A simple {@link Queue} based {@link KryoPool} implementation, should be built
* using the KryoPool.Builder.
* <p>
* Copied from Kryo 3.0 to facilitate dropping back to 2.22 for Spring IO
* compatibility.
* @author Martin Grotzke
*/
class KryoPoolQueueImpl implements KryoPool {
private final Queue<Kryo> queue;
private final KryoFactory factory;
KryoPoolQueueImpl(KryoFactory factory, Queue<Kryo> queue) {
this.factory = factory;
this.queue = queue;
}
public int size() {
return queue.size();
}
@Override
public Kryo borrow() {
Kryo res;
if ((res = queue.poll()) != null) {
return res;
}
return factory.create();
}
@Override
public void release(Kryo kryo) {
queue.offer(kryo);
}
@Override
public <T> T run(KryoCallback<T> callback) {
Kryo kryo = borrow();
try {
return callback.execute(kryo);
}
finally {
release(kryo);
}
}
public void clear() {
queue.clear();
}
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright 2015 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.codec.kryo.pool;
import java.lang.ref.SoftReference;
import java.util.Collection;
import java.util.Iterator;
import java.util.Queue;
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.
* <p>
* Copied from Kryo 3.0 to facilitate dropping back to 2.22 for Spring IO
* compatibility.
* @author Martin Grotzke
*/
class SoftReferenceQueue implements Queue<Kryo> {
private final Queue<SoftReference<Kryo>> delegate;
@SuppressWarnings("unchecked")
public SoftReferenceQueue(Queue<?> delegate) {
this.delegate = (Queue<SoftReference<Kryo>>) delegate;
}
@Override
public Kryo poll() {
Kryo res;
SoftReference<Kryo> ref;
while ((ref = delegate.poll()) != null) {
if ((res = ref.get()) != null) {
return res;
}
}
return null;
}
@Override
public boolean offer(Kryo e) {
return delegate.offer(new SoftReference<Kryo>(e));
}
@Override
public boolean add(Kryo e) {
return delegate.add(new SoftReference<Kryo>(e));
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public boolean contains(Object o) {
return delegate.contains(o);
}
@Override
public void clear() {
delegate.clear();
}
@Override
public boolean equals(Object o) {
return delegate.equals(o);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public String toString() {
return getClass().getSimpleName() + super.toString();
}
@Override
public Iterator<Kryo> iterator() {
throw new UnsupportedOperationException();
}
@Override
public Kryo remove() {
throw new UnsupportedOperationException();
}
@Override
public Object[] toArray() {
throw new UnsupportedOperationException();
}
@Override
public Kryo element() {
throw new UnsupportedOperationException();
}
@Override
public Kryo peek() {
throw new UnsupportedOperationException();
}
@Override
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends Kryo> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,5 @@
/**
* The <a href="https://code.google.com/p/kryo/">Kryo Pool</a> classes.
* Copy/paste from Kryo 3.0
*/
package org.springframework.integration.codec.kryo.pool;