diff options
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java')
-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; |