You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by jl...@apache.org on 2021/10/07 07:03:33 UTC

[openwebbeans] branch master updated: Better handling with MethodHandle for Java 11+

This is an automated email from the ASF dual-hosted git repository.

jlmonteiro 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 3fcc6a7  Better handling with MethodHandle for Java 11+
3fcc6a7 is described below

commit 3fcc6a70fecac9f21c8476693aaeedda4e4e0b66
Author: Jean-Louis Monteiro <jl...@tomitribe.com>
AuthorDate: Thu Oct 7 09:03:25 2021 +0200

    Better handling with MethodHandle for Java 11+
---
 .../java/org/apache/webbeans/proxy/Unsafe.java     | 92 ++++++++++++++--------
 1 file changed, 61 insertions(+), 31 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 68f0433..239138d 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
@@ -70,7 +70,7 @@ public class Unsafe
             catch (Exception e)
             {
                 WebBeansLoggerFacade.getLogger(Unsafe.class)
-                        .info("Cannot get sun.misc.Unsafe - will use newInstance() instead!");
+                      .info("Cannot get sun.misc.Unsafe - will use newInstance() instead!");
                 return null;
             }
         });
@@ -81,8 +81,7 @@ public class Unsafe
                 theInternalUnsafe.setAccessible(true);
                 return theInternalUnsafe.get(null);
             }
-            catch (final Exception notJ11OrMore)
-            {
+            catch (final Exception notJ11OrMore) {
                 return unsafe;
             }
         });
@@ -102,42 +101,73 @@ public class Unsafe
                 }
             });
 
-            try // some j>8, since we have unsafe let's use it
-            {
+            try {
                 final Class<?> rootLoaderClass = Class.forName("java.lang.ClassLoader");
-                final Method objectFieldOffset = unsafe.getClass().getDeclaredMethod("objectFieldOffset", Field.class);
-                final Method putBoolean = unsafe.getClass().getDeclaredMethod("putBoolean", Object.class, long.class, boolean.class);
-                objectFieldOffset.setAccessible(true);
-                final long accOffset = Long.class.cast(objectFieldOffset.invoke(unsafe, AccessibleObject.class.getDeclaredField("override")));
-                putBoolean.invoke(unsafe, rootLoaderClass.getDeclaredMethod("defineClass",
-                        new Class[]{String.class, byte[].class, int.class, int.class}),
-                        accOffset, true);
-                putBoolean.invoke(unsafe, rootLoaderClass
-                                .getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class,
-                                        int.class, int.class, ProtectionDomain.class}),
-                        accOffset, true);
+                try {
+                    final Method getModule = Class.class.getMethod("getModule");
+                    final Object module = getModule.invoke(rootLoaderClass);
+                    if (module != null)
+                    {
+                        final Method isOpen = module.getClass().getMethod("isOpen", String.class);
+                        if (Boolean.class.cast(isOpen.invoke(module, "sun.misc")))
+                        {
+                            oldStyleSetAccessibleDefineClass(rootLoaderClass);
+                        }
+                        else
+                        {
+                            hackSetDefineClassAccessible();
+                        }
+                    } else
+                    { // very unlikely since we should fall into unamed module
+                        hackSetDefineClassAccessible();
+                    }
+                }
+                catch (final NoSuchMethodException nsme)
+                { // pre java 9
+                    oldStyleSetAccessibleDefineClass(rootLoaderClass);
+                }
             }
             catch (final Exception e)
             {
-                try
-                {
-                    final Class<?> rootLoaderClass = Class.forName("java.lang.ClassLoader");
-                    rootLoaderClass.getDeclaredMethod(
-                        "defineClass", new Class[] { String.class, byte[].class, int.class, int.class })
-                        .setAccessible(true);
-                    rootLoaderClass.getDeclaredMethod(
-                        "defineClass", new Class[] {
-                                String.class, byte[].class, int.class, int.class, ProtectionDomain.class })
-                        .setAccessible(true); // this produces warning from 11+ and fails on 17+
-                }
-                catch (final Exception ex)
-                {
-                    // no-op
-                }
+                hackSetDefineClassAccessible();
             }
         }
     }
 
+    private void oldStyleSetAccessibleDefineClass(final Class<?> rootLoaderClass) throws NoSuchMethodException
+    {
+        rootLoaderClass.getDeclaredMethod(
+            "defineClass", new Class[]{String.class, byte[].class, int.class, int.class})
+                       .setAccessible(true);
+        rootLoaderClass.getDeclaredMethod(
+            "defineClass", new Class[]{
+                String.class, byte[].class, int.class, int.class, ProtectionDomain.class})
+                       .setAccessible(true);
+    }
+
+    private void hackSetDefineClassAccessible()
+    {
+        try
+        {
+            final Class<?> rootLoaderClass = Class.forName("java.lang.ClassLoader");
+            final Method objectFieldOffset = unsafe.getClass().getDeclaredMethod("objectFieldOffset", Field.class);
+            final Method putBoolean = unsafe.getClass().getDeclaredMethod("putBoolean", Object.class, long.class, boolean.class);
+            objectFieldOffset.setAccessible(true);
+            final long accOffset = Long.class.cast(objectFieldOffset.invoke(unsafe, AccessibleObject.class.getDeclaredField("override")));
+            putBoolean.invoke(unsafe, rootLoaderClass.getDeclaredMethod("defineClass",
+                                                                        new Class[]{String.class, byte[].class, int.class, int.class}),
+                              accOffset, true);
+            putBoolean.invoke(unsafe, rootLoaderClass
+                                  .getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class,
+                                                                                int.class, int.class, ProtectionDomain.class}),
+                              accOffset, true);
+        }
+        catch (final Exception e)
+        {
+            // no-op
+        }
+    }
+
     /**
      * The 'defineClass' method on the ClassLoader is protected, thus we need to invoke it via reflection.
      * @return the Class which got loaded in the classloader