Bug 49021 - TaskDef/ScriptDef in Sub Build = Memory Disaster
Summary: TaskDef/ScriptDef in Sub Build = Memory Disaster
Status: NEW
Alias: None
Product: Ant
Classification: Unclassified
Component: Core tasks (show other bugs)
Version: 1.8.2
Hardware: PC Windows XP
: P2 major with 2 votes (vote)
Target Milestone: ---
Assignee: Ant Notifications List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-03-29 22:21 UTC by Mike Murray
Modified: 2010-12-27 11:12 UTC (History)
2 users (show)



Attachments
Analysis Script (2.80 KB, text/plain)
2010-03-29 22:29 UTC, Mike Murray
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Murray 2010-03-29 22:21:59 UTC
Sub-builds (antcall, subant) load a task each time the task is defined, but do not release it when the sub-build project completes.  

It would be best if the sub-build would recognize the task is already loaded, just like it does when the task is loaded within the same project using loaderref.  If it is not feasible to re-use the task in this scenario, then it should be released to avoid sucking up all the available memory very quickly. I think this is only a problem with recent (> 1.5.8) releases of Groovy, since it requires so much PermGen.  You can't give it enough anymore.

The attached script runs out of memory in about 34 iterations of defining the groovy task within an antcall. 

It can be run as follows, where 3rdparty_libdir is the folder that contains the jars needed for the groovy task:
  ant -f GroovyMem.xml -Diterations=100 -D3rdparty_libdir=\3rdPartyJars\lib

Note: The script uses AntContrib to iterate.

http://marc.info/?l=ant-user&m=126970939205980&w=2
Comment 1 Mike Murray 2010-03-29 22:29:26 UTC
Created attachment 25209 [details]
Analysis Script

Demonstrates memory bug with:
   ant -f GroovyMem.xml -Diterations=100 -D3rdparty_libdir=\3rdPartyJars\lib
Comment 2 Keith D Gregory 2010-08-09 07:40:18 UTC
I ran into a similar problem. It appears that <taskdef> creates a new classloader every time (makes sense), but uses the J2EE delegation model and doesn't tie that classloader to the task/project that created it (doesn't make sense to me, but there might be a reason). So the classes never get GC'd. A longer writeup is on blog.kdgregory.com, today's date.

There is a work-around: use Groovy via antlib, just like you're already doing with ant-contrib. Change your <project> element like this:

<project name="GroovyMem" default="all"
         xmlns:antc="antlib:net.sf.antcontrib"
         xmlns:groovy="antlib:org.codehaus.groovy">

Then delete all of the <taskdef>s, and refer to the Groovy tasks using the namespace prefix:

   <target name="run_groovy">
            <groovy:groovy>
               // do nothing
            </groovy:groovy>               
   </target>

Note that you will have to add Groovy to Ant's runtime classpath. My preferred way to do this is with the "-lib" command-line option.