I am wondering how does Java code make a syscall, does the JIT compiler generate syscall instructions directly, or that it just put calls to libc functions (or other basic library functions)?
The Hotspot JVM generates machine code for Java code (which doesn't support making syscalls).
All code which makes syscalls is in a native method.
So when Java wants to make a syscalls, you have to call some native code to do it for you.
There are libraries you can use to wrap native calls. E.g. JNA and JNR-FFI. This allows you call c libraries without writhing native code.