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.
Jesse, could you please implement it as you suggested in #20323? Thanks.
Probably impl: It might be possible in case a module is about to be deleted to create a copy in /tmp (File.createTempFile) of all the JARs the classloader had open, open the copy JARs, close the originals, and switch the JarFile's used internally. Also, if and when the classloader is finalized, close the copy JARs and delete them.
Created attachment 4925 [details] Non-functional patch
I have partially solved this - at least the NB side of things. With the attached patch, the module classloader does not keep an open JarFile for the module after it has been deleted. However it is not enough. As I found out, if a jar: URL is *ever* opened in the VM, private JRE code keeps a hard reference to an open JarFile for that JAR and never releases it! This means that if the module classloader ever serves a request for ClassLoader.getResource (which almost every module will), using a jar: URL, and the module is not marked reloadable, the JAR will not be deletable (or upgradable) in this VM session on Windows. I filed a Java bug, will attach a URL when it is accepted. The new unit test demonstrates the problem. It passes on Unix but fails on Windows. I can think of two possible ways to continue: 1. Do not use jar: URLs. Define and use a custom URL protocol which behaves much like jar: but uses NB-specific knowledge about when a JAR should be closed. After the JAR is closed (e.g. because of ModuleManager.delete), it could be copied to a temp dir to serve old URL connection requests. Pros: safe; we may want to do similar manual rerouting of JAR entry requests in order to implement a fast JAR cache at startup anyway. Cons: some work to implement; duplication of a lot of JRE code. 2. Using reflection, delete entries from JarFileFactory.fileCache when ModuleManager.delete is called, to make sure that no open JarFile is retained. It would still be possible for "zombie" code in a dead classloader to ask for URL resources from the module, but the patched JarClassLoader would serve them from the copy JAR, making it possible to still delete the original. Pros: simple and may be effective. Cons: dangerous call to private impl code, cannot be guaranteed to work in future JDK releases. I will try to solve the problem using #2 for now. If we want to implement JAR caches later for reasons of startup performance, it may be worthwhile to rewrite to code to use style #1.
Java bug: #4646668
OK, using workaround #2 (reflection hack). Seems to work well enough with JDK 1.3.0 and 1.4.0 on Win2000. Also does not seem to hurt anything on Linux with JDK 1.3.1_02 nor 1.4.0 (though the fix is not really necessary on Unix systems anyway). Will commit soon. Ales - note that the JAR locks are released only after the module is really deleted from the ModuleManager pool. They are *not* released after just disabling a module. From Auto Update, you should be able to do this: delete the Modules/*.xml file corresponding to the module; listen for changes in the Lookup result on ModuleInfo and wait for the module to disappear from the list (with some sanity timeout of course); then physically delete the JAR. The same system should work for other JARs associated with the module: declared Class-Path extensions, locale/branding variants, and modules/patches/module-code-name/ patch JARs. Also Ales - please run the usual unit test suite on Windows after I commit (you run Windows, correct?). I ran ModuleManagerTest in isolation on Win2K because I do not have full XTest set up on that partition, but it would be good to make sure everything (esp. the new ModuleManagerTest.testModuleDeletion) passes OK for you as well, especially using JDK 1.3.1. Since reflection is used, it is possible for a random JDK to not have the same impl of jar: URL caching, in which case JarClassLoader will print an exception to the log file, and the fix will be disabled. I found that 1.3.0 seems to have a slightly different impl from 1.3.1 and 1.4.0 - the fileCache field became static.
committed * Up-To-Date 1.8 core/src/org/netbeans/core/modules/JarClassLoader.java committed * Up-To-Date 1.23 core/src/org/netbeans/core/modules/Module.java committed * Up-To-Date 1.25 core/src/org/netbeans/core/modules/ModuleManager.java committed * Up-To-Date 1.15 core/test/unit/src/org/netbeans/core/modules/ModuleManagerTest.java committed * Up-To-Date 1.6 xtest/src/org/netbeans/core/modules/Module.java