diff options
author | Thomas Watson | 2021-05-26 14:57:16 +0000 |
---|---|---|
committer | Thomas Watson | 2021-06-16 15:25:47 +0000 |
commit | 77fda35b312c6da5c6ce1530829804f7512bae7c (patch) | |
tree | c5aa135fc3c8d0a0e142f2654f60b555ba1c1328 | |
parent | 19766e7dd0c3deed8da9280d3815dfa53310a150 (diff) | |
download | rt.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.java | 41 |
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; |