Skip to content

Commit

Permalink
Performance improvements for Kryo.isClosure() (#956)
Browse files Browse the repository at this point in the history
  • Loading branch information
theigl committed Apr 19, 2023
1 parent 379b022 commit 8742e6e
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/com/esotericsoftware/kryo/Kryo.java
Expand Up @@ -1257,10 +1257,10 @@ public boolean isFinal (Class type) {
* the class {@link Registration}.
* <p>
* This can be overridden to support alternative closure implementations. The default implementation returns true if the
* specified type's name contains '/' (to detect a Java 8+ closure). */
* specified type is synthetic and the type's simple name contains '/' (to detect a Java 8+ closure). */
public boolean isClosure (Class type) {
if (type == null) throw new IllegalArgumentException("type cannot be null.");
return type.getName().indexOf('/') >= 0;
return type.isSynthetic() && type.getSimpleName().indexOf('/') >= 0;
}

/** Returns true if the specified type is a proxy. When true, Kryo uses {@link InvocationHandler} instead of the specified type
Expand Down
Expand Up @@ -26,6 +26,7 @@
import com.esotericsoftware.kryo.io.Output;

import java.util.concurrent.Callable;
import java.util.function.Supplier;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -59,7 +60,40 @@ void testSerializableClosure () {
}

@Test
void testCopyClosure() {
void testCapturingClosure () {
final int number = 72363;
Supplier<Integer> closure1 = (Supplier<Integer> & java.io.Serializable) () -> number;

// The length cannot be checked reliable, as it can vary based on the JVM.
roundTrip(Integer.MIN_VALUE, closure1);

Output output = new Output(1024, -1);
kryo.writeObject(output, closure1);

Input input = new Input(output.getBuffer(), 0, output.position());
Supplier<Integer> closure2 = (Supplier<Integer>)kryo.readObject(input, ClosureSerializer.Closure.class);

doAssertEquals(closure1, closure2);
}

@Test
void testMethodReference () {
Supplier<Integer> closure1 = (Supplier<Integer> & java.io.Serializable)NumberFactory::getNumber;

// The length cannot be checked reliable, as it can vary based on the JVM.
roundTrip(Integer.MIN_VALUE, closure1);

Output output = new Output(1024, -1);
kryo.writeObject(output, closure1);

Input input = new Input(output.getBuffer(), 0, output.position());
Supplier<Integer> closure2 = (Supplier<Integer>)kryo.readObject(input, ClosureSerializer.Closure.class);

doAssertEquals(closure1, closure2);
}

@Test
void testCopyClosure () {
Callable<Integer> closure1 = (Callable<Integer> & java.io.Serializable)( () -> 72363);

final Callable<Integer> closure2 = kryo.copy(closure1);
Expand All @@ -69,9 +103,20 @@ void testCopyClosure() {

protected void doAssertEquals (Object object1, Object object2) {
try {
assertEquals(((Callable)object1).call(), ((Callable)object2).call());
if (object1 instanceof Callable) {
assertEquals(((Callable)object1).call(), ((Callable)object2).call());
}
if (object1 instanceof Supplier) {
assertEquals(((Supplier)object1).get(), ((Supplier)object2).get());
}
} catch (Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}

static class NumberFactory {
private static int getNumber () {
return 72363;
}
}
}

0 comments on commit 8742e6e

Please sign in to comment.