Does the JVM use system calls to seek OS functionalities? - java

We know that the JVM calls on the underlying system to allocate memory and CPU time, access files, and many more. How does it work internally to achieve its activities?
Does the JVM use system calls?

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, String arguments 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

Yes, system calls are the only way that an OS allows access to any program.
In the case of Java, this is why some OS-specific “features” show through, so spoiling the ideal of write-once-run-anywhere. For example, I’ve had a program that I developed on a Windows box fail when run on a Linux box.
The problem turned out to be that in the resources directory, the filename was all-lower case, but my program had the file name inMixed case. The program worked on windows since filenames on windows are case-insensitive, but in Linux they are case-sensitive.

Related

How does it possible that each jar works on linux and windows?

I know that Java give a powerful advantagte: Java code is compiled to bytecode and this bytecode is executed by JVM, hence Java is about portability. However, there exists functions such that their implementation depends on operating system.
https://speakerdeck.com/raboof/jvm-hacking (4-th slide)
As you can see there are system-depended C code. How does it work ? I mean that the same jar using bind method can be executed on windows and linux. After all, bind method on linux and windows can be fairly different (number of paramers, name and more).
Can you explain it me?
It's the JVM and its runtime library that do the magic.
Pure Java programs consist of bytecode, and the JVM interprets or compiles this bytecode, so the local CPU / OS can execute it.
Then there are methods declared to be "native", and the specific Java runtime library for Windows x86 has its implementation, the x64 version has another implementation, the Linux XYZ has yet another implementation and so on. The signature (number and type of parameters) of these native methods is the same over all implementations, buildung a common abstraction over the Windows/Linux/macOS functionalities that they wrap.
If you need to use native methods yourself in your code, you must supply all the necessary implementations with your program (.dll, .so or whatever your targetted systems need). But luckily, that's rarely necessary as the Java library is fairly complete...

Mixed Code (native, managed): how does it (technically) interoperate?

I basically understand the idea of managed and native code and their difference. But how is it technically possible for them to communicate with each other? Imagine the following example:
I got some static or dynamic c++ library which is compiled for a specific platform. Now I write a Java Programm. Inside this code I call the library functions with the 'native' keyword. I build a jar file with the bytecode and the c++ library files will stay separate. The result will no longer be platform-independent.
But how does the java programm know if the called native methods exists?
How is the whole programmcode executed during runtime? I know that the bytecode will be interpreted or compiled with JIT.
How does this all fit in the sandboxing paradigm? Is the native code also executed inside the sandbox?
Does it work because both (java and c++) code is machine code in the end?
Maybe this is a dumb question. But I was always wondering...
EDIT: I got 3 good answers. really can't decide which helped me the most. But i will mark this question as answered to close this topic from my side.
It doesn't know until you call the method. The native code resides in a .DLL or .so; the java runtime looks for specific entry points that correspond to the native methods you created (if you're using JNI, there's a tool that can parse the methods and create function stubs that'll result in those entry points when compiled). If the wanted entry point is not there, an exception will be thrown.
The code generated by the JIT is not entirely self-suficient; it has to call external native code (both for low-level runtime routines or OS services) from time to time. The same mechanism is used to invoke the code for your native methods.
No. You can do everything you'd do in a pure C/C++ program there. The only things that'll stop it from doing any damage are external security measures you have (login privilege restrictions, other OS protections, security software, etc.) But the VM won't protect you.
No, JNI existed even before JIT appeared. The mechanism is the same, if the bytecode is being run by an interpreter, and you want this interpreter to invoke native code, you just need some logic in it to determine that a given method is "external" and should be called as native code. This information is contained in the compiled .class file, and when the interpreter or JIT loads it, it creates a memory representation that makes easy to direct the call upon a method lookup.
The JVM will check the libraries you defined and see if the method is there
Bytecode will be interpreted or JITted and a call to native code is added. This may include boxing/deboxing values and other things needed to convert the data into suitable format. The libraries have a certain interface which is explained to the Java compiler and it will produce the required interface logic.
Depends on the sandbox. By default native code is native code. It doesn't call Java APIs so the JVM cannot govern it in any way. But there may be other limitations, for example the JVM could run the native code with libraries that provide sandboxing, or the operating system might have a way of sandboxing.
It depends on what you mean. In the end anything the computer does is machine code, but it doesn't really matter in this case. What matters is the translation and execution part. That is the glue that makes everything work.
Think of the system as people. Person A only speaks Japanese, but wants to reserve a hotel in Paris. The receptionist B only speaks French. Person A can get a translator that will translate their commands to French, command receptionist B and in return translate what B produced into a form person A understands. This is the JNI part.
It depends on the platform. On Linux, Solaris, etc., the JRE uses dlopen. On Windows, it uses LoadLibraryEx and GetProcAddress. If the JRE is running in interpreted mode, it calls that function; in compiled mode, it compiles Java bytecode into native code that calls that function.
On all JREs I'm familiar with, you can't call a native function in a static library directly; only one in a dynamic library.
Native code doesn't have to be limited to a single platform; if it's standard C, you can probably compile it with a cross-compiler for every platform on which a JRE is available.

