I've been struggling to find a memory leak in an enterprise app
whose GUI we developed using jelly-swing.

Finally I've been able to make a minimalistic test which demonstrates the leak.
The problem is with the define:taglib and define:tag tags.
The test shows how repeteadly invoking a tag defined in a taglib increases
dramatically the number of instances of JellyContext and objects referencing
the contexts, and this objects get never released.


These are the two snapshots of the object instance before and after invoking
repeteadly the scripts. The new instances get never released.


Hope this helps.

>>>>> before.csv

"Name";"Instance count";"Difference";"Size"
"org.apache.commons.jelly.JellyContext";2;0;80
"org.apache.commons.jelly.TagLibrary$1";1;0;8
"org.apache.commons.jelly.expression.ConstantExpression";15;0;240
"org.apache.commons.jelly.expression.jexl.JexlExpression";3;0;48
"org.apache.commons.jelly.expression.jexl.JexlExpressionFactory";1;0;16
"org.apache.commons.jelly.expression.jexl.JexlExpressionFactory$ExpressionSupportLocal";3;0;72
"org.apache.commons.jelly.impl.CompositeTextScriptBlock";1;0;16
"org.apache.commons.jelly.impl.DefaultTagFactory";11;0;176
"org.apache.commons.jelly.impl.DynamicTagLibrary";1;0;24
"org.apache.commons.jelly.impl.ExpressionScript";1;0;16
"org.apache.commons.jelly.impl.ScriptBlock";12;0;192
"org.apache.commons.jelly.impl.StaticTagScript";1;0;64
"org.apache.commons.jelly.impl.TagScript";11;0;704
"org.apache.commons.jelly.impl.TextScript";5;0;80
"org.apache.commons.jelly.parser.XMLParser";1;0;80
"org.apache.commons.jelly.parser.XMLParser$1";1;0;24
"org.apache.commons.jelly.tags.core.ArgTag$1";1;0;16
"org.apache.commons.jelly.tags.core.ArgTag$2";1;0;16
"org.apache.commons.jelly.tags.core.ArgTag$3";1;0;16
"org.apache.commons.jelly.tags.core.ArgTag$4";1;0;16
"org.apache.commons.jelly.tags.core.ArgTag$5";1;0;16
"org.apache.commons.jelly.tags.core.ArgTag$6";1;0;16
"org.apache.commons.jelly.tags.core.CoreTagLibrary";1;0;16
"org.apache.commons.jelly.tags.core.JellyTag";1;0;32
"org.apache.commons.jelly.tags.define.DefineTagLibrary";1;0;16
"org.apache.commons.jelly.tags.define.ScriptTag";1;0;32
"org.apache.commons.jelly.tags.define.TagTag";1;0;32
"org.apache.commons.jelly.tags.define.TaglibTag";1;0;40
"org.apache.commons.jelly.tags.log.LogTagLibrary";1;0;16

>>>>. after.csv

"Name";"Instance count";"Difference";"Size"
"org.apache.commons.jelly.expression.ConstantExpression";165;"+150";2,640
"org.apache.commons.jelly.impl.TagScript";131;"+120";8,384
"org.apache.commons.jelly.impl.ScriptBlock";122;"+110";1,952
"org.apache.commons.jelly.impl.DefaultTagFactory";121;"+110";1,936
"org.apache.commons.jelly.expression.jexl.JexlExpressionFactory$ExpressionSupportLocal";33;"+30";792
"org.apache.commons.jelly.JellyContext";32;"+30";1,280
"org.apache.commons.jelly.expression.jexl.JexlExpression";33;"+30";528
"org.apache.commons.jelly.tags.core.InvokeStaticTag";20;"+20";1,120
"org.apache.commons.jelly.tags.core.InvokeTag";20;"+20";1,120
"org.apache.commons.jelly.tags.core.ArgTag";20;"+20";960
"org.apache.commons.jelly.expression.jexl.JexlExpressionFactory";11;"+10";176
"org.apache.commons.jelly.tags.core.JellyTag";11;"+10";352
"org.apache.commons.jelly.tags.define.TaglibTag";11;"+10";440
"org.apache.commons.jelly.tags.define.ScriptTag";11;"+10";352
"org.apache.commons.jelly.impl.DynamicTagLibrary";11;"+10";264
"org.apache.commons.jelly.impl.DynamicTag";10;"+10";400
"org.apache.commons.jelly.tags.define.TagTag";11;"+10";352
"org.apache.commons.jelly.impl.ExpressionScript";11;"+10";176
"org.apache.commons.jelly.impl.TextScript";15;"+10";240
"org.apache.commons.jelly.impl.CompositeTextScriptBlock";11;"+10";176
"org.apache.commons.jelly.impl.DynamicTagLibrary$1";10;"+10";160
"org.apache.commons.jelly.tags.log.DebugTag";10;"+10";400



