This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 48466 - project distribution jar being locked, and not released until restart
Summary: project distribution jar being locked, and not released until restart
Status: RESOLVED FIXED
Alias: None
Product: java
Classification: Unclassified
Component: Unsupported (show other bugs)
Version: 4.x
Hardware: PC Windows XP
: P1 blocker (vote)
Assignee: _ tball
URL:
Keywords:
Depends on:
Blocks: 46415
  Show dependency tree
 
Reported: 2004-09-03 16:28 UTC by gc
Modified: 2007-09-26 09:14 UTC (History)
6 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Possible diff - please test (6.33 KB, patch)
2004-09-03 20:48 UTC, Jesse Glick
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description gc 2004-09-03 16:28:23 UTC
This is a showstopping bug for j2me code-freeze on
Sept 8th, 2004.  

It appears to be mdr related, but my appologies if
it ends up being something we're doing wrong.

Steps to reproduce:
-Open new j2me project with midlet
-build project
-make some compile error, wait for error
annotation to appear.  
-fix compile error, wait for annotation to dissapear
-clean&build project

The distribution jar will be locked.

----

 Using a debugger and a file lock observing
program, i determined that the lock seems to be
created at the following location (for certain, it
is created somewhere in the "refreshAnnotation()"
method):

System Thread [Error Annotation Queue] (Running)
	File.<init>(String) line: 183
	File.getAbsoluteFile() line: 475
	File.toURI() line: 607
	ArchiveURLMapper.getURL(FileObject, int) line: 64
	URLMapper.findURL(FileObject, int) line: 80
	AbstractFileObject(FileObject).getURL() line: 703
	ECRequestDescImpl.getFileName(FileObject,
StringBuffer) line: 127
	ECRequestDescImpl.getCompileAndSourcePath(ClassPath,
StringBuffer, StringBuffer, Set) line: 98
	ECRequestDescImpl.<init>(ASTProvider,
ErrConsumer) line: 50
	ResourceImpl$ErrorList.initCheck() line: 1167
	ResourceImpl$ErrorList.size() line: 1177
	J2MEEditorSupport(JavaEditor).refreshAnnotations()
line: 373
	JavaEditor.access$200(JavaEditor) line: 69
	JavaEditor$2.run() line: 228
	RequestProcessor$Task(Task).run() line: 136
	RequestProcessor$Task.run() line: 330
	RequestProcessor$Processor.run() line: 686
Comment 1 gc 2004-09-03 17:17:35 UTC
Additional info:
-This problem is not occuring in beta 1.
-The problem does not occur after disabling annotations (by setting
tools->options->java sources->automatic parsing delay = 0)
Comment 2 gc 2004-09-03 17:53:57 UTC
Note that this bug also effects J2SE projects.  
-Create an application project that depends on a library project.  
-Build the library project.
-Trigger the annotation process on the application project
-clean/rebuild the library project will fail.
Comment 3 _ tball 2004-09-03 18:15:38 UTC
I'm not involved with mdr, and hope never to be.
Comment 4 _ tball 2004-09-03 18:21:49 UTC
I'll look into it, since everyone in Prague has probably gone home by
now...
Comment 5 _ tball 2004-09-03 19:16:28 UTC
I cannot reproduce this problem on today's source base.  I created a
J2SE app with a dependency on a library added to the Library Manager,
as Jesse describes.  After invoking the error checker (just type a
character), it works regardless of how I modify the library's
distribution jar file.  I also tried making the library a required
project, with the same (non-)result.

Please attach a real stacktrace of the deadlock, instead of this
incomplete and inaccurate list (for example, File.File() doesn't have
any synchronization).  Also, if you send me a pointer to where your
j2me projects live, I can investigate further.  

I don't think the problem has anything to do with the error checker as
it doesn't synchronize any objects.  My change to use the execute path
instead of the compile path means that the error checker will try to
access those elements returned by a
ClassPath.getClassPath(ClassPath.EXECUTE) instead of
ClassPath.COMPILE, but both should always return paths that are safe
to access.  If your code holds locks on those elements, it needs to
stop doing that.


Comment 6 Jesse Glick 2004-09-03 20:02:46 UTC
Not likely anything to do with MDR. Presumably something in the
parser, and presumably specific to Windows.

I agree that the top of the attached stack is not very helpful, since
the File constructor does not acquire a file lock. On Windows, file
locks on JARs usually occur as a result of someone making (and not
closing) a ZipFile. ArchiveURLMapper will not create such a lock, but
the manner in which it is being called indicates that it has been
passed a FileObject from a JarFileSystem, which may have such a lock.