How native mixed Java code is platform independent?

In the code of many Java library classes I can see native methods. Even in the Object class.
If Java is platform independent when Java code is converted into byte codes, then what about native code? Is it also converted into byte code?
Does this native code call go to the OS or is it coming from downloaded or installation of Java itself?
Java library code does make native calls. Now these calls are fulfilled by JVM. If you notice then each system has OS specific JVM, so all the system-dependent native calls are ultimately served by the system dependent JVM implementations.
There are different flavours of native method:
The native methods in the standard Java libraries will all be implemented (by Oracle and / or the vendor of your Java implementation) for the platform that you are running on. Doing this is part of the process of developing Java for the platform. By the time you get to use Java (on that platform) the porting work has been done. (The methods are implemented the JVM and its associated native code libraries / dlls.)
Native methods in your code or in 3rd party libraries are a different matter. The native code that implements these methods does indeed represent a portability impediment, because it need to (at least) be recompiled for each platform. And in a lot of cases, the porting process may even extent to a complete rewrite of the (native) code.
If Java is platform independent when Java code is converted into byte codes, then what about native code? Is it also converted into byte code?
No1. Native methods are implemented in some other programming language; e.g. C or C++.
(If the native methods could be translated to bytecodes, there would be no need for them to be written as "native" in the first place!)
Does this native code call go to the OS or is it coming from downloaded or installation of Java itself?
It is unlikely that a Java native method will map directly to an system call or a call to one of the standard OS provided libraries. Native methods are usually implemented either by the JVM implementation, or by customer or 3rd party native libraries. See above.
1 - Actually, there is one exception to this. On the JNode platform, most methods in the Java core libraries that are marked as native do in fact map back to Java code. But that is because, almost the entire JNode operating system is implemented in Java. JNode's native code compiler implements some "clever tricks" to allow this to happen.

Does each of java API function map to java native method?

Does each of java API function map to java native method?
If not then how those functions get the functions of operating system?
Some of them do, and others build on top of the former (or on functionality offered by the JVM itself). Only very few methods map directly to native code, as it is platform specific, and the whole point of the JVM is to offer a platform neutral stage for the code to run.
A Java program runs in a JVM: Java Virtual Machine. The actual executed program is the JVM (lauched by the java command). This JVM is written in C and/or C++. Its role is to load Java byte-code, interpret it (and compile it to native code), and run it.
Some Java methods have the native modifier, and this means that they don't contain any byte-code to execute, but are directly mapped to a native function written in C or C++.
No, as you can see in the source code or by decompilation. The truth is, only very few methods map to native code.
Think about your question it doesn't make complete sense as not all functions (methods) use functions of the operating system.

How JVM call the native method in host environment

These day I have been reading about Java Native Interface.So by the way I do have doubt.Let say for a instance,If we need to do a I/O operation in Java program, we exercise the Java API for I/O operations.Moreover,at low level, it should be mapped to OS level I/O handling.The doubt is how Java API interact with native I/O methods in host operating system.
Short and Sweet, I heard some of the methods in JDK are implemented natively.How those native methods are called by Java API.I guess it would be JNI(Java Native Interface).
Could somebody clarify my doubts.
Thanks
Nuwan Arambage
Methods in Java can be marked native to indicate that their implementation is not written in Java or in bytecode, but rather in something platform-dependent. For example, Java I/O operations are almost always implemented as native methods so that they can take advantage of the underlying hardware or OS interface on the machine.
There is no guarantee whatsoever about how native methods are actually implemented. In Sun's (now Oracle's) implementation of the JVM, you can write implementations for native methods by using JNI to define specially-named C functions that interact with custom libraries in order to interface with Java code. However, another JVM could implement native methods in a totally different way. In fact, right now I'm working on a project to implement a JVM in JavaScript, and so all the native methods are implemented in JavaScript rather than C.
In short, there's no "one way" in which native methods are implemented. The whole point is to give maximum flexibility to the JVM and Java library implementations, and so the less specified the behavior is the better.
After a native library has been loaded, the methods are bound (integrated) into the JVM. The Java VM Spec uses the term binding rather then linking to avoid confusion. But that's just wording.
The rest is simple. There are some bytecode operands that are used to invoke a method. And if that message is declared native, then the associated native code is invoked. Parameters and results are converted so that it doesn't make a difference if we call a native or a non-native method.
Have a look at the spec of invokevirtual, the bulleted list covers the native case.

Categories