ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Peter Reilly" <peter.kitt.rei...@gmail.com>
Subject Re: ant and classloading
Date Tue, 17 Oct 2006 09:44:06 GMT
On 10/17/06, Jacob Kjome <hoju@visi.com> wrote:
>
> Very interesting stuff.  I will definitely use your tasks for my own
> build files.  It would be very nice if your tasks were added to
> Ant-1.7.  Any luck with that so far?
>
> I actually did come up with a solution to my problem, though.  I need
> to be able to add path elements on the fly via the task to the
> current classloader, but make sure it gets cleaned up immediately
> thereafter so subsequent uses of the same classloader have no
> remnants of any changes.  I wrote the following....
>
>          AntClassLoader xmlcLoader = null;
>          String origClasspath = null;
>          try {
>              // Add the user-defined resource path to the current
> classloader so
>              // that XCatalog and DTD resources can be found by XMLC during
>              // compilation.  Store the original classpath so it can be reset.
>              // This avoids pollution of the classpath outside of the current
>              // <xmlc/> task invocation.
>              xmlcLoader = (AntClassLoader) getClass().getClassLoader();
>              origClasspath = xmlcLoader.getClasspath();
>              xmlcLoader.addPathElement(getResourcePath().toString());
>
>              ....
>              ....
>
>              Class clazz = Class.forName(xmlcClassName, true, xmlcLoader);
>
>              ....
>              ....
>
>          } catch (Exception x) {
>              throw new BuildException(x);
>          } finally {
>              if (xmlcLoader != null && origClasspath != null) {
>                  // Restore the original classpath to avoid leaking
> user-defined
>                  // resource path information outside the current invocation of
>                  // the <xmlc/> task.
>                  xmlcLoader.setClassPath(new Path(getProject(),
> origClasspath));
>              }
>          }
>
> Anyone see a problem with this?
The  "xmlcLoader = (AntClassLoader) getClass().getClassLoader();"
may not always be correct - your class may be in $ANT_HOME/lib
or in ~/.ant/lib,
in this case the classloader will be a URLClassLoader.

Peter
>
> Jake
>
> At 03:41 PM 10/16/2006, you wrote:
>  >maybe <classloaderreport> [1] can help you with diagnostics.
>  >
>  >rainer
>  >
>  >[1] http://enitsys.sourceforge.net/ant-classloadertask/
>  >
>  >
>  >
>  >> -----Original Message-----
>  >> From: Jacob Kjome [mailto:hoju@visi.com]
>  >> Sent: Monday, October 16, 2006 10:24 PM
>  >> To: Ant Users List
>  >> Subject: Re: ant and classloading
>  >>
>  >>
>  >> Quoting Peter Reilly <peter.kitt.reilly@gmail.com>:
>  >>
>  >> > On 10/16/06, Jacob Kjome <hoju@visi.com> wrote:
>  >> > >
>  >> > > I'm not sure this is 100% an Ant question, but it is within the
>  >> > > context of
>  >> > Ant.
>  >> > >
>  >> > > In my Ant task, I'm loading up a class using Class.forName() and
>  >> > > pass in a classloader that I would have expected to be
>  >> assigned as
>  >> > > the classloader for the class.  That doesn't seem to be
>  >> the case.
>  >> > > Here's what I'm doing..
>  >> > >
>  >> > >
>  >> > > AntClassLoader customLoader = new
>  >> > > AntClassLoader(getClass().getClassLoader(), true);
>  >> > > customLoader.setClassPath(getResourcePath());
>  >> > >
>  >> > > Class clazz = Class.forName(clazzName, true, customLoader);
>  >> > >
>  >> > >
>  >> >
>  >> System.out.println(customLoader.getResource("org/myorganizatio
>  >> n/resources/my.dtd"));
>  >> > >
>  >> >
>  >> System.out.println(clazz.getClassLoader().getResource("org/myo
>  >rganization/resources/my.dtd"));
>  >> > >
>  >> > >
>  >> > > The DTD resource is found in the first case using the custom
>  >> > > classloader where the user configured the resourcePath
>  >> attribute of
>  >> > > the task, but in the second case when I use the
>  >> classloader of the
>  >> > > class that I just loaded by passing in the custom
>  >> classloader I just
>  >> > > get "null".  The point of this is that the class I am
>  >> loading needs
>  >> > > to look up user-defined resources on the classpath.  With the
>  >> > > System.out lines, I am just testing what my loaded class
>  >> needs to do
>  >> > > further down the line.
>  >> > >
>  >> > > Shouldn't the classloader of the class I just loaded be a
>  >> reference
>  >> > > to that which I passed into Class.forName()?
>  >> >
>  >> > No, Java uses a delegated classloader model. Normally, classloaders
>  >> > search up the hierarchy, starting at the base classloader
>  >> to load a
>  >> > class. The reason for this is that classes are not the same unless
>  >> > they are loaded from the same classloader. To take a simple
>  >> case one
>  >> > would want java.lang.Object to be the same no matter how it
>  >> is loaded.
>  >> >
>  >>
>  >> So, is there a way to add some more classpath information to
>  >> the base classloader that loaded the task?  I have no ability
>  >> to pass a classloader to the code that attempts to load
>  >> configured resources.  The classloader that loads the class
>  >> needs to make this user-defined classpath available.
>  >>
>  >> Come to think of it, can I just cast the classloader to an
>  >> AntClassLoader and add the path to it using
>  >> addPathElement(String)?  I guess I didn't try that yesterday,
>  >> but I'll try it tonight.
>  >>
>  >> Of course, it seems like that might cause side effects for
>  >> later calls to the same task where an added path element from
>  >> one task use would be available for another.
>  >>
>  >> What other way is there?  Would I need to fork a new process
>  >> and define the classpath from the get-go for each call?  I'd
>  >> like to use something less heavyweight, but not have side effects.
>  >>
>  >> Jake
>  >>
>  >> >
>  >> > > This is probably more
>  >> > > of a general classloading question than an Ant question, but I'm
>  >> > > guessing others have had to deal with that here.  I must
>  >> be making a
>  >> > > bad assumption, but it seems like something like this should be
>  >> > > possible.
>  >> > >
>  >> > > My only workaround right now is to add the extra classpath
>  >> > > information to the Task definition classpath.  However,
>  >> that is not
>  >> > > intuitive for task users and a pretty ugly hack.  Is
>  >> there any way
>  >> > > to do this?  I've run into and solved many classloading issues in
>  >> > > the past, but I've never had to deal with this
>  >> specifically.  I have
>  >> > > to imagine someone has solved this problem already.  Care
>  >> to share
>  >> > > the
>  >> > solution?
>  >> > >
>  >> > >
>  >> > > Jake
>  >> > >
>  >> > >
>  >> > >
>  >> --------------------------------------------------------------------
>  >> > > -
>  >> > > 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
>  >> >
>  >>
>  >>
>  >>
>  >>
>  >> ---------------------------------------------------------------------
>  >> 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
>
>
> ---------------------------------------------------------------------
> 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