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.
Related
How does JVM translate API to its implementation inside JVM?
Is it similar to "Linux Kernel syscall" implementation? If so, where are these interfaces? Hope to see the source code.
Figure from https://www.artima.com/insidejvm/ed2/introarch4.html
e.g. ,
Any Java virtual machine implementation must take care to connect these methods of class ClassLoader to the internal class loader subsystem.
https://www.artima.com/insidejvm/ed2/jvmP.html
The API you have linked (https://docs.oracle.com/javase/7/docs/api/), is basically an ordinary class library. When you have installed a JDK, there will be file, src.zip or src.jar, depending on the version, containing the plain Java source code of most of this library. In all versions up to and including Java 8, the compiled API classes are delivered as ordinary jar files, the majority of the API classes being in rt.jar. Starting with Java 9, new module files are used, still, the majority of the API is implemented as ordinary Java code.
You can even browse the source code of certain versions online, e.g. this is the implementation of Object.toString() of version 8, update 40, beta 25, hosted at grepcode.com.
So for most methods, there is nothing “similar to ‘Linux Kernel syscall’” involved when you invoke an API method. It works like an ordinary method invocation and the optimizer may even inline the JRE specific code into your application’s code at runtime. You may also step into the JRE’s code while debugging.
Only a few methods are not implemented as plain Java code, e.g. Object.getClass() is a native method that can only be implemented in a JVM specific way.
There are two general ways to implement these methods. There is a standardized interface, JNI, allowing the interaction of arbitrary native code and Java code. It includes a special linkage between invocations of Java methods declared native and their implementation via JNI. But some methods are handled as intrinsic operations by the JVM instead, which implies that the invocations of these well-known methods (e.g. getClass()) is handled directly by the interpreter/optimizer like a dedicated bytecode instruction. This very efficient handling is sometimes even used for methods, which have an ordinary Java implementation, when there is a platform specific, more efficient alternative. E.g, Integer.rotateLeft and rotateRight have a pure Java implementation, but if the actual CPU used at runtime has dedicated instructions for bitwise rotation, all optimizing JVMs will replace the invocations of these method with intrinsic operations using these CPU instructions.
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...
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.
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.
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.