Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2015-01-15 17:26:25 +0000
committerThomas Watson2015-01-16 14:40:07 +0000
commitd25dd9e060c989637bd3f9fdee68d81fb9dfcc62 (patch)
tree7ba1cc7fb558f79aff44f5b99fbf67aeabe4e062
parent16bb483bd75d665c3ff6a554419ddf8ad93bab57 (diff)
downloadrt.equinox.framework-d25dd9e060c989637bd3f9fdee68d81fb9dfcc62.tar.gz
rt.equinox.framework-d25dd9e060c989637bd3f9fdee68d81fb9dfcc62.tar.xz
rt.equinox.framework-d25dd9e060c989637bd3f9fdee68d81fb9dfcc62.zip
Bug 457118 - OutOfMemoryError (Java Heap Space) when resolving bundles
- Add a option to control the batch size - Modify the batch loop to use a copy and list iterator - Added a test that has multiple require paths to a resource Change-Id: I0fe25b4ba266f6b51ffd8981a6942a72e708b158 Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java23
-rw-r--r--bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.a.MF6
-rw-r--r--bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.b.MF6
-rw-r--r--bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.c.MF6
-rw-r--r--bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.d.MF5
-rw-r--r--bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.e.MF6
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java29
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java4
8 files changed, 78 insertions, 7 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java
index 69df07323..7f10f05e5 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java
@@ -1794,6 +1794,29 @@ public class TestModuleContainer extends AbstractTest {
Assert.assertEquals("Wrong package name.", "biz", packageCaps.get(4).getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));
}
+ @Test
+ public void testBug457118() throws BundleException, IOException {
+ DummyContainerAdaptor adaptor = createDummyAdaptor();
+ ModuleContainer container = adaptor.getContainer();
+
+ Module systemBundle = installDummyModule("system.bundle.MF", Constants.SYSTEM_BUNDLE_LOCATION, container);
+
+ container.resolve(Arrays.asList(systemBundle), true);
+ Module e = installDummyModule("bug457118.e.MF", "e", container);
+ Module a = installDummyModule("bug457118.a.MF", "a", container);
+ Module b = installDummyModule("bug457118.b.MF", "b", container);
+ Module c = installDummyModule("bug457118.c.MF", "c", container);
+ Module d = installDummyModule("bug457118.d.MF", "d", container);
+
+ container.resolve(null, true);
+
+ Assert.assertEquals("e should resolve.", State.RESOLVED, e.getState());
+ Assert.assertEquals("a should resolve.", State.RESOLVED, a.getState());
+ Assert.assertEquals("b should resolve.", State.RESOLVED, b.getState());
+ Assert.assertEquals("c should resolve.", State.RESOLVED, c.getState());
+ Assert.assertEquals("d should resolve.", State.RESOLVED, d.getState());
+ }
+
private static void assertWires(List<ModuleWire> required, List<ModuleWire>... provided) {
for (ModuleWire requiredWire : required) {
for (List<ModuleWire> providedList : provided) {
diff --git a/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.a.MF b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.a.MF
new file mode 100644
index 000000000..0f7a10b51
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.a.MF
@@ -0,0 +1,6 @@
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: a
+Bundle-Version: 1.0.0
+Export-Package:
+ a; version=1.0; uses:="b,c"
+Require-Bundle: b, c
diff --git a/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.b.MF b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.b.MF
new file mode 100644
index 000000000..8b891183b
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.b.MF
@@ -0,0 +1,6 @@
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: b
+Bundle-Version: 1.0.0
+Export-Package:
+ b; version=1.0; uses:="d"
+Require-Bundle: d; visibility:=reexport
diff --git a/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.c.MF b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.c.MF
new file mode 100644
index 000000000..7d548524c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.c.MF
@@ -0,0 +1,6 @@
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: c
+Bundle-Version: 1.0.0
+Export-Package:
+ c; version=1.0; uses:="d"
+Require-Bundle: d; visibility:=reexport
diff --git a/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.d.MF b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.d.MF
new file mode 100644
index 000000000..e382078cf
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.d.MF
@@ -0,0 +1,5 @@
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: d
+Bundle-Version: 1.0.0
+Export-Package:
+ d; version=1.0
diff --git a/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.e.MF b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.e.MF
new file mode 100644
index 000000000..d313fe9f5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/test_files/containerTests/bug457118.e.MF
@@ -0,0 +1,6 @@
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: e
+Bundle-Version: 1.0.0
+Export-Package:
+ e; version=1.0; uses:="a"
+Require-Bundle: a
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java
index 0f980da00..0571ec5aa 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 IBM Corporation and others.
+ * Copyright (c) 2012, 2015 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
@@ -17,6 +17,7 @@ import org.eclipse.osgi.container.ModuleRequirement.DynamicModuleRequirement;
import org.eclipse.osgi.container.namespaces.EquinoxFragmentNamespace;
import org.eclipse.osgi.internal.container.InternalUtils;
import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.report.resolution.*;
@@ -54,6 +55,9 @@ final class ModuleResolver {
boolean DEBUG_WIRING = false;
boolean DEBUG_REPORT = false;
+ private final int DEFAULT_BATCH_SIZE = 100;
+ final int resolverRevisionBatchSize;
+
void setDebugOptions() {
DebugOptions options = adaptor.getDebugOptions();
// may be null if debugging is not enabled
@@ -87,6 +91,17 @@ final class ModuleResolver {
ModuleResolver(ModuleContainerAdaptor adaptor) {
this.adaptor = adaptor;
setDebugOptions();
+ String batchSizeConfig = this.adaptor.getProperty(EquinoxConfiguration.PROP_RESOLVER_REVISION_BATCH_SIZE);
+ int tempBatchSize;
+ try {
+ tempBatchSize = batchSizeConfig == null ? DEFAULT_BATCH_SIZE : Integer.parseInt(batchSizeConfig);
+ } catch (NumberFormatException e) {
+ tempBatchSize = DEFAULT_BATCH_SIZE;
+ }
+ if (tempBatchSize < 1) {
+ tempBatchSize = DEFAULT_BATCH_SIZE;
+ }
+ this.resolverRevisionBatchSize = tempBatchSize;
}
/**
@@ -934,17 +949,19 @@ final class ModuleResolver {
long initialFreeMemory = Runtime.getRuntime().freeMemory();
long maxUsedMemory = 0;
+ // make a copy so we do not modify the input
+ revisions = new LinkedList<ModuleRevision>(revisions);
List<Resource> toResolve = new ArrayList<Resource>();
- while (revisions.size() > 0) {
- Resource single = revisions.iterator().next();
- revisions.remove(single);
+ for (Iterator<ModuleRevision> iResources = revisions.iterator(); iResources.hasNext();) {
+ ModuleRevision single = iResources.next();
+ iResources.remove();
if (DEBUG_ROOTS) {
Debug.println("Resolver: Resolving root bundle: " + single); //$NON-NLS-1$
}
if (!wirings.containsKey(single) && !failedToResolve.contains(single)) {
toResolve.add(single);
}
- if (toResolve.size() == RESOLVE_REVISIONS_BATCH_SIZE || revisions.size() == 0) {
+ if (toResolve.size() == resolverRevisionBatchSize || !iResources.hasNext()) {
resolveRevisions(toResolve, isMandatory, logger, result);
toResolve.clear();
}
@@ -952,7 +969,7 @@ final class ModuleResolver {
}
if (DEBUG_ROOTS) {
- Debug.println("Resolver: resolve batch size: " + RESOLVE_REVISIONS_BATCH_SIZE); //$NON-NLS-1$ //$NON-NLS-2$
+ Debug.println("Resolver: resolve batch size: " + RESOLVE_REVISIONS_BATCH_SIZE); //$NON-NLS-1$
Debug.println("Resolver: time to resolve: " + (System.currentTimeMillis() - startTime) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
Debug.println("Resolver: max used memory: " + maxUsedMemory / (1024 * 1024) + "Mo"); //$NON-NLS-1$ //$NON-NLS-2$
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
index a8cfe68f9..bb50bb8eb 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2003, 2014 IBM Corporation and others.
+ * Copyright (c) 2003, 2015 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
@@ -192,6 +192,8 @@ public class EquinoxConfiguration implements EnvironmentInfo {
public static final String PROP_ALLOW_RESTRICTED_PROVIDES = "osgi.equinox.allow.restricted.provides"; //$NON-NLS-1$
public static final String PROP_LOG_HISTORY_MAX = "equinox.log.history.max"; //$NON-NLS-1$
+ public static final String PROP_RESOLVER_REVISION_BATCH_SIZE = "equinox.resolver.revision.batch.size"; //$NON-NLS-1$
+
private final static Collection<String> populateInitConfig = Arrays.asList(PROP_OSGI_ARCH, PROP_OSGI_OS, PROP_OSGI_WS, PROP_OSGI_NL, FRAMEWORK_OS_NAME, FRAMEWORK_OS_VERSION, FRAMEWORK_PROCESSOR, FRAMEWORK_LANGUAGE);
/**

Back to the top