Since the introduction of JLink (maybe a bit later) it is possible to put jar libraries inside the directory-structure of packages. If this package is installed in one of the places Mathematica searches, the jar libraries are automatically found by JLink.
The problem is that under 64 bit Windows XP, after loading JLink these files are locked and cannot be removed from within Mathematica, although none of the jars are really used, but only added to the class-path of Java.
Let me give a short example: Place a Test folder with Java subfolder inside your $UserAddOnsDirectory and copy any jar file into the Java folder. This looks like
Test/
└── Java
└── blub.jar
When you now start a fresh Kernel and load <<JLink` you can verify by looking at JavaClassPath[], that this directory and the jar was indeed added to the class-path. When you try to remove the complete folder, you get (a misleading) error message
DeleteDirectory[path, DeleteContents -> True]
(*
DeleteDirectory::dirne: Directory D:\Documents and Settings\mscheibe\
Application Data\Mathematica\Applications\Test not empty. >>
*)
After Quit-ing the kernel, calling UninstallJava[] or JLink`QuitJava[] the directory can be removed. This behavior does not occur in Linux or on MacOSX and I could only test it on Windows XP 64 bit.
Question: Why, if the jar-path is only appended to the class-path, does JLink lock the files as they where opened for reading? Why does this happen on Windows only? Is there anyone, who has a deeper insight into JLink who can suggest a better solution that calling JLink`QuitJava[]; Pause[2]; inside my module when I want to remove a jar-file found by Mathematica.
Remark 1: This behavior is not restricted to automatically found jars. When you use java-code by manually adding a jar with AddToClassPath[path] the similar thing happens.
Remark 2: I forgot to mention, that JLink`QuitJava[] does not really quit java like Quit would kill the kernel. Meaning, I call this and without doing anything else I can still call my functions inside the jars. This seems to suggest, that QuitJava[] kills the class-loader instance Leonid is mentioning which locks the files. But a call to e.g. JavaNew seems to set up everything correct again.
QuitJava. Does this mean that, when I have a few million jars in my search-path, JLink` opens and maybe loads every jar at startup instead of adding it to the search path? Does java has to preload jars or could it just start loading, when a symbol cannot be resolved? – halirutan Feb 07 '12 at 10:34URLClassloader(well, its J/Link subclass) created by JLink. In the JDK7, a new methodclosehas been added to it, so I suppose it can be used explicitly from JLink/Mathematica, when you are done loading classes. Then, if you need to load more, you create a new instance. Something like that may work, but for that a full understanding of the process may be needed. – Leonid Shifrin Feb 07 '12 at 10:59JLinkClassloaderclass, making a fieldhelper(of typeJLinkClassLoaderHelper) public (it is protected inJLinkClassloader, which creates a singleton). 2. Work directly with theKernelLink.javaclass, which has a methodsetClassLoader: create an instance ofKernelLink, and then set as the classloader the subclass I mentioned. 3. When needed, access the fieldhelperof this subclass, and callclose()on it. Then replace it with a new instance of the helper. No idea if this works though. – Leonid Shifrin Feb 07 '12 at 11:09