Bug 29182 - Jasper locks jar files when compiling JSPs through Ant
Summary: Jasper locks jar files when compiling JSPs through Ant
Status: RESOLVED WONTFIX
Alias: None
Product: Tomcat 5
Classification: Unclassified
Component: Jasper (show other bugs)
Version: 5.0.24
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-05-24 16:53 UTC by Petr Jiricka
Modified: 2004-11-16 19:05 UTC (History)
0 users



Attachments
Test case for this issue (2.01 KB, application/octet-stream)
2004-05-24 16:55 UTC, Petr Jiricka
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Petr Jiricka 2004-05-24 16:53:24 UTC
When using Ant to compile JSPs, Jasper locks jar files, so they can not be
deleted on Windows. I am attaching an application that reproduces this issue. To
use it, do the following:

1. Unpack the zip archive
2. Edit the build.properties file to point to your Tomcat installation
(reproduced with 5.0.24)
3. Run ant (reproduced with 1.6.1) in the root directory of the application

The ant script compiles pages in the application and then tried to delete the
jar files used by the app. Deletion fails.
Comment 1 Petr Jiricka 2004-05-24 16:55:32 UTC
Created attachment 11640 [details]
Test case for this issue
Comment 2 Remy Maucherat 2004-05-24 21:25:16 UTC
Did you check that it's not an Ant or javac issue ? Do you use fork=true ?
Comment 3 Petr Jiricka 2004-05-25 08:54:02 UTC
I don't think this is a Javac or Ant issue - in fact, my testcase does not use
Javac at all. As I wrote privately to Kin-Man, I believe the problem is that
JspC uses URLClassLoader, which is known to lock jar files. When Jasper runs
inside the Catalina container, Catalina's WebappClassLoader is used, so the code
that locks jars is avoided.

But thanks for the hint with fork=true, this actually helped. I replaced the
<taskdef name="jasper2" classname="org.apache.jasper.JspC"> style of calling
Jasper by the <java> task, which allows to fork JspC:

<java classname="org.apache.jasper.JspC"
    fork="true"
    failonerror="true"
>
    <arg value="-uriroot"/>
    <arg value="${basedir}/build/web"/>
    <arg value="-d"/>
    <arg value="${basedir}/build/jsps/src"/>
    <arg value="-die1"/>
    <classpath> 
        <pathelement location="${java.home}/../lib/tools.jar"/> 
        <fileset dir="${tomcat.home}/bin"> 
            <include name="*.jar"/> 
        </fileset> 
        <fileset dir="${tomcat.home}/server/lib"> 
            <include name="*.jar"/> 
        </fileset> 
        <fileset dir="${tomcat.home}/common/lib"> 
            <include name="*.jar"/> 
        </fileset> 
    </classpath> 
</java>

When using the above code, jar files are not locked and my testcase succeeds.
However, I don't much like this solution, because:

- Code that uses <java> is uglier than when you use <taskdef>
- Tomcat documentation recommends the use of <taskdef>, see:
  http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jasper-howto.html

So I would still appreciate if this is fixed.

There is an additional aspect: many current IDEs have some kind of Ant
integrations, and most IDEs run Ant internally, without launching a separate
process. So when JspC locks jar files, these jar files will be locked until the
IDE exits. That's another compelling reason to fix this issue. Thanks.
Comment 4 Yoav Shapira 2004-05-28 00:11:09 UTC
I'm not sure a fix to URLClassLoader to not lock jar files is that easy, even 
if it's desirable.  However, would adding support for the fork attribute to 
the JspC task (and maybe even making fork true by default) be good enough?
Comment 5 Petr Jiricka 2004-05-28 08:38:05 UTC
> I'm not sure a fix to URLClassLoader to not lock jar files is that easy, even 
> if it's desirable.

Agreed. Also, it's desirable to support existing JDKs.

Adding fork attribute to JspC would be sufficient, although I'm not sure if it's
that easy, because:

- You would have to also specify a classpath attribute (or nested element) that
would tell the task what classpath to use when the separate JVM is run
- You would need to capture output from the separate process and somehow
redirect it to the original task's output (Ant output).
- You may want to allow all the attributes that the <java> task has that relate
to JVM parameters, such as jvm, maxmemory, jvmargs, failonerror, or nested
elements jvmarg, sysproperty

Is this (easily) doable?
Comment 6 Yoav Shapira 2004-05-28 14:15:06 UTC
What I had in mind actually was either very simple or complex, depending on how 
you look at it: have org.apache.jasper.JspC extend 
org.apache.tools.ant.taskdefs.Java ;)  That way we get all the attributes of 
that task (classpath, jvmargs, sysproperty, forking, etc.) without having to 
write code for it.  We already have the ant.jar in common/lib, so we won't be 
adding any dependencies.

