drain-java icon indicating copy to clipboard operation
drain-java copied to clipboard

Replace JVM file watcher by alternatives that are not affected by filesystems boundaries

Open bric3 opened this issue 4 years ago • 2 comments

The watchservice of the JVM suffers from a few drawbacks regarding its integration with the OS. In Linux in particular events of bind mounts are not received.

Let's investigate alternative, in particular the gradle native integration : https://github.com/gradle/native-platform

+    implementation("net.rubygrapefruit:file-events:0.22")
+    implementation("net.rubygrapefruit:native-platform:0.22")

Currently file watching capabilities just appeared in a 0.22 milestone, unfortunately this is not completely released (platform specific native libraries are not published on bintray (for the published milestone)).

To follow https://github.com/gradle/native-platform/releases

However native-platform:0.21 is available on it's possible to play with some api like the terminal or files, e.g. :

try {
    Terminals terminals = Native.get(Terminals.class);
    var isTerminal = terminals.withAnsiOutput().isTerminal(Output.Stdout);

    if (isTerminal) {
        var terminal = terminals.withAnsiOutput().getTerminal(Output.Stdout);
        terminal.write("Hello");
        SECONDS.sleep(5);
        terminal.cursorStartOfLine()
                .clearToEndOfLine()
                .bold().write("Bold hello")
                .reset();
    }
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

bric3 avatar Jan 05 '21 23:01 bric3

Gradle's native-platform may not be a good fit after all.

Gradle's native-platform uses macOs's fsevents to handle file events, which does not pickup all file changes. While looking at macOs tail source code I found that it is based on BSD's kqueue and this mechanisms report correctly single file changes.

This finding has been confirmed with the tool fswatch (it implements various way to watch files ; on macOS: fsevents, kqueue, or polling).

Reference issues :

  • https://github.com/gradle/native-platform/issues/269
  • https://github.com/emcrisostomo/fswatch/issues/265

bric3 avatar Jan 12 '21 10:01 bric3

Another idea would be to use JDK16's foreign linker incubator API to leverage kqueue (if JDK 16 is available). Or write a JNI / C code.

bric3 avatar May 22 '21 14:05 bric3