Community
Participate
Working Groups
Build ID: 3.3.1 Steps To Reproduce: 1. install a bundle 2. start a bundle 3. stop a bundle 4. uninstall a bundle Do steps 1-4 repeatedly. There is a memory leak! More information: A slow memory-leak tendency could be found during running the deployment endurance test with CE60 load12. The deployment test will do as below for each time: -------------------------------------------------- install test bundle start test bundle stop test bundle uninstall test bundle -------------------------------------------------- After running for over 400 times, I got the snapshot of the instance counts in memory(excluding platform) as below(the maximal ten counts). -------------------------------------------------- 5111 instances of class org.eclipse.osgi.internal.resolver.ImportPackageSpecificationImpl 5103 instances of class org.eclipse.osgi.internal.module.ResolverImport 4793 instances of class [Lorg.eclipse.osgi.internal.module.VersionSupplier; 4483 instances of class org.osgi.framework.Version 3549 instances of class org.eclipse.osgi.internal.resolver.ExportPackageDescriptionImpl 3536 instances of class org.eclipse.osgi.internal.module.ResolverExport 2942 instances of class org.eclipse.osgi.service.resolver.VersionRange 876 instances of class [Lorg.eclipse.osgi.service.resolver.ExportPackageDescription; 677 instances of class [Lorg.eclipse.osgi.internal.module.ResolverExport; 640 instances of class [Lorg.eclipse.osgi.service.resolver.ImportPackageSpecification; ...... -------------------------------------------------- (The above instances still exist even though gc is invoked) And the instance data members for org.eclipse.osgi.internal.resolver.ImportPackageSpecificationImpl are as below: -------------------------------------------------- attributes (L) : <null> bundle (L) : org.eclipse.osgi.internal.resolver.BundleDescriptionImpl@0x3636a48 (64 bytes) bundleVersionRange (L) : <null> name (L) : tests.integration.acceptance.deployment.server.bundles.dynamic.divide (24 bytes) resolution (L) : static (24 bytes) supplier (L) : org.eclipse.osgi.internal.resolver.ExportPackageDescriptionImpl@0x3636b98 (57 bytes) symbolicName (L) : <null> versionRange (L) : org.eclipse.osgi.service.resolver.VersionRange@0x3638348 (18 bytes) -------------------------------------------------- From the below instance counts snapshot after the test is called 0/30/60/90 times, you can see the instance counts of these classes are increasing regularly during the reduplicate deployment/undeployment. 0:----------------- 2009 instances of class org.eclipse.osgi.internal.resolver.ImportPackageSpecificationImpl 2001 instances of class org.eclipse.osgi.internal.module.ResolverImport 30:---------------- 2183 instances of class org.eclipse.osgi.internal.resolver.ImportPackageSpecificationImpl 2175 instances of class org.eclipse.osgi.internal.module.ResolverImport 60:---------------- 2363 instances of class org.eclipse.osgi.internal.resolver.ImportPackageSpecificationImpl 2355 instances of class org.eclipse.osgi.internal.module.ResolverImport 90:---------------- 2543 instances of class org.eclipse.osgi.internal.resolver.ImportPackageSpecificationImpl 2535 instances of class org.eclipse.osgi.internal.module.ResolverImport I do not know the reason of this leak. Maybe it is a problem of equinox?
I found that the increased objects are almost all referenced from the class org.eclipse.osgi.internal.resolver.BundleDescriptionImpl$LazyData directly or indirectly.(See the attached snapshot of one LazyData instance) And I also found that during the reduplicate deployment/undeployment, files as below will be created continuously. In fact, after 100 times deployment/undeployment were done, such 1000 set files were newly created. ---------------------------------------------------------- {CE_Instance_Dir}/osgicfg/org.eclipse.osgi/.bundledata.xxx {CE_Instance_Dir}/osgicfg/org.eclipse.osgi/.lazy.xxx {CE_Instance_Dir}/osgicfg/org.eclipse.osgi/.state.xxx ---------------------------------------------------------- From the above info, I guess maybe equinox keeps the 'lazy data' both in memory and disk based on some algorithm. So, I am not sure but I guess that the 'memory-leak' is not a problem if the increased objects are still controlled by equinox as 'lazy data'. I also tried to add a '-Dosgi.noLazyStateLoading=true' option as CE vm arg to see whether the 'memory-leak' does not occur when unusing 'lazy load'. But this option did not go into effect and the 'lazy datas' in both memory and disk are still created.
I think this is really a problem of Equinox. The reason is that class org.eclipse.osgi.internal.module.ResolverBundle maintains a arraylist named 'refs', and it only provides a addRef() method for adding member to this arraylist but a removeRef() method for removing member from the arraylist is not provided. In detail, if 'org.osgi.framework' is included in the 'Import-Package' list of the manifest.mf of a bundle, when this bundle is being resolved, the 'ResolverBundle' instance of this being deployed bundle will be added to 'refs' list in the 'ResolverBundle' instance of 'System Bundle'. But, when the deployed bundle is being unresolved, nothing will be removed from 'refs'. The attached file is a decompiled java file from the class org.eclipse.osgi.internal.module.ResolverBundle.class in org.osgi.eclipse.equinox_3.3.1.p1.jar we now using. You can find the init and add methods for 'refs' as below, but there is no remove method for 'refs' at all. ---------------------------------------------------- void initialize(boolean useSelectedExports) { if(getBundle().isSingleton()) <= the 'System Bundle' will satisfy this condition. refs = new ArrayList(); ... } void addRef(ResolverBundle ref) { if(refs != null && !refs.contains(ref)) refs.add(ref); } ----------------------------------------------------- Only for test purpose, I tried to use 'Import-Package: com.bea.core.workmanager' to replace the original 'Import-Package: org.osgi.framework' in the menifest.mf of the bundle which is repeatably deployed/undeployed during the test so that the 'refs.add(ref)' will not be invoked. And then, the 'memory-leak' disappeared.
Thanks for the great analysis John (kudos with a greatbug)! I will investigate for M7.
Created attachment 93892 [details] patch The resolver is in need of some serious love. I really hope GSOC project can help us move to a SAT4J solution (http://blog.bjhargrave.com/2008/03/equinox-and-google-summer-of-code.html) The ref stuff is only used to help in the selection of singleton bundles when we are attempting to resolve multiple versions of a singleton bundle at the same time. This patch clears the ref set after the singleton selection process and prevents the ref set from growing when a bundle is already resolved (and hence needs to ref counts for singleton selection).
That last sentence should read ... and hence needs *no* ref counts for singleton selection
Patch released for 3.4 M7.