|
Hi,
currently Ant loads all taskdef classes (as defined
in defaults.properties) on startup. This mechanism has at least 3
drawbacks:
-It can take up to one second or longer (if you use
ant for everyday development, you will notice the difference)
-It wastes memory
-It completely lacks descriptive error messages.
For example, if you use <junit>, but junit.jar isn't in your classpath,
you only get a default message telling you something about optional.jar. I've
been puzzled as to why tasks couldn't be loaded more than once.
I would like to submit a patch that solves all
three problems. I also took care to ensure
that the public interface of org.apache.tools.ant.Project is backward
compatible.
-Stefan
Here is the patch against recent CVS (I already
added @author tags for your convenience ;-):
Index:
main/org/apache/tools/ant/Project.java
=================================================================== RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/Project.java,v retrieving revision 1.64 diff -u -r1.64 Project.java --- main/org/apache/tools/ant/Project.java 2001/07/17 12:12:39 1.64 +++ main/org/apache/tools/ant/Project.java 2001/07/21 17:03:14 @@ -68,6 +68,7 @@ * file paths at runtime as well as defining various project properties. * * @author [EMAIL PROTECTED] + * @author Stefan Reich <a href="">[EMAIL PROTECTED]</a> */ public class Project { @@ -101,7 +102,8 @@ private Hashtable references = new Hashtable(); private String defaultTarget; private Hashtable dataClassDefinitions = new Hashtable(); - private Hashtable taskClassDefinitions = new Hashtable(); + private TaskDefinitionHashtable taskClassDefinitions = new TaskDefinitionHashtable(); + private Hashtable targets = new Hashtable(); private Hashtable filters = new Hashtable(); private File baseDir; @@ -114,6 +116,27 @@ /** The system classloader - may be null */ private ClassLoader systemLoader = null; + public static class TaskDefinitionHashtable extends Hashtable { + /** lazily call Class.forName */ + public Object get(Object key) { + Object value = super.get(key); + if (value instanceof String) { + try { + value = Class.forName((String) value); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e.toString()); + } catch (NoClassDefFoundError e) { + throw new RuntimeException(e.toString()); + } + } + return value; + } + + public String getClassName(Object key) { + return (String) super.get(key); + } + } + static { // Determine the Java version by looking at available classes @@ -161,19 +184,23 @@ props.load(in); in.close(); + long startTime = System.currentTimeMillis(); Enumeration enum = props.propertyNames(); while (enum.hasMoreElements()) { String key = (String) enum.nextElement(); String value = props.getProperty(key); - try { + /*try { Class taskClass = Class.forName(value); addTaskDefinition(key, taskClass); } catch (NoClassDefFoundError ncdfe) { // ignore... } catch (ClassNotFoundException cnfe) { // ignore... - } + }*/ + addTaskDefinition(key, value); } + long endTime = System.currentTimeMillis(); + System.out.println("Class loading took "+(endTime-startTime)+" ms"); } catch (IOException ioe) { throw new BuildException("Can't load default task list"); } @@ -367,13 +394,19 @@ log("Detected OS: " + System.getProperty("os.name"), MSG_VERBOSE); } + public void addTaskDefinition(String taskName, String taskClass) { + String msg = " +User task: " + taskName + " " + taskClass; + log(msg, MSG_DEBUG); + taskClassDefinitions.put(taskName, taskClass); + } + public void addTaskDefinition(String taskName, Class taskClass) { String msg = " +User task: " + taskName + " " + taskClass.getName(); log(msg, MSG_DEBUG); taskClassDefinitions.put(taskName, taskClass); } - public Hashtable getTaskDefinitions() { + public TaskDefinitionHashtable getTaskDefinitions() { return taskClassDefinitions; } @@ -445,7 +478,12 @@ } public Task createTask(String taskType) throws BuildException { - Class c = (Class) taskClassDefinitions.get(taskType); + Class c; + try { + c = (Class) taskClassDefinitions.get(taskType); + } catch (RuntimeException e) { + throw new BuildException(e.getMessage()); + } if (c == null) return null; Index: main/org/apache/tools/ant/taskdefs/Ant.java =================================================================== RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Ant.java,v retrieving revision 1.23 diff -u -r1.23 Ant.java --- main/org/apache/tools/ant/taskdefs/Ant.java 2001/07/06 11:57:29 1.23 +++ main/org/apache/tools/ant/taskdefs/Ant.java 2001/07/21 17:03:15 @@ -76,6 +76,7 @@ * * * @author [EMAIL PROTECTED] + * @author Stefan Reich <a href="">[EMAIL PROTECTED]</a> */ public class Ant extends Task { @@ -143,11 +144,11 @@ } } - Hashtable taskdefs = project.getTaskDefinitions(); + Project.TaskDefinitionHashtable taskdefs = project.getTaskDefinitions(); Enumeration et = taskdefs.keys(); while (et.hasMoreElements()) { String taskName = (String) et.nextElement(); - Class taskClass = (Class) taskdefs.get(taskName); + String taskClass = taskdefs.getClassName(taskName); p1.addTaskDefinition(taskName, taskClass); } |
- Re: [PATCH] Lazy task class loading Stefan Reich
- Re: [PATCH] Lazy task class loading Stefan Bodewig
- Re: [PATCH] Lazy task class loading Stefan Reich
- Re: [PATCH] Lazy task class loading Stefan Bodewig
- Re: [PATCH] Lazy task class loading Stefan Reich
- Re: [PATCH] Lazy task class loading Conor MacNeill
- Re: [PATCH] Lazy task class loading Stefan Reich
- RE: [PATCH] Lazy task class loading Paul Kilroy
- Re: [PATCH] Lazy task class loading Stefan Reich
- Re: [PATCH] Lazy task class loading Stefan Bodewig
