[GLASSFISH-19727] wab expanded directory can not be cleaned after accessing the wab resource Created: 25/Feb/13  Updated: 19/Sep/14  Resolved: 17/Jun/13

Status: Resolved
Project: glassfish
Component/s: OSGi-JavaEE
Affects Version/s: 3.1.2
Fix Version/s: 4.1

Type: Bug Priority: Critical
Reporter: TangYong Assignee: Sanjeeb Sahoo
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows XP



 Description   

Similar to Glassfish-19696, however, re-producing steps are a litter different from that bug.

Re-producing Steps:

1 asadmin deploy --type=osgi sample.uas.api.jar
2 asadmin deploy --type=osgi sample.uas.simplewabfragment.jar
3 asadmin deploy --type=osgi sample.uas.simplewab.war
4 accessing the wab "localhost:8080/uas/" ---> accessing wab resources
5 asadmin undeploy sample.uas.simplewab



 Comments   
Comment by TangYong [ 25/Feb/13 ]

The reason has been found and a litter complex as following:

[Reason]
While deploying a wab, a OSGiDeploymentContext instance will be created and a WABClassLoader will be setuped by calling setupClassLoader(). Then, while accessing WAB resouces(eg. localhost:8080/uas/), WEB-INF/lib/*.jars will be scanned and opened(eg. calling org.glassfish.web.loader.WebappClassLoader.openJARs()). What's more, these jars must be opened alway in order to service WAB resources.

Then, while undeploying the wab, we must execute org.glassfish.web.loader.WebappClassLoader.closeJARS(true) or stop() in order to release these WEB-INF/lib/.jars resources. I have made such an experiment on OSGiWebUndeploymentRequest class and obtain the setuped WABClassloader to execute closeJARS(true) by OSGiUndeploymentRequest's dc field(I modified it into protected access level), however, these WEB-INF/lib/.jars resources are not still closed.

Next, I start to guess a thing that the WABClassloader I obtained by dc.getFinalClassLoader() is not the same as the WABClassloader which is setuped by the OSGiDeploymentContext instance. And by confirming WABClassLoader instance id, I can confirm the guess is right.

That is to say, OSGiUndeploymentRequest.getDeploymentContextImpl will create a new OSGiDeploymentContext and WABClassloader instance and is different from OSGiDeploymentRequest.getDeploymentContextImpl.

In a word, here there is a jar resource leak caused by a WABClassLoader while undeploying a wab.

[Fixing Way]
While undeploying the wab, we must obtain the same WABClassLoader as deploying the wab. So, I consider to register the WABClassLoader into OSGi Registry with propery WabId="<the wab bundle id>", then, executing closeJARS(true).

Please Sahoo seeing what I said and maybe I have not said clearly.

Thanks
--Tang

Comment by TangYong [ 26/Feb/13 ]

Fixing Way needs to be taken care of because here , there are two basic fixing ways:

1 Registering WABClassLoader into OSGi registry

Although this seems to be direct, there are the following disadvantages:

1) Whether doing the duplicated work?
Because while deploying, a OSGiApplicationInfo has been registered into OSGi registry and by this OSGiApplicationInfo, we should get WABClassLoader for the wab.

2) How to unregister
This is also a issue if once deciding to use 1.

3) WABClassLoader's update
On some cases, while updating the WAB, bundle Id will not change, but we should update its WABClassLoader in order not use stale WABClassLoader.

2 Associate WABClassLoader between Deplying and UnDeploying

This should be better way for existed fighterfish design, and I have been mading some experiments, however, noticing Deploying/Undeploying class layers are a litter complex and needing more attention.

Comment by TangYong [ 26/Feb/13 ]

Now, I used 2 to fix the issue and a patch is in reviewing by Sahoo.
BTW: just as Sahoo comments in OSGiUndeploymentRequest.execute() :

OSGiUndeploymentRequest.java
        // TODO(Sahoo): There may be side effect of creating a deployment context
        // as that leads to creation of class loaders again.
        try
        {
            dc = getDeploymentContextImpl(
                    reporter,
                    logger,
                    osgiAppInfo.getAppInfo().getSource(),
                    getUndeployParams(osgiAppInfo),
                    env,
                    osgiAppInfo.getBundle());
        }

The side effect has been triggered by the issue.

Comment by Sanjeeb Sahoo [ 26/Mar/13 ]

Yes, by following the steps provided by Tang, I am able to reproduce this issue - only on Windows. I see that after undeployment of the wab, WEB-INF/lib/Bundle<id>.jar is still there. This jar is created for the fragment that's attached to the wab. Windows is known to not allow files to be deleted if there is another process which has open file descriptors for a file. So, I do agree Tang's analysis of the second WebAppClassLoader holding onto this reference is correct as well.

Since this is a Windows only bug and it does not have any effect on running of applications, I am inclined to defer this bug from 4.0 if I am not able to find a simple solution to the issue.

Comment by Sanjeeb Sahoo [ 26/Mar/13 ]

Defer to 4.0.1

Comment by Sanjeeb Sahoo [ 27/Mar/13 ]

Sending osgi-javaee-base/RELEASENOTE.txt
Sending osgi-javaee-base/src/main/java/org/glassfish/osgijavaeebase/OSGiUndeploymentRequest.java
Transmitting file data ..
Committed revision 60947.

Will resolve this bug when we integrate osgi-javaee-base:1.0.7 or higher version.

Comment by Sanjeeb Sahoo [ 17/Jun/13 ]

integrated osgi-javaee-base:1.0.7 in svn #62234.

Generated at Mon Jan 16 19:11:50 UTC 2017 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.