<div dir="ltr">Hi,<br><br>I have a question about the behavior of critical functions inside a for-loop. I marked open() as critical (I know this is not an empty function like the java docs tells me i should use critical for, but I really wanted to try it). Wanting to see if it speeds things up. What I didn't expect was that it doesn't work well with variables created inside the loop itself, or at least that seems to be the case. Open() fails returning -1. To work around this issue I created a "stableBuffer" just outside the loop, which makes the code work all of the time. <div><br></div><div>I just have two questions. Is this expected behavior for critical functions? Why does the stable buffer approach work consistently while using variables inside the loop fail after a few iterations?<div><br></div><div>The loop that causes issues:<br><div><div style=""><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><font color="#000000">    @Test<br>    void test() {<br>        var paths = <span style="font-style:italic">filesTooRead</span>;<br><br>        byte[] stableBuffer = new byte[4096];<br><br>        for (var path : paths) {<br><br>            byte[] pathBytes = path.getBytes();<br>            Arrays.<span style="font-style:italic">fill</span>(stableBuffer, (byte) 0);<br>            System.<span style="font-style:italic">arraycopy</span>(pathBytes, 0, stableBuffer, 0, pathBytes.length);<br><br>            <span style="font-style:italic">// works all the time<br></span><span style="font-style:italic">            </span>int fd = openFile(stableBuffer, 0, 0);<br><br>            <span style="font-style:italic">// works for a couple of </span></font>iterations<font color="#000000"><span style="font-style:italic"><br></span><span style="font-style:italic">//            int fd = openFile(path.getBytes(), 0, 0);<br></span><span style="font-style:italic">//            int fd = openFile("/media/david/Data2/text_files/file_2299.bin".getBytes(), 0, 0);<br></span><span style="font-style:italic"><br></span><span style="font-style:italic">            </span>MemorySegment buffer = Arena.<span style="font-style:italic">ofAuto</span>().allocate(4);<br><br>            read(fd, buffer, 4);<br>            buffer.set(ValueLayout.<span style="font-style:italic">JAVA_BYTE</span>, 3, (byte) 0);<br><br>         <span style="font-style:italic">//   System.out.println(path + "content " + buffer.getString(0));<br></span><span style="font-style:italic"><br></span><span style="font-style:italic">            </span>if (fd < 0) {<br>                System.<span style="font-style:italic">err</span>.println("Failed to open file:");<br>            }<br><br>            <span style="font-style:italic">closeFile</span>(fd);<br><br>        }<br>    }</font></pre><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt">OS: Pop!_OS 22.04 LTS<br style="font-family:Arial,Helvetica,sans-serif;font-size:small;white-space:normal"><span style="font-family:Arial,Helvetica,sans-serif;font-size:small;white-space:normal">Java version: JDK 24 EA Build 35 (2025/2/4)</span><font color="#000000"></font></pre><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="font-family:Arial,Helvetica,sans-serif;font-size:small;white-space:normal"><br></span></pre>Thank you for your time and feedback.<br><br>Kind regards,<br>David Vlijmincx<br><br>The entire class:<pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><div style=""><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><font color="#000000">package bench;<br><br>import org.junit.jupiter.api.Test;<br><br>import java.io.IOException;<br>import java.lang.foreign.*;<br>import java.lang.invoke.MethodHandle;<br>import java.nio.file.Files;<br>import java.nio.file.Path;<br>import java.util.Arrays;<br>import java.util.stream.Stream;<br><br>import static java.lang.foreign.ValueLayout.*;<br><br>public class CriticalLoopTest {<br><br>    public static final String <span style="font-style:italic">BENCHMARK_FILE_EXTENSION </span>= ".bin";<br>    public static final Path <span style="font-style:italic">BASE_BENCHMARK_FILES_DIR </span>= Path.<span style="font-style:italic">of</span>("/media/david/Data2/text_files");<br>    public static final String[] <span style="font-style:italic">filesTooRead</span>;<br><br>    private static final MethodHandle <span style="font-style:italic">open</span>;<br>    private static final MethodHandle <span style="font-style:italic">close</span>;<br>    private static final MethodHandle <span style="font-style:italic">read</span>;<br><br>    static {<br>        Linker linker = Linker.<span style="font-style:italic">nativeLinker</span>();<br><br>        <span style="font-style:italic">open </span>= linker.downcallHandle(<br>                linker.defaultLookup().find("open").orElseThrow(),<br>                FunctionDescriptor.<span style="font-style:italic">of</span>(<span style="font-style:italic">JAVA_INT</span>, <span style="font-style:italic">ADDRESS</span>, <span style="font-style:italic">JAVA_INT</span>, <span style="font-style:italic">JAVA_INT</span>),<br>                Linker.Option.<span style="font-style:italic">critical</span>(true)<br>        );<br><br>        <span style="font-style:italic">read </span>= linker.downcallHandle(<br>                linker.defaultLookup().find("read").orElseThrow(),<br>                FunctionDescriptor.<span style="font-style:italic">of</span>(<span style="font-style:italic">JAVA_INT</span>, <span style="font-style:italic">JAVA_INT</span>, <span style="font-style:italic">ADDRESS</span>, <span style="font-style:italic">JAVA_INT</span>)<br>        );<br><br>        <span style="font-style:italic">close </span>= linker.downcallHandle(<br>                linker.defaultLookup().find("close").orElseThrow(),<br>                FunctionDescriptor.<span style="font-style:italic">ofVoid</span>(<span style="font-style:italic">JAVA_INT</span>)<br>        );<br><br>        try (Stream<Path> files = Files.<span style="font-style:italic">walk</span>(<span style="font-style:italic">BASE_BENCHMARK_FILES_DIR</span>)){<br>            <span style="font-style:italic">filesTooRead </span>= files<br>                    .filter(p -> p.getFileName().toString().endsWith(<span style="font-style:italic">BENCHMARK_FILE_EXTENSION</span>))<br>                    .map(Path::toString)<br>                    .toArray(String[]::new);<br>        } catch (IOException e) {<br>            throw new RuntimeException(e);<br>        }<br>    }<br><br><br>    @Test<br>    void test() {<br>        var paths = <span style="font-style:italic">filesTooRead</span>;<br><br>        byte[] stableBuffer = new byte[4096];<br><br>        for (var path : paths) {<br><br>            byte[] pathBytes = path.getBytes();<br>            Arrays.<span style="font-style:italic">fill</span>(stableBuffer, (byte) 0);<br>            System.<span style="font-style:italic">arraycopy</span>(pathBytes, 0, stableBuffer, 0, pathBytes.length);<br><br>            <span style="font-style:italic">// works all the time<br></span><span style="font-style:italic">            </span>int fd = openFile(stableBuffer, 0, 0);<br><br>            <span style="font-style:italic">// works sometimes<br></span><span style="font-style:italic">//            int fd = openFile(path.getBytes(), 0, 0);<br></span><span style="font-style:italic">//            int fd = openFile("/media/david/Data2/text_files/file_2299.bin".getBytes(), 0, 0);<br></span><span style="font-style:italic"><br></span><span style="font-style:italic">            </span>MemorySegment buffer = Arena.<span style="font-style:italic">ofAuto</span>().allocate(4);<br><br>            read(fd, buffer, 4);<br>            buffer.set(ValueLayout.<span style="font-style:italic">JAVA_BYTE</span>, 3, (byte) 0);<br><br>         <span style="font-style:italic">//   System.out.println(path + "content " + buffer.getString(0));<br></span><span style="font-style:italic"><br></span><span style="font-style:italic">            </span>if (fd < 0) {<br>                System.<span style="font-style:italic">err</span>.println("Failed to open file:");<br>            }<br><br>            <span style="font-style:italic">closeFile</span>(fd);<br><br>        }<br>    }<br><br>    public int read(int fd, MemorySegment mem, int len) {<br>        try {<br>            return (int) <span style="font-style:italic">read</span>.invokeExact(fd, mem, len);<br>        } catch (Throwable e) {<br>            throw new RuntimeException(e);<br>        }<br>    }<br><br>    public int openFile(byte[] filePath, int flags, int mode) {<br>        try {<br>            int fd = (int) <span style="font-style:italic">open</span>.invokeExact(MemorySegment.<span style="font-style:italic">ofArray</span>(filePath), flags, mode);<br>            if (fd < 0) {<br>                throw new RuntimeException("Failed to open file fd=" + fd);<br>            }<br>            return fd;<br>        } catch (Throwable e) {<br>            throw new RuntimeException(e);<br>        }<br>    }<br><br>    public static void closeFile(int fd) {<br>        try {<br>            <span style="font-style:italic">close</span>.invokeExact(fd);<br>        } catch (Throwable e) {<br>            throw new RuntimeException("Could not close file with FD:" + fd, e);<br>        }<br>    }<br>}</font><font color="#080808"><br></font></pre></div></pre></div></div></div></div></div>