HHH-16400 Avoid reflection for calls to StackWalker
This commit is contained in:
parent
6ddf354b98
commit
5f0b571df6
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.bytecode.internal.bytebuddy;
|
package org.hibernate.bytecode.internal.bytebuddy;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
@ -99,37 +98,11 @@ public class HibernateMethodLookupDispatcher {
|
||||||
PrivilegedAction<PrivilegedAction<Class<?>[]>> initializeGetCallerStackAction = new PrivilegedAction<PrivilegedAction<Class<?>[]>>() {
|
PrivilegedAction<PrivilegedAction<Class<?>[]>> initializeGetCallerStackAction = new PrivilegedAction<PrivilegedAction<Class<?>[]>>() {
|
||||||
@Override
|
@Override
|
||||||
public PrivilegedAction<Class<?>[]> run() {
|
public PrivilegedAction<Class<?>[]> run() {
|
||||||
Class<?> stackWalkerClass = null;
|
|
||||||
try {
|
try {
|
||||||
// JDK 9 introduced the StackWalker
|
return new StackWalkerGetCallerStackAction(StackWalker.getInstance( StackWalker.Option.RETAIN_CLASS_REFERENCE) );
|
||||||
stackWalkerClass = Class.forName( "java.lang.StackWalker" );
|
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException e) {
|
catch (Throwable e) {
|
||||||
// ignore, we will deal with that later.
|
throw new HibernateException( "Unable to initialize the stack walker", e );
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -165,59 +138,42 @@ public class HibernateMethodLookupDispatcher {
|
||||||
throw new SecurityException( "Unable to determine the caller class" );
|
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.
|
* A privileged action that retrieves the caller stack using a stack walker.
|
||||||
*/
|
*/
|
||||||
private static class StackWalkerGetCallerStackAction implements PrivilegedAction<Class<?>[]> {
|
private static class StackWalkerGetCallerStackAction implements PrivilegedAction<Class<?>[]> {
|
||||||
private final Object stackWalker;
|
private final StackWalker stackWalker;
|
||||||
private final Method stackWalkerWalkMethod;
|
|
||||||
private final Method stackFrameGetDeclaringClass;
|
|
||||||
|
|
||||||
StackWalkerGetCallerStackAction(Object stackWalker, Method stackWalkerWalkMethod,
|
StackWalkerGetCallerStackAction(StackWalker stackWalker) {
|
||||||
Method stackFrameGetDeclaringClass) {
|
|
||||||
this.stackWalker = stackWalker;
|
this.stackWalker = stackWalker;
|
||||||
this.stackWalkerWalkMethod = stackWalkerWalkMethod;
|
|
||||||
this.stackFrameGetDeclaringClass = stackFrameGetDeclaringClass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?>[] run() {
|
public Class<?>[] run() {
|
||||||
try {
|
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 );
|
throw new SecurityException( "Unable to determine the caller class", e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
private final Function<Stream<StackWalker.StackFrame>, Class<?>[]> stackFrameExtractFunction = new Function<>() {
|
||||||
private final Function<Stream, Object> stackFrameExtractFunction = new Function<Stream, Object>() {
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply(Stream stream) {
|
public Class<?>[] apply(Stream<StackWalker.StackFrame> stream) {
|
||||||
return stream.map( stackFrameGetDeclaringClassFunction )
|
return stream.map( stackFrameGetDeclaringClassFunction )
|
||||||
.limit( MAX_STACK_FRAMES )
|
.limit( MAX_STACK_FRAMES )
|
||||||
.toArray( Class<?>[]::new );
|
.toArray( Class<?>[]::new );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Function<Object, Class<?>> stackFrameGetDeclaringClassFunction = new Function<Object, Class<?>>() {
|
private final Function<StackWalker.StackFrame, Class<?>> stackFrameGetDeclaringClassFunction = new Function<>() {
|
||||||
@Override
|
@Override
|
||||||
public Class<?> apply(Object t) {
|
public Class<?> apply(StackWalker.StackFrame frame) {
|
||||||
try {
|
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 );
|
throw new HibernateException( "Unable to get stack frame declaring class", e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue