This is an automated email from the ASF dual-hosted git repository. struberg pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openwebbeans.git
The following commit(s) were added to refs/heads/master by this push: new 6ae21f8 OWB-1375 cache hit and miss 6ae21f8 is described below commit 6ae21f87d54f47780ef76124ddcc89fa255e4370 Author: Mark Struberg <strub...@apache.org> AuthorDate: Mon Mar 15 19:04:05 2021 +0100 OWB-1375 cache hit and miss We do not need to try our different classdefine strategies every time. Either they work everytime or not at all. So we can cache those. For Java8 we an even cache away the reflect Method per ClassLoader. --- .../java/org/apache/webbeans/proxy/Unsafe.java | 71 +++++++++++++++------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java b/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java index 850b523..d85dbd5 100644 --- a/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java +++ b/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java @@ -26,6 +26,8 @@ import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.ProtectionDomain; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -47,6 +49,10 @@ public class Unsafe private Method unsafeAllocateInstance; private final AtomicReference<Method> unsafeDefineClass = new AtomicReference<>(); + // defineClass method on ClassLoader + private Boolean useDefineClassMethod = null; + private final Map<ClassLoader, Method> defineClassMethodsByClassLoader = new HashMap<>(); + // java 16 private volatile Method privateLookup; private Method defineClass; @@ -142,32 +148,53 @@ public class Unsafe Class<?> parent) throws ProxyGenerationException { - Class<?> clazz = classLoader.getClass(); - Method defineClassMethod = null; - do + + if (useDefineClassMethod == null || Boolean.TRUE.equals(useDefineClassMethod)) { - try - { - defineClassMethod = clazz.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); - } - catch (NoSuchMethodException e) + defineClassMethod = defineClassMethodsByClassLoader.get(classLoader); + + if (defineClassMethod == null) { - // do nothing, we need to search the superclass - } + Class<?> clClazz = classLoader.getClass(); - clazz = clazz.getSuperclass(); - } while (defineClassMethod == null && clazz != Object.class); + do + { + try + { + defineClassMethod = clClazz.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); + } + catch (NoSuchMethodException e) + { + // do nothing, we need to search the superclass + } - if (defineClassMethod != null && !defineClassMethod.isAccessible()) - { - try - { - defineClassMethod.setAccessible(true); - } - catch (RuntimeException re) // likely j9, let's use unsafe - { - defineClassMethod = null; + clClazz = clClazz.getSuperclass(); + } while (defineClassMethod == null && clClazz != Object.class); + + if (defineClassMethod == null) + { + // This ClassLoader does not have any accessible defineClass method + useDefineClassMethod = Boolean.FALSE; + } + else if (!defineClassMethod.isAccessible()) + { + try + { + defineClassMethod.setAccessible(true); + defineClassMethodsByClassLoader.put(classLoader, defineClassMethod); + } + catch (RuntimeException re) + { + // likely j9 or not accessible via security, let's use unsafe + defineClassMethod = null; + useDefineClassMethod = Boolean.FALSE; + } + } + else + { + defineClassMethodsByClassLoader.put(classLoader, defineClassMethod); + } } } @@ -178,10 +205,10 @@ public class Unsafe if (defineClassMethod != null) { definedClass = (Class<T>) defineClassMethod.invoke(classLoader, proxyName, proxyBytes, 0, proxyBytes.length); + useDefineClassMethod = Boolean.TRUE; } else { - definedClass = (Class<T>) unsafeDefineClass().invoke(internalUnsafe, proxyName, proxyBytes, 0, proxyBytes.length, classLoader, null); }