>>>>>>>>>>>>>>>   Main.java
package test.jelly;

import java.io.*;
import java.net.*;
import org.apache.commons.jelly.*;

public class Main
{
  private static Main instance;
  private JellyContext context;

  static{
     instance = new Main();
  }

  private Main() {
     context = new JellyContext();
     context.setClassLoader(getClass().getClassLoader());
  }

public static Main getInstance() {
return instance;
}
public JellyContext runScript( String scriptName ) {
JellyContext childJC = null;


   ByteArrayOutputStream out = new ByteArrayOutputStream();

   try {
        URL url = this.getClass().getResource(scriptName);
       String exturl = url.toExternalForm();
       int lastSlash = exturl.lastIndexOf("/");
       String extBase = exturl.substring(0,lastSlash+1);
       URL baseurl = new URL(extBase);
       context.setCurrentURL(baseurl);

       XMLOutput xmlOutput = XMLOutput.createXMLOutput(out);
      childJC = context.runScript( scriptName, xmlOutput);
      xmlOutput.flush();
   } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(e.getMessage());
   }
    finally{
        try{ out.close(); }catch( Exception e ){/*DO NOTHING*/}
        out = null;
    }
   return childJC;
  }

  public void addInt( int integer ) {
     Integer i = (Integer)context.findVariable("integer");
     if( i == null ){
        i = new Integer(0);
        context.setVariable("integer",i);
     }
     i = new Integer( i.intValue() + integer );
     context.setVariable("integer",i);
  }

  public static void main( String[] args ) {
     try {
          int n = Integer.parseInt(args[0]);

        Main main = Main.getInstance();
        main.runScript("definetag.jelly");

           // Read a line to start the test
         System.in.read();

for (int i=0; i < n; i++) {
main.runScript("invoketag.jelly");
} // To take the profiling snapshot
System.in.read();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}


>>>>>>>>>>  definetag.jelly

<?xml version="1.0"  encoding="ISO-8859-1"?>
<j:jelly
   xmlns:j="jelly:core"
   xmlns:log="jelly:log"
   xmlns:define="jelly:define"
   xmlns:bogus="bogus"
  xmlns:swing="jelly:swing">

<define:taglib uri="bogus">
<define:tag name="count">
<j:invokeStatic className="test.jelly.Main" method="getInstance" var="main" />
<j:invoke on="${main}" method="addInt" >
<j:arg value="1" type="int" />
</j:invoke>
<log:debug>bogus ${integer}</log:debug>
</define:tag>
</define:taglib>


<define:script var="incrCounter">
<j:invokeStatic className="test.jelly.Main" method="getInstance" var="main" />
<j:invoke on="${main}" method="addInt" >
<j:arg value="1" type="int" />
</j:invoke>
<bogus:count/>
</define:script>
</j:jelly>


>>>>>>  invoketag.jelly

<?xml version="1.0"  encoding="ISO-8859-1"?>
<j:jelly
   xmlns:j="jelly:core"
   xmlns:log="jelly:log"
   xmlns:define="jelly:define"
  xmlns:swing="jelly:swing">

  <j:include uri="definetag.jelly" />
  <define:invoke script="${incrCounter}" />
   <log:debug>Count: ${integer}</log:debug>
</j:jelly>




--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to