We have encountered a problem in javac that we would like to
have addressed with some urgency.
The problem involves jarfiles and the closing of such files.
To speed up compilation time for several of our products, a
lot of compilation is done "in process" from ant-scripts, i.e.,
the main-method in javac is called with Method.invoke instead
of spawning out a new process with Runtime.exec.
Problem is with method addJarClassPath in com/sun/tools/javac/util/Paths$Path.
This method looks like this (in b57):
private void addJarClassPath(String jarFileName, boolean warn) {
try {
String jarParent = new File(jarFileName).getParent();
JarFile jar = new JarFile(jarFileName);
Manifest man = jar.getManifest();
if (man == null) return;
Attributes attr = man.getMainAttributes();
if (attr == null) return;
String path = attr.getValue(Attributes.Name.CLASS_PATH);
if (path == null) return;
for (StringTokenizer st = new StringTokenizer(path);
st.hasMoreTokens();) {
String elt = st.nextToken();
if (jarParent != null)
elt = new File(jarParent, elt).toString();
addFile(elt, warn);
}
} catch (IOException e) {
log.error(Position.NOPOS,
"error.reading.file", jarFileName, e);
}
}
This method creates a new JarFile, but does not call close on
it. This means that it relies on finalization to take place
to close the JarFile. Since JarFile is a ZipFile, reading
the javadoc for ZipFile says:
Since the time when GC would invoke this method is undetermined, it is
strongly recommended that applications invoke the close method as soon
they have finished accessing this ZipFile. This will prevent holding up
system resources for an undetermined length of time.
I have attached a test case in a jar: javacbug.jar. Unjar and
read README.txt for instructions.
Note that this problem is not a theoretical one, it is actually
blocking us to some extent and gives us unpredictability in our
builds at the moment.