ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Kerns, Bob" <Bob.Ke...@firepond.com>
Subject RE: [PATCH] build listener class loading
Date Mon, 31 Dec 2001 10:31:35 GMT
I was sort of wondering why these cleanups exist. It looks to me like
perhaps there's some premature optimization going on here, and some
poorly-allocated division of responsibility.

While closing the zipfiles is certainly important, that's a cache; it'll
reopen as necessary. But clearing out project & pathComponents? I'm guessing
that's the proximal cause of the "unusuable state" you find the loader in --
unnecessary "optimization" as far as I can tell.

And why isn't the creator of the AntClassLoader responsible for cleaning it
up? e.g., refactoring the code in Launcher.java:

    protected AntClassLoader getClassLoader(ClassLoader systemClassLoader,
File antHome) {
        // We now create the class loader with which we are going to launch
ant
        AntClassLoader antLoader = new AntClassLoader(systemClassLoader,
false);

        // need to find tools.jar
        addToolsJar(antLoader);        
        
        // add everything in the lib directory to this classloader
        File libDir = new File(antHome, "lib");
        addDirJars(antLoader, libDir);
        
        File optionalDir = new File(antHome, "lib/optional");
        addDirJars(antLoader, optionalDir);
        return antLoader;
    }

    protected File findAntHome(ClassLoader systemClassLoader) {
        if (systemClassLoader == null) {
            antHome = determineAntHome11();
        }
        else {
            antHome = determineAntHome(systemClassLoader);
        }
        if (antHome == null) {
            System.err.println("Unable to determine ANT_HOME");
            System.exit(1);
        }
    
        System.out.println("ANT_HOME is " + antHome);
        return antHome;
    }

    public static void main(String[] args) {
        ClassLoader systemClassLoader = Launcher.class.getClassLoader();
        File antHome = findAntHome(systemClassLoader);

        Properties launchProperties = new Properties();
        launchProperties.put("ant.home", antHome.getAbsolutePath());        
        
        AntClassLoader antLoader = getClassLoader(systemClassLoader,
antHome);
        try {
            Class mainClass =
antLoader.loadClass("org.apache.tools.ant.Main");
            antLoader.initializeClass(mainClass);
            
            final Class[] param = {Class.forName("[Ljava.lang.String;"),
                                   Properties.class, ClassLoader.class};
            final Method startMethod = mainClass.getMethod("start", param);
            final Object[] argument = {args, launchProperties,
systemClassLoader};
            startMethod.invoke(null, argument);
        }
        catch (Exception e) {
            System.out.println("Exception running Ant: " +
e.getClass().getName() + ": " + e.getMessage());
            e.printStackTrace();
        }
        finally {
            antLoader.cleanup(); // I would call this 'close()'
        }
    }

I can find even less justification for the IntrospectionHelper's use of this
event. Wouldn't it be simpler to just move the
IntrospectionHelper.getHelper() method to Project as a non-static? And thus
have IntrospectionHelper.helpers be an instance field of Project, and thus
be GC'd when the Project is GC'd?

All this manual managing of resources makes me queasy -- and apparently
leads to bugs.

-----Original Message-----
From: Adam Murdoch [mailto:adammurdoch_ml@yahoo.com]
Sent: Saturday, December 29, 2001 4:02 PM
To: ant-dev@jakarta.apache.org
Subject: [PATCH] build listener class loading



Hi,

This patch fixes an odd class loading problem, where the classes used by a
BuildListener's buildFinished() method cannot be loaded.  This is how the
problem happens:

- The task is loaded via an AntClassLoader (e.g. using <taskdef> with a
classpath specified).

- The AntClassLoader adds a BuildListener to the project, so that it can
clean up when the build finishes.

- When the task executes, it adds a BuildListener to its project.

- The build finishes, and a build finished event is fired.

- The AntClassLoader's buildFinished() method is called.  The class loader
cleans itself up.

- The task's buildFinished() method is called.  If this method uses classes
which have not been loaded, the AntClassLoader's findClass() method is
called.

- The AntClassLoader is in an unusable state, and a NPE is thrown.

This patch defers AntClassLoader (and IntrospectionHelper) cleanup until
after the build finished event has been handled by all build listeners.


Adam

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message