Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2009-09-08 19:13:50 +0000
committerThomas Watson2009-09-08 19:13:50 +0000
commit1320f1b9fbe5699dd30300f55737d26731035e5a (patch)
tree932c909006ec278f8561a81263f1db9288cc9c82
parentbb286f21405f581d54c70c5f7bd1d55352086d5a (diff)
downloadrt.equinox.framework-1320f1b9fbe5699dd30300f55737d26731035e5a.tar.gz
rt.equinox.framework-1320f1b9fbe5699dd30300f55737d26731035e5a.tar.xz
rt.equinox.framework-1320f1b9fbe5699dd30300f55737d26731035e5a.zip
Bug 288680 - Change lazy start trigger to be a one time event per class loader
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java10
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java22
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java23
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java7
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoader.java16
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java28
6 files changed, 69 insertions, 37 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java
index 5bcbdfec5..5a00f9807 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java
@@ -348,14 +348,20 @@ public class ClassLoadingBundleTests extends AbstractBundleTests {
actualFrameworkEvents = frameworkListenerResults.getResults(1);
compareResults(expectedFrameworkEvents, actualFrameworkEvents);
+ expectedEvents = new Object[1];
+ expectedEvents[0] = new BundleEvent(BundleEvent.STARTED, osgiA);
+ actualEvents = simpleResults.getResults(1);
+ compareResults(expectedEvents, actualEvents);
+
startLevel.setStartLevel(startLevel.getStartLevel() - 15);
expectedFrameworkEvents = new Object[1];
expectedFrameworkEvents[0] = new FrameworkEvent(FrameworkEvent.STARTLEVEL_CHANGED, OSGiTestsActivator.getContext().getBundle(0), null);
actualFrameworkEvents = frameworkListenerResults.getResults(1);
compareResults(expectedFrameworkEvents, actualFrameworkEvents);
- expectedEvents = new Object[0];
- actualEvents = simpleResults.getResults(0);
+ expectedEvents = new Object[1];
+ expectedEvents[0] = new BundleEvent(BundleEvent.STOPPED, osgiA);
+ actualEvents = simpleResults.getResults(1);
compareResults(expectedEvents, actualEvents);
// now load a class while start-level is met.
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java
index c7b6c957b..997cadc72 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java
+++ b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,6 +14,7 @@ package org.eclipse.osgi.framework.adaptor;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
+import org.osgi.framework.BundleException;
/**
* A ClassLoaderDelegate is used by the BundleClassLoader in a similar
@@ -25,6 +26,7 @@ import java.util.Enumeration;
* <p>
* This interface is not intended to be implemented by clients.
* </p>
+ * @noimplement This interface is not intended to be implemented by clients.
* @since 3.1
*/
public interface ClassLoaderDelegate {
@@ -89,4 +91,22 @@ public interface ClassLoaderDelegate {
*/
public String findLibrary(String libraryname);
+ /**
+ * Returns true if the lazy trigger has been set for this
+ * delegate. The lazy trigger is set when a bundle has been
+ * marked for lazy activation due to a successful class load.
+ * @return true if the lazy trigger has been set
+ * @since 3.6
+ */
+ public boolean isLazyTriggerSet();
+
+ /**
+ * Sets the lazy trigger for this delegate. This will activate
+ * the bundle if the bundle has been started with the activation
+ * policy and the bundle's start level is met.
+ * @throws BundleException if an error occurred while activating the bundle
+ * @see ClassLoaderDelegate#isLazyTriggerSet()
+ * @since 3.6
+ */
+ public void setLazyTrigger() throws BundleException;
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java
index 15c6114f4..323e52e13 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java
@@ -24,6 +24,7 @@ import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
public class BundleHost extends AbstractBundle {
+ public static final int LAZY_TRIGGER = 0x40000000;
/**
* The BundleLoader proxy; a lightweight object that acts as a proxy
* to the BundleLoader and allows lazy creation of the BundleLoader object
@@ -235,7 +236,7 @@ public class BundleHost extends AbstractBundle {
if (!(e instanceof StatusException) && (bundledata.getStatus() & Constants.BUNDLE_LAZY_START) != 0 && !testStateChanging(Thread.currentThread()))
try {
// only start the bundle if this is a simple CNFE
- framework.secureAction.start(this, START_TRANSIENT);
+ loader.setLazyTrigger();
} catch (BundleException be) {
framework.adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, be.getMessage(), 0, be, null));
}
@@ -303,9 +304,8 @@ public class BundleHost extends AbstractBundle {
}
if (!framework.active || (state & ACTIVE) != 0)
return;
-
if (getStartLevel() > framework.startLevelManager.getStartLevel()) {
- if ((options & START_TRANSIENT) != 0) {
+ if ((options & LAZY_TRIGGER) == 0 && (options & START_TRANSIENT) != 0) {
// throw exception if this is a transient start
String msg = NLS.bind(Msg.BUNDLE_TRANSIENT_START_ERROR, this);
// Use a StatusException to indicate to the lazy starter that this should result in a warning
@@ -409,11 +409,13 @@ public class BundleHost extends AbstractBundle {
// Return false if the bundle is not persistently marked for start
if ((status & Constants.BUNDLE_STARTED) == 0)
return false;
- if ((status & Constants.BUNDLE_ACTIVATION_POLICY) == 0 || (status & Constants.BUNDLE_LAZY_START) == 0)
+ if ((status & Constants.BUNDLE_ACTIVATION_POLICY) == 0 || (status & Constants.BUNDLE_LAZY_START) == 0 || isLazyTriggerSet())
return true;
- if (!isResolved())
- // should never transition from UNRESOLVED -> STARTING
- return false;
+ if (!isResolved()) {
+ if (framework.getAdaptor().getState().isResolved() || !framework.packageAdmin.resolveBundles(new Bundle[] {this}))
+ // should never transition from UNRESOLVED -> STARTING
+ return false;
+ }
// now we can publish the LAZY_ACTIVATION event
state = STARTING;
// release the state change lock before sending lazy activation event (bug 258659)
@@ -422,6 +424,13 @@ public class BundleHost extends AbstractBundle {
return false;
}
+ private synchronized boolean isLazyTriggerSet() {
+ if (proxy == null)
+ return false;
+ BundleLoader loader = proxy.getBasicBundleLoader();
+ return loader != null ? loader.isLazyTriggerSet() : false;
+ }
+
/**
* Create a BundleContext for this bundle.
*
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java
index 2836cfc13..a26ec7177 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java
@@ -46,7 +46,6 @@ public class StartLevelManager implements EventDispatcher, EventListener, StartL
/** An object used to lock the active startlevel while it is being referenced */
private final Object lock = new Object();
private final Framework framework;
- volatile private boolean settingStartLevel = false;
/** This constructor is called by the Framework */
protected StartLevelManager(Framework framework) {
@@ -224,7 +223,6 @@ public class StartLevelManager implements EventDispatcher, EventListener, StartL
*/
void doSetStartLevel(int newSL) {
synchronized (lock) {
- settingStartLevel = true;
ClassLoader previousTCCL = Thread.currentThread().getContextClassLoader();
ClassLoader contextFinder = framework.getContextFinder();
if (contextFinder == previousTCCL)
@@ -273,7 +271,6 @@ public class StartLevelManager implements EventDispatcher, EventListener, StartL
} finally {
if (contextFinder != null)
Thread.currentThread().setContextClassLoader(previousTCCL);
- settingStartLevel = false;
}
}
}
@@ -696,8 +693,4 @@ public class StartLevelManager implements EventDispatcher, EventListener, StartL
}
}
}
-
- public boolean isSettingStartLevel() {
- return settingStartLevel;
- }
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoader.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoader.java
index ae867f25f..bdc87209c 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoader.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoader.java
@@ -20,12 +20,12 @@ import java.util.*;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.internal.core.*;
+import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.util.KeyedHashSet;
import org.eclipse.osgi.internal.loader.buddy.PolicyHandler;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.*;
/**
* This object is responsible for all classloader delegation for a bundle.
@@ -41,6 +41,7 @@ public class BundleLoader implements ClassLoaderDelegate {
public final static byte FLAG_HASDYNAMICIMPORTS = 0x02;
public final static byte FLAG_HASDYNAMICEIMPORTALL = 0x04;
public final static byte FLAG_CLOSED = 0x08;
+ public final static byte FLAG_LAZYTRIGGER = 0x10;
public final static ClassContext CLASS_CONTEXT = (ClassContext) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
@@ -253,6 +254,17 @@ public class BundleLoader implements ClassLoaderDelegate {
return importedSources;
}
+ public synchronized boolean isLazyTriggerSet() {
+ return (loaderFlags & FLAG_LAZYTRIGGER) != 0;
+ }
+
+ public void setLazyTrigger() throws BundleException {
+ synchronized (this) {
+ loaderFlags |= FLAG_LAZYTRIGGER;
+ }
+ BundleLoaderProxy.secureAction.start(bundle, Bundle.START_TRANSIENT | BundleHost.LAZY_TRIGGER);
+ }
+
final PackageSource createExportPackageSource(ExportPackageDescription export, KeyedHashSet visited) {
BundleLoaderProxy exportProxy = getLoaderProxy(export.getExporter());
if (exportProxy == null)
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java
index 75fefdbca..d9a4df652 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java
+++ b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2008 IBM Corporation and others.
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,7 +14,6 @@ package org.eclipse.core.runtime.internal.adaptor;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
-import java.security.AccessController;
import java.util.*;
import org.eclipse.osgi.baseadaptor.*;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
@@ -26,20 +25,16 @@ import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.adaptor.StatusException;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.internal.core.*;
+import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.framework.util.SecureAction;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.StateHelper;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
-import org.osgi.service.startlevel.StartLevel;
public class EclipseLazyStarter implements ClassLoadingStatsHook, AdaptorHook, HookConfigurator {
private static final boolean throwErrorOnFailedStart = "true".equals(FrameworkProperties.getProperty("osgi.compatibility.errorOnFailedStart", "true")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
- private static final SecureAction secureAction = (SecureAction) AccessController.doPrivileged(SecureAction.createSecureAction());
- private StartLevelManager startLevelService;
- private ServiceReference slRef;
private BaseAdaptor adaptor;
// holds the current activation trigger class and the ClasspathManagers that need to be activated
private ThreadLocal activationStack = new ThreadLocal();
@@ -102,14 +97,15 @@ public class EclipseLazyStarter implements ClassLoadingStatsHook, AdaptorHook, H
throw (TerminatingClassNotFoundException) errors.get(managers[i]);
continue;
}
- AbstractBundle bundle = (AbstractBundle) managers[i].getBaseData().getBundle();
+
// The bundle must be started.
// Note that another thread may already be starting this bundle;
// In this case we will timeout after 5 seconds and record the BundleException
try {
// do not persist the start of this bundle
- secureAction.start(bundle, Bundle.START_TRANSIENT);
+ managers[i].getBaseClassLoader().getDelegate().setLazyTrigger();
} catch (BundleException e) {
+ Bundle bundle = managers[i].getBaseData().getBundle();
Throwable cause = e.getCause();
if (cause != null && cause instanceof StatusException) {
StatusException status = (StatusException) cause;
@@ -148,6 +144,8 @@ public class EclipseLazyStarter implements ClassLoadingStatsHook, AdaptorHook, H
private boolean shouldActivateFor(String className, BaseData bundledata, EclipseStorageHook storageHook, ClasspathManager manager) throws ClassNotFoundException {
if (!isLazyStartable(className, bundledata, storageHook))
return false;
+ //if (manager.getBaseClassLoader().getDelegate().isLazyTriggerSet())
+ // return false;
// Don't activate non-starting bundles
if (bundledata.getBundle().getState() == Bundle.RESOLVED) {
if (throwErrorOnFailedStart) {
@@ -155,8 +153,7 @@ public class EclipseLazyStarter implements ClassLoadingStatsHook, AdaptorHook, H
if (error != null)
throw error;
}
- StartLevelManager sl = startLevelService;
- return sl != null && ((sl.getStartLevel() == bundledata.getStartLevel() && sl.isSettingStartLevel()));
+ return (bundledata.getStatus() & Constants.BUNDLE_STARTED) != 0;
}
return true;
}
@@ -203,16 +200,11 @@ public class EclipseLazyStarter implements ClassLoadingStatsHook, AdaptorHook, H
}
public void frameworkStart(BundleContext context) throws BundleException {
- slRef = context.getServiceReference(StartLevel.class.getName());
- if (slRef != null)
- startLevelService = (StartLevelManager) context.getService(slRef);
+ // nothing
}
public void frameworkStop(BundleContext context) throws BundleException {
- if (slRef != null) {
- context.ungetService(slRef);
- startLevelService = null;
- }
+ // nothing
}
public void frameworkStopping(BundleContext context) {

Back to the top