Bug 224432 - Memory Leak in install -> start -> stop -> uninistall cycle
Summary: Memory Leak in install -> start -> stop -> uninistall cycle
Status: RESOLVED FIXED
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: Framework (show other bugs)
Version: 3.3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.4 M7   Edit
Assignee: Thomas Watson CLA
QA Contact:
URL:
Whiteboard:
Keywords: greatbug
Depends on:
Blocks:
 
Reported: 2008-03-27 14:43 EDT by John Wells CLA
Modified: 2008-03-31 18:11 EDT (History)
3 users (show)

See Also:


Attachments
patch (1.70 KB, patch)
2008-03-27 18:05 EDT, Thomas Watson CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John Wells CLA 2008-03-27 14:43:07 EDT
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?
Comment 1 John Wells CLA 2008-03-27 14:44:51 EDT
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.
Comment 2 John Wells CLA 2008-03-27 14:45:52 EDT
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.
Comment 3 Thomas Watson CLA 2008-03-27 15:35:59 EDT
Thanks for the great analysis John (kudos with a greatbug)!  I will investigate for M7.
Comment 4 Thomas Watson CLA 2008-03-27 18:05:35 EDT
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).
Comment 5 Thomas Watson CLA 2008-03-27 18:07:08 EDT
That last sentence should read ...  and hence needs *no* ref counts for singleton selection
Comment 6 Thomas Watson CLA 2008-03-31 18:11:48 EDT
Patch released for 3.4 M7.