On Oct 13, 2008, at 12:33 PM, Adam Murdoch wrote:
Adam Murdoch wrote:
Hans Dockter wrote:
On Sep 27, 2008, at 11:16 AM, Hans Dockter wrote:
On Sep 27, 2008, at 1:34 AM, Adam Murdoch wrote:
Hi,
I've run across an interesting problem in the classloader
isolation stuff for groovy compilation.
The symptom is, when I change the constructor of a java class
which a groovy class extends, then compilation fails,
complaining that the java class does not have the old
constructor. For example, when I removed the dag parameter from
DefaultTask and updated the groovy tasks, I got lots of
compilation failures complaining that constructor DefaultTask
(project, name, dag) did not exist, even though everything had
been updated to use the constructor.
I have run into this problem once before when I have tried to
refactor the exception hierarchy. I thought it was a bug in
groovyc.
Digging a little, I found that if I excluded gradle*.jar from
the classpath used to build the isolated classloader in
GradleUtil.executeIsolatedAntScript() then everything compiled
fine. It appears that groovyc is picking up the old classes
from its classloader, rather than from the source it is given.
However, when I removed gradle from the classloader, I also had
to remove the ant logging adapter from the isolated ant build.
This makes a lot of sense to me now that you are pointing this out.
I have filed an issue: http://jira.codehaus.org/browse/GRADLE-246
This has bitten me again. I had to upload a new wrapper
distribution as a work around.
It bit me a couple of times over the weekend too. I ended up
rolling back some changes rather than update the wrapper. It's
become really annoying. I'm going to have a go at fixing this.
One potential solution is to rearrange the classloader hierarchy
somewhat so that ant is in a parent of the build classloader,
something like:
1 - system classloader
2 - classloader: ant
3 - classloader: shared stuff: logging, groovy, gradle api, ivy
4 - classloader: build (as defined in settings file)
5 - classloader: gradle impl
Or a simpler one:
1 - system classloader
2 - classloader: ant
3 - classloader: everything else
This means that all ant taskdefs are going to get a clean classpath
(not just the groovyc task), and since the ant classloader is
visible to the gradle impl, we can swap our ant logging bridge
without reflection.
I like the simple solution for now, as it looks easy to integrate
into our current flow. Then we should discuss which approach we are
going to take for modularization (multi-project build for Gradle,
OSGi, Classloader isolation, ...).
There is one wart I have left in the code which might be confusing.
BaseSettings.createClassLoader returns a classloader that is used for
evaluating the build script. But what it returns, is the URL context
classloader that would be used anyhow for evaluating the script. The
createClassLoader method adds also jars to the classpath of this URL
context classloader. The reason for this behavior was, that after I
had implemented the classloader isolation for build scripts, there
was some discusson about keeping classloading simple. As a result I
have changed the behavior in the way as described above. But I didn't
wanted to throw away all the functionality for isolation immediately.
I'm not saying that this was best practices :)
- Hans
--
Hans Dockter
Gradle Project lead
http://www.gradle.org
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email