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:[EMAIL PROTECTED]
> 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: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]