That approach (passing the `target` dir as agent argument through `-javaagent`) might cause problems for concurrent builds, e.g. a Gradle build which concurrently runs tests with different JDK versions. In that case the agent cannot use a static file name for the bootstrap JAR since the concurrent runs might overwrite each others files. So it would again have to create unique / temp files in that directory. Creating temp files in `target` might be somewhat better than creating them in the OS temp dir, but it is also not so great. Especially if the user does not run `mvn clean ...` / `gradle clean ...` that often, for better build performance.

Have you tried giving each test run its own temp directory?


I assume that would be possible, but it would be even more cumbersome for users of those agent libraries then, and the build config setup needed for this would start getting non-trivial.



So if an agent was able to delete the file passed to `appendToBootstrapClassLoaderSearch`, that might really be the easiest solution for agent implementations.

This amounts to deleting a JAR file on bootstrap class path while the VM is running.

Note that opening the JAR file with FILE_SHARE_DELETE won't address the on Windows. While the delete may appear to work, the semantics are not the same as Unix and there will be an error somewhere else if something attempts to create a new JAR file with the same name.


To clarify and to avoid any misunderstandings: I am not asking for being able to delete the file immediately; instead I am looking for a way to delete the file eventually when the JVM terminates.
My understanding is that the order of actions is currently:

1. Library calls `appendToBootstrapClassLoaderSearch`
2. At some point JVM shutdown begins
3. Shutdown hooks / `File#deleteOnExit` runs
4. JVM closes bootstrap JAR file handle in native code

So if something like DELETE_ON_CLOSE was possible (which in JVM native code acted as if the JarFile was opened with ZipFile.OPEN_DELETE), then when the JVM closes the JAR the file is deleted. From my testing with a dummy JarFile on Windows 11, it seems the file is even deleted if the JVM terminates abnormally, e.g. being killed by the Task Manager (as desired).

I think the case that something else tries to create a JAR with the same file path is also not an issue. This DELETE_ON_CLOSE use case would be opt-in and the agent libraries already create unique temp files (after all the problem is that they cannot get rid of these temp files again), so an accidental collision is quite unlikely.



Actually, maybe part of the problem is that `appendToBootstrapClassLoaderSearch` takes a JarFile in the first place. I guess from a theoretical perspective something like a `Function<String, byte[]>` (but probably as dedicated interface with `throws IOException`) or a JarInputStream would suffice? Though maybe supporting that within the JVM implementation would be difficult?

It would be feasible to have the VM upcall to invoke this function.

The lower level JVMTI AddToBootstrapClassLoaderSearch (Java agents are implemented as a JVMTI agent) is more flexible in that it allows directories to be added too. It might not be terrible to add overloads of the Instrumentation.appendToXXX methods to take a directory. It wouldn't be hard to try that and see if any issues come up.


Adding support for directories might be useful for other use cases, but here it would not help much I think. It would only shift the problem from "how to delete a temp JAR" to "how to delete a temp directory". Maybe deleting the directory would be possible on Windows then, but I suspect then you really run into problems when the JVM code tries to access it (and possibly has accessed it before) and suddenly the directory is gone, e.g. because it was deleted by a shutdown hook.

So some kind of lowest possible abstraction (e.g. an interface similar to `Function<String, byte[]>`, or a `Map<String, byte[]>` if all entries need to be known) would be ideal. Then the user can decide whether they serve the entries from a JarFile, a directory or possibly a different location (e.g. a subset of the enclosing JAR file) or even create them on demand.

Kind regards

Reply via email to