Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2019-11-14 17:01:29 +0000
committerThomas Watson2019-11-14 17:01:29 +0000
commita731195ec06070c34a03d7bfd15b51bfd1fd5283 (patch)
treecf2c8702d13f2bb5b81d274bb1bc9297f0c04f42
parentb11a6c0a6552bd7152e6b25bc0c3b6fe7b912635 (diff)
downloadrt.equinox.framework-a731195ec06070c34a03d7bfd15b51bfd1fd5283.tar.gz
rt.equinox.framework-a731195ec06070c34a03d7bfd15b51bfd1fd5283.tar.xz
rt.equinox.framework-a731195ec06070c34a03d7bfd15b51bfd1fd5283.zip
In Java 9 the application class loader changed from a URLClassLoader to an internal type jdk.internal.loader.ClassLoaders.AppClassLoader. The new AppClassLoader no longer has the addURL method that we used to add framework extension content to the class loader when the framework is loaded from the java class path. This fix uses the method appendToClassPathForInstrumentation(String) on the new AppClassLoader class. To do this extra work is needed to allow reflection on the AppClassLoader class. This is not ideal, but will allow the framework extensions to work when the framework is launched from the java application class path. Note that Eclipse launcher uses its own class loader which still has addURL method available. This new approach is only attempted if the class loader used to launch the framework does not have an available addURL method. Change-Id: I0a4195307db6fb87dbab08933584e1a798ccf34a Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java65
2 files changed, 45 insertions, 22 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 5d9ced4b3..ec38d9bed 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
@@ -49,7 +49,7 @@ public abstract class MultiplexingFactory {
* The setAccessible class will be defined in the java.base module which grants
* it the ability to call setAccessible(true) on other types from the java.base module
*/
- static final Collection<AccessibleObject> setAccessible;
+ public static final Collection<AccessibleObject> setAccessible;
static final Collection<ClassLoader> systemLoaders;
static {
Collection<AccessibleObject> result = null;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java
index 939e9548f..59f570185 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java
@@ -14,6 +14,7 @@
package org.eclipse.osgi.storage;
import java.io.File;
+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
@@ -36,6 +37,7 @@ import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.hookregistry.ActivatorHookFactory;
import org.eclipse.osgi.internal.hookregistry.HookRegistry;
import org.eclipse.osgi.internal.messages.Msg;
+import org.eclipse.osgi.internal.url.MultiplexingFactory;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
@@ -50,29 +52,40 @@ import org.osgi.resource.Capability;
public class FrameworkExtensionInstaller {
private static final ClassLoader CL = FrameworkExtensionInstaller.class.getClassLoader();
private static final Method ADD_FWK_URL_METHOD = findAddURLMethod(CL, "addURL"); //$NON-NLS-1$
+ private static final Method ADD_FWK_FILE_PATH_METHOD = ADD_FWK_URL_METHOD == null ? findAddFilePathMethod(CL, "appendToClassPathForInstrumentation") : null; //$NON-NLS-1$
private final ArrayMap<BundleActivator, Bundle> hookActivators = new ArrayMap<>(5);
private static Method findAddURLMethod(ClassLoader cl, String name) {
if (cl == null)
return null;
- return findMethod(cl.getClass(), name, new Class[] {URL.class});
+ return findMethod(cl.getClass(), name, new Class[] {URL.class}, null);
+ }
+
+ private static Method findAddFilePathMethod(ClassLoader cl, String name) {
+ if (cl == null)
+ return null;
+ return findMethod(cl.getClass(), name, new Class[] {String.class}, MultiplexingFactory.setAccessible);
}
// recursively searches a class and it's superclasses for a (potentially inaccessable) method
- private static Method findMethod(Class<?> clazz, String name, Class<?>[] args) {
+ private static Method findMethod(Class<?> clazz, String name, Class<?>[] args, Collection<AccessibleObject> setAccessible) {
if (clazz == null)
return null; // ends the recursion when getSuperClass returns null
try {
Method result = clazz.getDeclaredMethod(name, args);
- result.setAccessible(true);
+ if (setAccessible != null) {
+ setAccessible.add(result);
+ } else {
+ result.setAccessible(true);
+ }
return result;
} catch (SecurityException e) {
// if we do not have the permissions then we will not find the method
} catch (NoSuchMethodException | RuntimeException e) {
// do nothing look in super class below
// have to avoid blowing up <clinit>
- }
- return findMethod(clazz.getSuperclass(), name, args);
+ }
+ return findMethod(clazz.getSuperclass(), name, args, setAccessible);
}
private static void callAddURLMethod(URL arg) throws InvocationTargetException {
@@ -83,6 +96,14 @@ public class FrameworkExtensionInstaller {
}
}
+ private static void callAddFilePathMethod(File file) throws InvocationTargetException {
+ try {
+ ADD_FWK_FILE_PATH_METHOD.invoke(CL, new Object[] {file.getCanonicalPath()});
+ } catch (Throwable t) {
+ throw new InvocationTargetException(t);
+ }
+ }
+
private final EquinoxConfiguration configuration;
public FrameworkExtensionInstaller(EquinoxConfiguration configuraiton) {
@@ -113,34 +134,36 @@ public class FrameworkExtensionInstaller {
// framework extensions
return;
}
- if (CL == null || ADD_FWK_URL_METHOD == null) {
- // use the first revision as the blame
- ModuleRevision revision = revisions.iterator().next();
- throw new BundleException("Cannot support framework extension bundles without a public addURL(URL) method on the framework class loader: " + revision.getBundle()); //$NON-NLS-1$
- }
for (ModuleRevision revision : revisions) {
- File[] files = getExtensionFiles(revision);
- if (files == null) {
- return;
+ if (CL == null || (ADD_FWK_URL_METHOD == null && ADD_FWK_FILE_PATH_METHOD == null)) {
+ // use the first revision as the blame
+ throw new BundleException("Cannot support framework extension bundles without a public addURL(URL) or appendToClassPathForInstrumentation(String) method on the framework class loader: " + revision.getBundle()); //$NON-NLS-1$
}
+ File[] files = getExtensionFiles(revision);
for (File file : files) {
if (file == null) {
- continue;
+ continue;
}
try {
- callAddURLMethod(StorageUtil.encodeFileURL(file));
- }catch (InvocationTargetException | MalformedURLException e) {
+ if (ADD_FWK_URL_METHOD != null) {
+ callAddURLMethod(StorageUtil.encodeFileURL(file));
+ } else if (ADD_FWK_FILE_PATH_METHOD != null) {
+ callAddFilePathMethod(file);
+ }
+ } catch (InvocationTargetException | MalformedURLException e) {
throw new BundleException("Error adding extension content.", e); //$NON-NLS-1$
}
}
}
- try {
- // initialize the new urls
- CL.loadClass("thisIsNotAClass"); //$NON-NLS-1$
- } catch (ClassNotFoundException e) {
- // do nothing
+ if (CL != null) {
+ try {
+ // initialize the new urls
+ CL.loadClass("thisIsNotAClass"); //$NON-NLS-1$
+ } catch (ClassNotFoundException e) {
+ // do nothing
+ }
}
if (systemModule != null) {
BundleContext systemContext = systemModule.getBundle().getBundleContext();

Back to the top