Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2021-05-26 14:57:16 +0000
committerThomas Watson2021-06-16 15:25:47 +0000
commit77fda35b312c6da5c6ce1530829804f7512bae7c (patch)
treec5aa135fc3c8d0a0e142f2654f60b555ba1c1328
parent19766e7dd0c3deed8da9280d3815dfa53310a150 (diff)
downloadrt.equinox.framework-77fda35b312c6da5c6ce1530829804f7512bae7c.tar.gz
rt.equinox.framework-77fda35b312c6da5c6ce1530829804f7512bae7c.tar.xz
rt.equinox.framework-77fda35b312c6da5c6ce1530829804f7512bae7c.zip
Bug 574236 - Use Lookup.defineHiddenClass to avoid illegal accessI20210616-1800
Unsafe.defineAnonymousClass got removed in Java 17 and Lookup.defineHiddenClass got added in Java 16. Change-Id: Iac75637458ba46ceb04a1cf7a5b61993bc981ca5 Signed-off-by: Thomas Watson <tjwatson@us.ibm.com> Reviewed-on: https://git.eclipse.org/r/c/equinox/rt.equinox.framework/+/182046 Tested-by: Equinox Bot <equinox-bot@eclipse.org>
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java41
1 files changed, 34 insertions, 7 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java
index 0470a7af8..a11552620 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java
@@ -11,7 +11,10 @@
*******************************************************************************/
package org.eclipse.osgi.internal.url;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
@@ -62,16 +65,40 @@ public abstract class MultiplexingFactory {
theUnsafe.setAccessible(true);
Object unsafe = theUnsafe.get(null);
- // using defineAnonymousClass here because it seems more simple to get what we need
- Method defineAnonymousClass = unsafeClass.getMethod("defineAnonymousClass", Class.class, byte[].class, Object[].class); //$NON-NLS-1$
// The SetAccessible bytes stored in a resource to avoid real loading of it (see SetAccessible.java.src for source).
- String tResource = "SetAccessible.bytes"; //$NON-NLS-1$
+ byte[] bytes = StorageUtil.getBytes(MultiplexingFactory.class.getResource("SetAccessible.bytes").openStream(), -1, 4000); //$NON-NLS-1$
+
+ Class<Collection<AccessibleObject>> collectionClass = null;
+ // using defineAnonymousClass here because it seems more simple to get what we need
+ try {
+ Method defineAnonymousClass = unsafeClass.getMethod("defineAnonymousClass", Class.class, byte[].class, //$NON-NLS-1$
+ Object[].class);
+ @SuppressWarnings("unchecked")
+ Class<Collection<AccessibleObject>> unchecked = (Class<Collection<AccessibleObject>>) defineAnonymousClass
+ .invoke(unsafe, URL.class, bytes, (Object[]) null);
+ collectionClass = unchecked;
+
+ } catch (NoSuchMethodException e) {
+ long offset = (long) unsafeClass.getMethod("staticFieldOffset", Field.class).invoke(unsafe, //$NON-NLS-1$
+ MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP")); //$NON-NLS-1$
+ MethodHandles.Lookup lookup = (MethodHandles.Lookup) unsafeClass
+ .getMethod("getObject", Object.class, long.class) //$NON-NLS-1$
+ .invoke(unsafe, MethodHandles.Lookup.class, offset);
+ lookup = lookup.in(URL.class);
+ Class<?> classOption = Class.forName("java.lang.invoke.MethodHandles$Lookup$ClassOption"); //$NON-NLS-1$
+ Object classOptions = Array.newInstance(classOption, 0);
+ Method defineHiddenClass = Lookup.class.getMethod("defineHiddenClass", byte[].class, boolean.class, //$NON-NLS-1$
+ classOptions.getClass());
+ lookup = (Lookup) defineHiddenClass.invoke(lookup, bytes, Boolean.FALSE, classOptions);
+ @SuppressWarnings("unchecked")
+ Class<Collection<AccessibleObject>> unchecked = (Class<Collection<AccessibleObject>>) lookup
+ .lookupClass();
+ collectionClass = unchecked;
+ }
- byte[] bytes = StorageUtil.getBytes(MultiplexingFactory.class.getResource(tResource).openStream(), -1, 4000);
- @SuppressWarnings("unchecked")
- Class<Collection<AccessibleObject>> clazz = (Class<Collection<AccessibleObject>>) defineAnonymousClass.invoke(unsafe, URL.class, bytes, (Object[]) null);
- result = clazz.getConstructor().newInstance();
+ result = collectionClass.getConstructor().newInstance();
} catch (Throwable t) {
+ t.printStackTrace();
// ingore as if there is no Unsafe
}
setAccessible = result;

Back to the top