The complex part might be the testing: I don't know the JspC task well enought 
to comprehensively test it.
Comment 7 Yoav Shapira 2004-07-28 21:12:39 UTC
Tomcat 5.1 will have an antiLockingResources or antiLockingJARs attribute on 
the Host or Context that should address this.  I'm not sure this will be fixed 
in Tomcat 5.0.
Comment 8 Petr Jiricka 2004-07-29 06:49:14 UTC
That would be good, but will the attributes you mention really fix this? JspC
does not use any Catalina code at all, and it does not read server.xml, AFAIK.
This is purely about Jasper code. How exactly will the new attributes affect
this issue? Thanks.
Comment 9 Yoav Shapira 2004-09-02 19:23:31 UTC
Tomcat 5.5 uses the Eclipse JDT compiler by default, hopefully it behaves 
better with regards to resource locking.
Comment 10 Petr Jiricka 2004-09-03 10:12:13 UTC
Yoav, I don't think the usage of JDT will help here, because this is not a Java
compiler issue, as I wrote in my comment on 2004-05-25. The problem occurs in
the JSP -> servlet translation phase, not in the servlet -> class compilation.

Specifically, I believe the problem is in method JspC.initClassLoader(...),
which creates a new URLClassLoader. Using a different classloader that does not
lock jar files (e.g. WebappClassLoader from Catalina) would fix this issue, IMHO.
Comment 11 Remy Maucherat 2004-09-03 10:19:47 UTC
This is really getting ridiculous. -1 for adding workarounds to address broken
implementation in the JVM. (BTW, I never noticed the behavior you describe)
Instead, you should ask your employer to fix *their* bug. Please don't reopen
this report.
Comment 12 Petr Jiricka 2004-09-03 11:35:54 UTC
Remy, I don't understand what's ridiculous about this - this is a legitimate
bug. Let's be constructive, please.

> -1 for adding workarounds to address broken implementation in the JVM.

Doesn't WebappClassLoader already have workarounds to prevent locking jars and
to allow redeployment? There is code in Tomcat that bypasses URLConnection, so
why apply different measures in this case?

Also, I believe Tomcat should strive to work with taday's existing JDKs.

FYI, a bug was submitted against JDK, but it was not resolved:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5041014

> BTW, I never noticed the behavior you describe

Are you saying you are not able to reproduce this usign the test case I submitted?

One practical real-world situation when this may arise is when you run Ant
scripts that compile JSPs in IDEs. IDEs generally run Ant in their own VM; they
don't launch a separate one. So any jars that are locked by jspc will not be
closed after the Ant build completes. Next time you run ant clean (in your IDE),
you hit this bug. And here I am not only talking about NetBeans, Eclipse also
does it this way, I believe.

Comment 13 Remy Maucherat 2004-09-03 12:23:16 UTC
I maintain my -1. Fixing this yould be *etremely* painful. The WCL is a
different solution, for different needs.

There are two workarounds:

a) fork your compilation in a separate VM. You should also be able to do that by
putting the jspc task in a seprate target, and using a java call to run this
target. You acknowledge something similar as a solution, but unfortunately, it
is not clean enough for you. This kind of answer does annoy me greatly, as well
as your insistence at abusing Yoav's time on this issue which should be handled
in the JDK.

b) use the Jasper internals, which will allow you to provide your own
classloader (which I hope, won't lock JARs).
Comment 14 Petr Jiricka 2004-09-03 13:07:15 UTC
I agree these are both possible workarounds. However, they are not quite useful
for end users of Tomcat:

Re. a) This is indeed what we do in NetBeans 4.0. But if we are serious about
it, then it should be at least described in
http://jakarta.apache.org/tomcat/tomcat-5.5-doc/jasper-howto.html

Re. b) An end user of Tomcat is not going to write her own classloader. If we
know this would help, why not include and use such a classloader in Jasper
directly? That way, ALL users will benefit, not just those who are able and
willing to write their own classloader.
Comment 15 Remy Maucherat 2004-09-03 13:17:54 UTC
-1.

BTW, you're definitely not a "regular user", you're embedding Jasper. It's the
same when I'm embedding Eclipse JDT (which is a very good compiler) and
providing it with a classloader (while I could choose to not care and feed it my
classpath using a higher level - and much simpler - interface), because I have
specific needs (and this way, since I assume the compiler would lock its JARs, I
remain in control of the locking - to some extent: Windows sucks).