What does look suspicious to me is
ECRequestDescImpl.getCompileAndSourcePath. It gets a ClassPath.Entry
and then does two things with it:

1. Uses entry.root to get the compilation CP (I guess).

2. Uses entry.url to get source roots.

#2 is fine. But I can't see any justification in #1 for using
entry.root rather than entry.url; in fact getFileName is only going to
use the URL anyway! The only reason to call entry.root would be that
it will return null if the file does not exist, which lets the code
skip the CP entry. But this is an inefficient way to make that check;
getFileName could take the java.io.File and call .exists() to the same
effect.

Now if you get the FileObject for the root of a JAR, that means making
a JarFileSystem, and ArchiveURLMapper holds it softly. Ideally JFS
would not hold a lock on the JAR except when first made (when it needs
to scan entries) or when actually reading an entry, but perhaps it
does anyway - Radek would know. Anyway, this is likely the source of
the problem. ECRDI does not need to go through the Filesystems API for
this piece of code, and it should avoid doing so. (Even if there were
no locking issues, it is inefficient.)

May be the case that this bug only became apparent due to Tom's
changes re. ClassPath.EXECUTE, but it is unlikely that the problem did
not exist before that; would apply to any situation where you are
compiling against a JAR file and subsequently want to delete it.
Comment 7 Jesse Glick 2004-09-03 20:48:36 UTC
Created attachment 17365 [details]
Possible diff - please test
Comment 8 Jesse Glick 2004-09-03 21:11:58 UTC
I made up a testing patch that might correct the problem, by using URL
over FileObject wherever possible. I don't run Windows so I can't
really know. It at least compiles and does not cause me obvious
problems on Linux. Anyone who is able to reproduce this bug, please
check whether the patch cures it.

Please note that I do not work on this module, this is just a guess
what is wrong (and how it should be corrected). Fortunately it seemed
all the suspicious code was relatively well localized to this one Java
source.
Comment 9 gc 2004-09-06 09:00:35 UTC
The patch does not resolve the issue.
Comment 10 Tomas Hurka 2004-09-06 09:39:32 UTC
This problem is caused by the following commit:

java/gjast/libsrc/org/netbeans/lib/gjast/Attic/ASClassReader.java
revision 1.1.2.19
date: 2004/08/12 22:33:53;  author: tball;  state: Exp;  lines: +45 -3
Improved attribution speed by caching jar file contents.

Jar files are hold in private static Map<String,SharedArchive> sharedArchives 

Disabling the cache fixes the problem. Here is the diff:
RCS file: /nbextra/java/gjast/libsrc/org/netbeans/lib/gjast/Attic/ASClassReader.java,v
retrieving revision 1.1.2.21
diff -c -r1.1.2.21 ASClassReader.java
*** ASClassReader.java  2004/08/26 21:10:39     1.1.2.21
--- ASClassReader.java  2004/09/06 08:31:12
***************
*** 85,91 ****
        if (archive == null || file.lastModified() > archive.lastModified) {
            ZipFile zdir = new ZipFile(file);
            archive = new SharedArchive(zdir, file.lastModified());
!           sharedArchives.put(dirname, archive);
        }
        return archive;
      }
--- 85,91 ----
        if (archive == null || file.lastModified() > archive.lastModified) {
            ZipFile zdir = new ZipFile(file);
            archive = new SharedArchive(zdir, file.lastModified());
! //        sharedArchives.put(dirname, archive);
        }
        return archive;
      }

Note that this is not a fix. This is just a prove what caused the problem. Tom has to fix 
it correctly.

I will attach modified gjast.jar as a short-term workaround.

 
Comment 11 Tomas Hurka 2004-09-06 09:43:29 UTC
I am sorry, I cannot attach modified gjast.jar, since it is larger than attachment limit. 
Comment 12 Jesse Glick 2004-09-07 18:24:31 UTC
Note that the patch I attached may be desirable for performance and
robustness reasons whether or not it is needed to fix this problem.
Will leave it at that, was just jumping in because it was a Friday. :-)
Comment 13 _ tball 2004-09-07 18:33:04 UTC
Removed jar caching from ClassReader for beta2.
Comment 14 Jesse Glick 2004-09-09 17:49:54 UTC
*** Issue 48736 has been marked as a duplicate of this issue. ***
Comment 15 Quality Engineering 2007-09-20 09:47:50 UTC
Reorganization of java component