HHH-16400 Avoid reflection for calls to StackWalker
This commit is contained in:
parent
31f1a30c7d
commit
e54b4dee54
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.bytecode.internal.bytebuddy;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
@ -99,37 +98,11 @@ public class HibernateMethodLookupDispatcher {
|
|||
PrivilegedAction<PrivilegedAction<Class<?>[]>> initializeGetCallerStackAction = new PrivilegedAction<PrivilegedAction<Class<?>[]>>() {
|
||||
@Override
|
||||
public PrivilegedAction<Class<?>[]> run() {
|
||||
Class<?> stackWalkerClass = null;
|
||||
try {
|
||||
// JDK 9 introduced the StackWalker
|
||||
stackWalkerClass = Class.forName( "java.lang.StackWalker" );
|
||||
return new StackWalkerGetCallerStackAction(StackWalker.getInstance( StackWalker.Option.RETAIN_CLASS_REFERENCE) );
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
// ignore, we will deal with that later.
|
||||
}
|
||||
|
||||
if ( stackWalkerClass != null ) {
|
||||
// We can use a stack walker
|
||||
try {
|
||||
Class<?> optionClass = Class.forName( "java.lang.StackWalker$Option" );
|
||||
Object stackWalker = stackWalkerClass.getMethod( "getInstance", optionClass )
|
||||
// The first one is RETAIN_CLASS_REFERENCE
|
||||
.invoke( null, optionClass.getEnumConstants()[0] );
|
||||
|
||||
Method stackWalkerWalkMethod = stackWalkerClass.getMethod( "walk", Function.class );
|
||||
Method stackFrameGetDeclaringClass = Class.forName( "java.lang.StackWalker$StackFrame" )
|
||||
.getMethod( "getDeclaringClass" );
|
||||
return new StackWalkerGetCallerStackAction(
|
||||
stackWalker, stackWalkerWalkMethod,stackFrameGetDeclaringClass
|
||||
);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new HibernateException( "Unable to initialize the stack walker", e );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We cannot use a stack walker, default to fetching the security manager class context
|
||||
return new SecurityManagerClassContextGetCallerStackAction();
|
||||
catch (Throwable e) {
|
||||
throw new HibernateException( "Unable to initialize the stack walker", e );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -165,59 +138,42 @@ public class HibernateMethodLookupDispatcher {
|
|||
throw new SecurityException( "Unable to determine the caller class" );
|
||||
}
|
||||
|
||||
/**
|
||||
* A privileged action that retrieves the caller stack from the security manager class context.
|
||||
*/
|
||||
private static class SecurityManagerClassContextGetCallerStackAction extends SecurityManager
|
||||
implements PrivilegedAction<Class<?>[]> {
|
||||
@Override
|
||||
public Class<?>[] run() {
|
||||
return getClassContext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A privileged action that retrieves the caller stack using a stack walker.
|
||||
*/
|
||||
private static class StackWalkerGetCallerStackAction implements PrivilegedAction<Class<?>[]> {
|
||||
private final Object stackWalker;
|
||||
private final Method stackWalkerWalkMethod;
|
||||
private final Method stackFrameGetDeclaringClass;
|
||||
private final StackWalker stackWalker;
|
||||
|
||||
StackWalkerGetCallerStackAction(Object stackWalker, Method stackWalkerWalkMethod,
|
||||
Method stackFrameGetDeclaringClass) {
|
||||
StackWalkerGetCallerStackAction(StackWalker stackWalker) {
|
||||
this.stackWalker = stackWalker;
|
||||
this.stackWalkerWalkMethod = stackWalkerWalkMethod;
|
||||
this.stackFrameGetDeclaringClass = stackFrameGetDeclaringClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] run() {
|
||||
try {
|
||||
return (Class<?>[]) stackWalkerWalkMethod.invoke( stackWalker, stackFrameExtractFunction );
|
||||
return stackWalker.walk( stackFrameExtractFunction );
|
||||
}
|
||||
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
catch (RuntimeException e) {
|
||||
throw new SecurityException( "Unable to determine the caller class", e );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private final Function<Stream, Object> stackFrameExtractFunction = new Function<Stream, Object>() {
|
||||
private final Function<Stream<StackWalker.StackFrame>, Class<?>[]> stackFrameExtractFunction = new Function<>() {
|
||||
@Override
|
||||
public Object apply(Stream stream) {
|
||||
public Class<?>[] apply(Stream<StackWalker.StackFrame> stream) {
|
||||
return stream.map( stackFrameGetDeclaringClassFunction )
|
||||
.limit( MAX_STACK_FRAMES )
|
||||
.toArray( Class<?>[]::new );
|
||||
}
|
||||
};
|
||||
|
||||
private final Function<Object, Class<?>> stackFrameGetDeclaringClassFunction = new Function<Object, Class<?>>() {
|
||||
private final Function<StackWalker.StackFrame, Class<?>> stackFrameGetDeclaringClassFunction = new Function<>() {
|
||||
@Override
|
||||
public Class<?> apply(Object t) {
|
||||
public Class<?> apply(StackWalker.StackFrame frame) {
|
||||
try {
|
||||
return (Class<?>) stackFrameGetDeclaringClass.invoke( t );
|
||||
return frame.getDeclaringClass();
|
||||
}
|
||||
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
catch (RuntimeException e) {
|
||||
throw new HibernateException( "Unable to get stack frame declaring class", e );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue