Your way isn't far off from what I'd probably do:
Runtime r = Runtime.getRuntime();
Process p = r.exec("uname -a");
p.waitFor();
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = b.readLine()) != null) {
System.out.println(line);
}
b.close();
Handle whichever exceptions you care to, of course.
Answer from John Feminella on Stack OverflowYour way isn't far off from what I'd probably do:
Runtime r = Runtime.getRuntime();
Process p = r.exec("uname -a");
p.waitFor();
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = b.readLine()) != null) {
System.out.println(line);
}
b.close();
Handle whichever exceptions you care to, of course.
That is the best way to do it. Also you can use the ProcessBuilder which has a variable argument constructor, so you could save a line or two of code
I am working on large monolithic java app that copies large files from a SAN to NAS, to copy the files it uses the rsync linux command. I wouldnt have guessed to use a linux command over native java code in this scenario. Do senior java devs have a strong understanding of underlying linux commands? When optimizing java processes do senior devs weigh the option of calling linux commands directly? this is the first time encountering rsync, and I realized I should definitely know how it works/the benefits, I bought “the linux programming interface” by michael kerrisk, and it has been great in getting myself up to speed, to summarize, Im curious if senior devs are very comfortable with linux commands and if its worth being an expert on all linux commands or a few key commands?
Videos
You need to use a native method, but you don't need to implement it yourself. Java has a variation on JNI called JNA (Java Native Access), which lets you access shared libraries directly without needing a JNI interface wrapped around them, so you can use that to interface directly with glibc:
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Test {
public interface CStdLib extends Library {
int syscall(int number, Object... args);
}
public static void main(String[] args) {
CStdLib c = (CStdLib)Native.loadLibrary("c", CStdLib.class);
// WARNING: These syscall numbers are for x86 only
System.out.println("PID: " + c.syscall(20));
System.out.println("UID: " + c.syscall(24));
System.out.println("GID: " + c.syscall(47));
c.syscall(39, "/tmp/create-new-directory-here");
}
}
It is necessary to use a native method, or a library that does so for you.
Does the JVM use system calls?
Yes.
How does it work internally to achieve its activities?
The typical pattern is that some of the methods in a Java class are labelled as native. When the JVM encounters a call to a native method it makes a call into C or C++ code that is part of the JVM executable. The native method implementation typically does the following:
Check arguments from Java, and translates them into a C / C++ compatible form. For example,
Stringarguments need to be converted to zero-terminated form.Call the standard C / C++ library function with the arguments it needs.
The library function makes the syscall.
The OS does its stuff and the syscall returns.
The standard C / C++ library function returns.
The native method implementation checks the 'errno'. If there was an error, it creates a Java exception object and throws it.
Otherwise, the native method implementation converts results, etc into Java objects and returns them to the caller of the Java method.
The details vary, depending on what the native method does.
If you want to get a deeper understanding, I recommend that you checkout a copy of the OpenJDK source tree and start trawling. (You need to do the hard yards yourself ....)
Indeed, JVM needs to leverage system calls which is an operating system way to allow processes to interact with underlying system resources.
You can run strace java -version to see a bunch of system calls (mmap, mprotect, openat, etc.) executed even during this very limited java/jvm run.
Another good way to find out more is to dig trough JVM sources for native methods.
One example could be an implementation of FileChannel#force method
which internally calls fsync system call (for example): https://github.com/AdoptOpenJDK/openjdk-jdk11u/blob/5f01925b80ed851b133ee26fbcb07026ac04149e/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c#L172