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 <[email protected]>
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);
}