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