Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java')
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java50
1 files changed, 37 insertions, 13 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java
index 2e7f0e319..4e0f698dd 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java
@@ -96,7 +96,7 @@ public class BundleLoader extends ModuleLoader {
private Object classLoaderMonitor = new Object();
/* @GuardedBy("classLoaderMonitor") */
- private ModuleClassLoader classloader;
+ private volatile ModuleClassLoader classloader;
private final ClassLoader parent;
private final AtomicBoolean triggerClassLoaded = new AtomicBoolean(false);
@@ -220,8 +220,14 @@ public class BundleLoader extends ModuleLoader {
}
public ModuleClassLoader getModuleClassLoader() {
- synchronized (classLoaderMonitor) {
- if (classloader == null) {
+ if (classloader != null) {
+ return classloader;
+ }
+ // Need to obtain readlock on module database to prevent out of order locks that can happen
+ // when a refresh operation (requiring write lock) closes a BundleLoader
+ container.getStorage().getModuleDatabase().readLock();
+ try {
+ synchronized (classLoaderMonitor) {
final List<ClassLoaderHook> hooks = container.getConfiguration().getHookRegistry().getClassLoaderHooks();
final Generation generation = (Generation) wiring.getRevision().getRevisionInfo();
if (System.getSecurityManager() == null) {
@@ -238,17 +244,26 @@ public class BundleLoader extends ModuleLoader {
for (ClassLoaderHook hook : hooks) {
hook.classLoaderCreated(classloader);
}
+ return classloader;
}
- return classloader;
+ } finally {
+ container.getStorage().getModuleDatabase().readUnlock();
}
}
@Override
protected void loadFragments(Collection<ModuleRevision> fragments) {
- synchronized (classLoaderMonitor) {
- addFragmentExports(wiring.getModuleCapabilities(PackageNamespace.PACKAGE_NAMESPACE));
- loadClassLoaderFragments(fragments);
- clearManifestLocalizationCache();
+ // Need to obtain readlock on module database to prevent out of order locks that can happen
+ // when a refresh operation (requiring write lock) closes a BundleLoader
+ container.getStorage().getModuleDatabase().readLock();
+ try {
+ synchronized (classLoaderMonitor) {
+ addFragmentExports(wiring.getModuleCapabilities(PackageNamespace.PACKAGE_NAMESPACE));
+ loadClassLoaderFragments(fragments);
+ clearManifestLocalizationCache();
+ }
+ } finally {
+ container.getStorage().getModuleDatabase().readUnlock();
}
}
@@ -289,10 +304,17 @@ public class BundleLoader extends ModuleLoader {
policy.close(context);
}
}
- synchronized (classLoaderMonitor) {
- if (classloader != null) {
- classloader.close();
+ // Need to obtain readlock on module database to prevent out of order locks that can happen
+ // when a refresh operation (requiring write lock) closes a BundleLoader
+ container.getStorage().getModuleDatabase().readLock();
+ try {
+ synchronized (classLoaderMonitor) {
+ if (classloader != null) {
+ classloader.close();
+ }
}
+ } finally {
+ container.getStorage().getModuleDatabase().readUnlock();
}
}
@@ -367,7 +389,7 @@ public class BundleLoader extends ModuleLoader {
String pkgName = getPackageName(name);
boolean bootDelegation = false;
// follow the OSGi delegation model
- if (checkParent && parent != null && container.isBootDelegationPackage(pkgName))
+ if (checkParent && parent != null && container.isBootDelegationPackage(pkgName)) {
// 2) if part of the bootdelegation list then delegate to parent and continue of failure
try {
return parent.loadClass(name);
@@ -375,6 +397,7 @@ public class BundleLoader extends ModuleLoader {
// we want to continue
bootDelegation = true;
}
+ }
Class<?> result = null;
try {
result = (Class<?>) searchHooks(name, PRE_CLASS);
@@ -438,13 +461,14 @@ public class BundleLoader extends ModuleLoader {
return result;
// hack to support backwards compatibility for bootdelegation
// or last resort; do class context trick to work around VM bugs
- if (parent != null && !bootDelegation && ((checkParent && container.getConfiguration().compatibilityBootDelegation) || isRequestFromVM()))
+ if (parent != null && !bootDelegation && ((checkParent && container.getConfiguration().compatibilityBootDelegation) || isRequestFromVM())) {
// we don't need to continue if a CNFE is thrown here.
try {
return parent.loadClass(name);
} catch (ClassNotFoundException e) {
// we want to generate our own exception below
}
+ }
throw new ClassNotFoundException(name + " cannot be found by " + this); //$NON-NLS-1$
}

Back to the top