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);
             }
 

Reply via email to