ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Rainer Noack" <rai...@noacks.net>
Subject RE: custom classloader for a task
Date Wed, 31 Aug 2005 22:52:18 GMT
Hi Jochen,

unfortunately, the displayed delegation hierarchy is typically not correct.
oata.AntClassLoader allways returns the System Classloader (class
sun.misc.Launcher$AppClassLoader) as its
parent.
See http://issues.apache.org/bugzilla/show_bug.cgi?id=35436
 
If you run ant from it's shell script you will have typically the following
delegation hierarchy:
* class org.apache.tools.ant.AntClassLoader (loads a task explicitely
defined by taskdef, contains the jars/dirs defined in taskdefs classpath
argument)
* class java.net.URLClassLoader   (created by Launcher, Classloader of
oata.Project, default tasks and most of the other ant stuff; typically
contains your classpath, the jars in $ANT_HOME/lib and the jdk's tools.jar)
* class sun.misc.Launcher$AppClassLoader (known as System-, Application- or
User- Classloader, that only loads the oata.launch.* classes, normally only
contains ant-launcher.jar)
* class sun.misc.Launcher$ExtClassLoader (Extension classloader, typically
contains the jars in $JRE_HOME/lib/ext)
* null (bootstrap classloader for all the jdk stuff, typically contains the
jars in $JRE_HOME/lib resp. $JDK_HOME/lib)

To find out the delegation hierarchy in maven you have to change your code
to something like this (not clean but should work, assumed your task extends
oata.Task):

public void execute() throws BuildException {
    ClassLoader loader = this.getClass().getClassLoader();
    if (loader instanceof AntClassLoader) {
        System.out.println(loader.getClass());
        loader = getProject().getCoreloader();
        if (loader == null)
            loader = Project.class.getClassLoader();
    }
    while (loader!=null) {
        System.out.println(loader.getClass());
        loader = loader.getParent();
    }
}

In the next weeks, I will publish a new patch (and a ready-to-use trial
version) for the proposed <classloader> and <classloaderreport> task (see
http://issues.apache.org/bugzilla/show_bug.cgi?id=28228) that gives a more
common 
solution for this problem.

Once knowing the environment's delegation hierarchy you have to decide
whether it is really possible to create a consistent second delegation
hierarchy for the conflicting jars or not. (This could be done by the
proposed <classloader> task).

However, if you want to run your task in very different environments (in
terms of classloading), I think forking is the cleanest solution. (BTW,
forking of compile tasks is IMHO mostly allways the best solution).

Cheers

Rainer

> -----Original Message-----
> From: Jochen Theodorou [mailto:blackdrag@gmx.org] 
> Sent: Tuesday, August 30, 2005 10:49 AM
> To: Ant Users List
> Subject: Re: custom classloader for a task
> 
> 
> Conor MacNeill schrieb:
> 
> > 
> > Jochen Theodorou wrote:
> > 
> >>Hi all,
> >>
> >>Te problem I have is a little complex but I hope you can help me. 
> >>Groovy has an ant task to compile groovy classes and a task to use 
> >>groovy from within ant see 
> http://groovy.codehaus.org/Groovy+Ant+Task 
> >>for details. But in some enviroments such as in maven with certain 
> >>plugins we have conflicting jars. I mean jars of a 
> different version 
> >>than needed by groovy. For example antlr or asm.
> >>
> >>Our current workaround for the compile task (groovyc) is to 
> fork the 
> >>VM. But this can't be the solution? I mean isn't there a 
> possibility 
> >>to load a task through a custom classloader? It's no 
> problem for me to 
> >>write such a loader, but where to wire it in? I know about the 
> >>loaderref attribute, but as far as I understand this 
> attribute is for 
> >>reusing a classloader. A normal classloader can't be used since a 
> >>normal classloader looks for a class first in the parent and if the 
> >>parent knows the conflicting jar/class then we have the 
> same problem 
> >>as before.
> > 
> > Since you are passing a classpath to the taskdef above, Ant will 
> > create a classloader to load this task's classes. What classes this 
> > classloader can see will depend on the classloader hierarchy under 
> > Maven. I have no idea what that will be.
> 
> classloader hirarchy for the task class without loaderref:
> 
> class org.apache.tools.ant.AntClassLoader
> class sun.misc.Launcher$AppClassLoader
> class sun.misc.Launcher$ExtClassLoader
> 
> printed by a task:
> 
>      public void execute() throws BuildException {
>          ClassLoader loader = this.getClass().getClassLoader();
>          while (loader!=null) {
>              System.out.println(loader.getClass());
>              loader = loader.getParent();
>          }
>      }
> 
> so it seems maven does not change the hirarchy...
> 
> > It is possible to specify a reverseloader="true" attribute 
> on an Ant 
> > taskdef. It is highly deprecated, unsupported, bad things 
> happen, etc. 
> > It will cause the classloader to consult it's jars first, 
> before those 
> > of its parent.
> 
> well, reverseloader=true might be the thing I am searching for, and a 
> test shows it works then... But these deprecated warnings are 
> annoying. 
> No way to work around this problem?
> 
> >>I heard that when you do loaderref="root" in a maven 
> project you get 
> >>the ant-loader, but that will be no help if the normal classpath 
> >>contains a conflicting jar for another task. Maybe someone 
> can explain 
> >>me if a classpath from a taskdef is added to the loader reffered by 
> >>loaderref. If so the ant-loader will be polluted too.
> > 
> > No, this does not happen - loaderref and classpath are exclusive, I 
> > think.
> 
> my tests are showing that with a loaderref I hae a different 
> AntClassLoader, than the normal Classloader, but I have still the 
> conflicting jar. When I enable reverseloader, then it's ok. 
> So the new 
> Loader has to share some classpath parts with the normal antloader 
> somewhere, because I am sure the sun.misc.Launcher does not caontain 
> that jar.
> 
> by blackdrag
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
> For additional commands, e-mail: user-help@ant.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
For additional commands, e-mail: user-help@ant.apache.org


Mime
View raw message