You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Max Rydahl Andersen <ma...@jboss.com> on 2005/06/18 23:44:15 UTC
ant tasks creation of classloaders
Hi guys,
Having some "fun" issues with classloading these days.
I have a task (HibernateTool) that is used like this:
<taskdef name="hibernatetool"
classname="org.hibernate.tool.ant.HibernateToolTask">
<classpath path="[necessary hibernate libs]">
</taskdef>
<target name="exportddl" depends="compiletest" description="Export the
DDL to caveatemptor.ddl and DB">
<hibernatetool destdir="${build.dir}">
<classpath path="etc;${build.dir}/classes"/>
<annotationconfiguration
configurationfile="${classes.dir}/hibernate.cfg.xml"/>
<hbm2ddl export="false" console="false" drop="false"
create="true" outputfilename="caveatemptor.ddl" delimiter=";"/>
</hibernatetool>
</target>
Notice that the classpath of the taskdef and hibernatetool have no
overlaps.
Until today I had the following code in the HibernateToolTask for creating
the classloader:
AntClassLoader loader = getProject().createClassLoader(classPath);
loader.setParent(getProject().getCoreLoader());
loader.setThreadContextLoader();
But when I run this stuff with the task above I get ClassNotFoundErrors
for annotations defined in hibernate.
This occurs because with the above classloader setup I effectively goes
around the <taskdef> classpath - it
will instead first look in the parent of the AntClassLoader I created and
this will be the system classloader which
of course know nothing about the hibernate specific classloaders.
Know my current work around for this is to do:
AntClassLoader loader = getProject().createClassLoader(classPath);
loader.setParent(this.getClass().getClassLoader()); <-- this is the
HibernateToolTask instance
loader.setThreadContextLoader();
This will setup the right classloading sequence.
But i'm just curious of why this does not seem to be the default way of
doing things in the existing ant tasks ?
e.g. in LoadProperties is:
ClassLoader cL = (classpath != null)
? getProject().createClassLoader(classpath)
: LoadProperties.class.getClassLoader();
which for me says "ignore LoadProperties own classloader if i have a
<classpath>"
and most other places they *only* uses the core task loader which for me
seems kinda strange (as it can give funny
sideeffects if not all classes used by the <taskdef> isn't loaded yet)
So, am I missing some crucial insight or is it just "random" how the
current ant tasks setup their classloaders :) ?
Anyone which can think up any bad things with the classloader setup I did
here ?
/max
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org
RE: ant tasks creation of classloaders
Posted by Rainer Noack <ra...@noacks.net>.
> -----Original Message-----
> From: Max Rydahl Andersen [mailto:max.andersen@jboss.com]
> Sent: Monday, June 20, 2005 7:42 AM
> To: rainer@noacks.net; 'Ant Developers List'
> Subject: Re: ant tasks creation of classloaders
>
>
>
> > If you want your "local" classloader a childloader of the task's
> > loader
> > you
> > should - as of less classpath overhead - simply code
> > new URLClassloader(this.getClass().getClassloader(),localClasspath)
> > (and set it as ThreadContextClassloader) unless you want to
> support
> > things
> > like "isolate"...
>
> Is "isolate" what you call setParentFirst(false) ?
Yep.
>
> > Hope that helps a little bit
>
> It did. So, the short answer to my initial question is: Yes,
> its ok to use the tasks own classloader even though not many
> other tasks dod it ;)
>
> /max
>
> > Cheers
> >
> > Rainer
> >
> >> -----Original Message-----
> >> From: Max Rydahl Andersen [mailto:max.andersen@jboss.com]
> >> Sent: Saturday, June 18, 2005 11:44 PM
> >> To: dev@ant.apache.org
> >> Subject: ant tasks creation of classloaders
> >>
> >>
> >> Hi guys,
> >>
> >> Having some "fun" issues with classloading these days.
> >>
> >> I have a task (HibernateTool) that is used like this:
> >>
> >> <taskdef name="hibernatetool"
> >> classname="org.hibernate.tool.ant.HibernateToolTask">
> >> <classpath path="[necessary hibernate libs]">
> >> </taskdef>
> >>
> >>
> >> <target name="exportddl" depends="compiletest"
> description="Export
> >> the DDL to caveatemptor.ddl and DB">
> >> <hibernatetool destdir="${build.dir}">
> >> <classpath path="etc;${build.dir}/classes"/>
> >> <annotationconfiguration
> >> configurationfile="${classes.dir}/hibernate.cfg.xml"/>
> >> <hbm2ddl export="false" console="false" drop="false"
> >> create="true" outputfilename="caveatemptor.ddl" delimiter=";"/>
> >> </hibernatetool>
> >> </target>
> >>
> >>
> >> Notice that the classpath of the taskdef and hibernatetool have no
> >> overlaps.
> >>
> >> Until today I had the following code in the HibernateToolTask for
> >> creating the classloader:
> >>
> >> AntClassLoader loader = getProject().createClassLoader(classPath);
> >> loader.setParent(getProject().getCoreLoader());
> >> loader.setThreadContextLoader();
> >>
> >> But when I run this stuff with the task above I get
> >> ClassNotFoundErrors for annotations defined in hibernate.
> >>
> >> This occurs because with the above classloader setup I effectively
> >> goes around the <taskdef> classpath - it
> >> will instead first look in the parent of the AntClassLoader I
> >> created and
> >> this will be the system classloader which
> >> of course know nothing about the hibernate specific classloaders.
> >>
> >> Know my current work around for this is to do:
> >>
> >> AntClassLoader loader = getProject().createClassLoader(classPath);
> >> loader.setParent(this.getClass().getClassLoader()); <--
> this is the
> >> HibernateToolTask instance
> >> loader.setThreadContextLoader();
> >>
> >> This will setup the right classloading sequence.
> >>
> >> But i'm just curious of why this does not seem to be the
> default way
> >> of doing things in the existing ant tasks ?
> >>
> >> e.g. in LoadProperties is:
> >> ClassLoader cL = (classpath != null)
> >> ? getProject().createClassLoader(classpath)
> >> : LoadProperties.class.getClassLoader();
> >>
> >> which for me says "ignore LoadProperties own classloader
> if i have a
> >> <classpath>"
> >>
> >> and most other places they *only* uses the core task
> loader which for
> >> me seems kinda strange (as it can give funny
> >> sideeffects if not all classes used by the <taskdef> isn't
> loaded yet)
> >>
> >> So, am I missing some crucial insight or is it just
> "random" how the
> >> current ant tasks setup their classloaders :) ?
> >>
> >> Anyone which can think up any bad things with the
> classloader setup I
> >> did here ?
> >>
> >> /max
> >>
> >>
> >>
> >>
> >>
> >>
> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
> >> For additional commands, e-mail: dev-help@ant.apache.org
> >>
> >
> >
> >
> ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
> > For additional commands, e-mail: dev-help@ant.apache.org
> >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
> For additional commands, e-mail: dev-help@ant.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org
Re: ant tasks creation of classloaders
Posted by Max Rydahl Andersen <ma...@jboss.com>.
> If you want your "local" classloader a childloader of the task's loader
> you
> should - as of less classpath overhead - simply code
> new URLClassloader(this.getClass().getClassloader(),localClasspath)
> (and set it as ThreadContextClassloader) unless you want to support
> things
> like "isolate"...
Is "isolate" what you call setParentFirst(false) ?
> Hope that helps a little bit
It did. So, the short answer to my initial question is: Yes, its ok to use
the tasks own classloader even though not many other tasks dod it ;)
/max
> Cheers
>
> Rainer
>
>> -----Original Message-----
>> From: Max Rydahl Andersen [mailto:max.andersen@jboss.com]
>> Sent: Saturday, June 18, 2005 11:44 PM
>> To: dev@ant.apache.org
>> Subject: ant tasks creation of classloaders
>>
>>
>> Hi guys,
>>
>> Having some "fun" issues with classloading these days.
>>
>> I have a task (HibernateTool) that is used like this:
>>
>> <taskdef name="hibernatetool"
>> classname="org.hibernate.tool.ant.HibernateToolTask">
>> <classpath path="[necessary hibernate libs]">
>> </taskdef>
>>
>>
>> <target name="exportddl" depends="compiletest"
>> description="Export the
>> DDL to caveatemptor.ddl and DB">
>> <hibernatetool destdir="${build.dir}">
>> <classpath path="etc;${build.dir}/classes"/>
>> <annotationconfiguration
>> configurationfile="${classes.dir}/hibernate.cfg.xml"/>
>> <hbm2ddl export="false" console="false" drop="false"
>> create="true" outputfilename="caveatemptor.ddl" delimiter=";"/>
>> </hibernatetool>
>> </target>
>>
>>
>> Notice that the classpath of the taskdef and hibernatetool have no
>> overlaps.
>>
>> Until today I had the following code in the HibernateToolTask
>> for creating
>> the classloader:
>>
>> AntClassLoader loader = getProject().createClassLoader(classPath);
>> loader.setParent(getProject().getCoreLoader());
>> loader.setThreadContextLoader();
>>
>> But when I run this stuff with the task above I get
>> ClassNotFoundErrors
>> for annotations defined in hibernate.
>>
>> This occurs because with the above classloader setup I
>> effectively goes
>> around the <taskdef> classpath - it
>> will instead first look in the parent of the AntClassLoader I
>> created and
>> this will be the system classloader which
>> of course know nothing about the hibernate specific classloaders.
>>
>> Know my current work around for this is to do:
>>
>> AntClassLoader loader = getProject().createClassLoader(classPath);
>> loader.setParent(this.getClass().getClassLoader()); <-- this is the
>> HibernateToolTask instance
>> loader.setThreadContextLoader();
>>
>> This will setup the right classloading sequence.
>>
>> But i'm just curious of why this does not seem to be the
>> default way of
>> doing things in the existing ant tasks ?
>>
>> e.g. in LoadProperties is:
>> ClassLoader cL = (classpath != null)
>> ? getProject().createClassLoader(classpath)
>> : LoadProperties.class.getClassLoader();
>>
>> which for me says "ignore LoadProperties own classloader if i have a
>> <classpath>"
>>
>> and most other places they *only* uses the core task loader
>> which for me
>> seems kinda strange (as it can give funny
>> sideeffects if not all classes used by the <taskdef> isn't loaded yet)
>>
>> So, am I missing some crucial insight or is it just "random" how the
>> current ant tasks setup their classloaders :) ?
>>
>> Anyone which can think up any bad things with the classloader
>> setup I did
>> here ?
>>
>> /max
>>
>>
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
>> For additional commands, e-mail: dev-help@ant.apache.org
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
> For additional commands, e-mail: dev-help@ant.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org
RE: ant tasks creation of classloaders
Posted by Rainer Noack <ra...@noacks.net>.
Hi Max,
not surprising.
getProject().createClassLoader(classPath) creates a new AntClassLoader with
the given classpath and set CoreLoader (which is usually null) as it's
parent(Same as <taskdef ... classpath="..."/>).
AntClassLoader uses System.getClassloader() as it's default parent unless
you set another parent loader explicitely.
So you have initially two parallel child loaders of the system loader.
If you want your "local" classloader a childloader of the task's loader you
should - as of less classpath overhead - simply code
new URLClassloader(this.getClass().getClassloader(),localClasspath)
(and set it as ThreadContextClassloader) unless you want to support things
like "isolate"...
LoadProperties checks, whether it needs to set up a new classloader or can
use it's own classloader which is ant's project classloader (normally also a
child of system loader). (Creating an AntClassloader implicitely adds the
lib jars to this classloader.)
CoreLoader is a relict. It's not really used in ant itself but supported by
most classloader creations. Maybe it is used by some IDEs or other
frameworks. (I don't know any example.)
Hope that helps a little bit
Cheers
Rainer
> -----Original Message-----
> From: Max Rydahl Andersen [mailto:max.andersen@jboss.com]
> Sent: Saturday, June 18, 2005 11:44 PM
> To: dev@ant.apache.org
> Subject: ant tasks creation of classloaders
>
>
> Hi guys,
>
> Having some "fun" issues with classloading these days.
>
> I have a task (HibernateTool) that is used like this:
>
> <taskdef name="hibernatetool"
> classname="org.hibernate.tool.ant.HibernateToolTask">
> <classpath path="[necessary hibernate libs]">
> </taskdef>
>
>
> <target name="exportddl" depends="compiletest"
> description="Export the
> DDL to caveatemptor.ddl and DB">
> <hibernatetool destdir="${build.dir}">
> <classpath path="etc;${build.dir}/classes"/>
> <annotationconfiguration
> configurationfile="${classes.dir}/hibernate.cfg.xml"/>
> <hbm2ddl export="false" console="false" drop="false"
> create="true" outputfilename="caveatemptor.ddl" delimiter=";"/>
> </hibernatetool>
> </target>
>
>
> Notice that the classpath of the taskdef and hibernatetool have no
> overlaps.
>
> Until today I had the following code in the HibernateToolTask
> for creating
> the classloader:
>
> AntClassLoader loader = getProject().createClassLoader(classPath);
> loader.setParent(getProject().getCoreLoader());
> loader.setThreadContextLoader();
>
> But when I run this stuff with the task above I get
> ClassNotFoundErrors
> for annotations defined in hibernate.
>
> This occurs because with the above classloader setup I
> effectively goes
> around the <taskdef> classpath - it
> will instead first look in the parent of the AntClassLoader I
> created and
> this will be the system classloader which
> of course know nothing about the hibernate specific classloaders.
>
> Know my current work around for this is to do:
>
> AntClassLoader loader = getProject().createClassLoader(classPath);
> loader.setParent(this.getClass().getClassLoader()); <-- this is the
> HibernateToolTask instance
> loader.setThreadContextLoader();
>
> This will setup the right classloading sequence.
>
> But i'm just curious of why this does not seem to be the
> default way of
> doing things in the existing ant tasks ?
>
> e.g. in LoadProperties is:
> ClassLoader cL = (classpath != null)
> ? getProject().createClassLoader(classpath)
> : LoadProperties.class.getClassLoader();
>
> which for me says "ignore LoadProperties own classloader if i have a
> <classpath>"
>
> and most other places they *only* uses the core task loader
> which for me
> seems kinda strange (as it can give funny
> sideeffects if not all classes used by the <taskdef> isn't loaded yet)
>
> So, am I missing some crucial insight or is it just "random" how the
> current ant tasks setup their classloaders :) ?
>
> Anyone which can think up any bad things with the classloader
> setup I did
> here ?
>
> /max
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
> For additional commands, e-mail: dev-help@ant.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org