DATACMNS-1074 - Cache MethodHandles of default methods after lookup.

We now cache method handles after lookup on a best-effort basis to reuse them and prevent subsequent lookups as a MethodHandle lookup is expensive, in particular the lookup uses exceptions as control flow [0] during speculative lookup [1].

[0] http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/5b86f66575b7/src/share/classes/java/lang/invoke/MemberName.java#l978
[1] http://mail.openjdk.java.net/pipermail/core-libs-dev/2016-August/042770.html

Original pull request: #221.
This commit is contained in:
Mark Paluch
2017-05-24 13:14:12 +02:00
committed by Oliver Gierke
parent cabfa287cb
commit 9038e6894c

View File

@@ -21,11 +21,14 @@ import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Optional;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType;
import org.springframework.util.ReflectionUtils;
/**
@@ -38,6 +41,7 @@ import org.springframework.util.ReflectionUtils;
public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor {
private final MethodHandleLookup methodHandleLookup = MethodHandleLookup.getMethodHandleLookup();
private final Map<Method, MethodHandle> methodHandleCache = new ConcurrentReferenceHashMap<>(10, ReferenceType.WEAK);
/*
* (non-Javadoc)
@@ -55,7 +59,20 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor
Object[] arguments = invocation.getArguments();
Object proxy = ((ProxyMethodInvocation) invocation).getProxy();
return methodHandleLookup.lookup(method).bindTo(proxy).invokeWithArguments(arguments);
return getMethodHandle(method).bindTo(proxy).invokeWithArguments(arguments);
}
private MethodHandle getMethodHandle(Method method) throws Exception {
MethodHandle handle = methodHandleCache.get(method);
if (handle == null) {
handle = methodHandleLookup.lookup(method);
methodHandleCache.put(method, handle);
}
return handle;
}
/**