mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 01:19:28 +01:00
5fa04d36712e239a0daf9d59be133ff53449f8f6
Shortly said, we don't need to handle recursive invocations of the `java.io` to nio adapters, while this recursion leads to problems. # Problem Since we're not allowed to modify public API of Java classes, an unreliable workaround `IoOverNio.PARENT_FOR_FILE_CHANNEL_IMPL` had been introduced. This trick lets us pass some object into a called function without adding a new function argument. The trick backfired at the following code: ```java // at java.base/java.io.IoOverNioFileSystem.initializeStreamUsingNio (simplified code) IoOverNio.PARENT_FOR_FILE_CHANNEL_IMPL.set(owner); return initializeStreamsUsingNio0(owner, nioFs, file, nioPath, optionsForChannel, channelCleanable); // at java.base/java.io.IoOverNioFileSystem.initializeStreamsUsingNio0 channel = nioFs.provider().newFileChannel(nioPath, optionsForChannel); ``` The intention of setting `PARENT_FOR_FILE_CHANNEL_IMPL` is to path `owner` inside a constructor of `sun.nio.ch.FileChannelImpl` which may be called by `newFileChannel(nioPath, optionsForChannel)`. The implementation of `newFileChannel` in IntelliJ triggered class loading. The classloader of IntelliJ triggered the call `java.nio.file.Files.readAllBytes`. The latter code also invoked the constructor of `FileChannelImpl`, and the constructor got from the thread-local variable the value for the field `parent`. That value was supposed to be passed to a different invocation of the constructor. The observable result of this bug was a `NullPointerExceptions` from `java.io.FileOutputStream.close`. Hypothetically, this bug could also lead to closing file descriptors earlier as expected in other unpredictable places. # Rejected approaches * The cleanest solution could be passing specific function arguments through function arguments. However, we may neither create a new public function in the module `java.base`, nor add an argument to an existing one. Thus, we have to keep dealing with thread-local variables. * To hold several values in the thread-local variable. In this case, the constructor of `FileChannelImpl` should somehow choose the right value from the list. The only possible way for filtering values is by the provided path. It doesn't look like a performant and reliable solution. # Chosen solution This commit disables recursive invocations of `java.io` from `java.nio` adapters. The chosen solution is tied to specifics of IntelliJ. The reason for introducing java.io over java.nio adapter was to be able to access files from remote machines without rewriting old code. It is not expected that an implementation of `java.nio.file.spi.FileSystemProvider` accesses the file system using `java.io`. The only imaginable way to get a `java.io` call from `java.nio` is class loading. In case of IntelliJ, it's assumed that the class loader never accesses classes and jars from a remote machine.
…
Welcome to the JDK!
For build instructions please see the online documentation, or either of these files:
- doc/building.html (html version)
- doc/building.md (markdown version)
See https://openjdk.org/ for more information about the OpenJDK Community and the JDK and see https://bugs.openjdk.org for JDK issue tracking.
Languages
Java
73.7%
C++
14%
C
8.1%
Assembly
2.7%
Objective-C
0.5%
Other
0.8%