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:
committed by
Oliver Gierke
parent
cabfa287cb
commit
9038e6894c
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user