Java Native Interface and Security - java

Is there any chance for the the violation of java security policy through java native interface.
Which are the main areas we have to use JNI

Java's Security policies simply do not apply to native code called via JNI, so obviously the native code can violate them at will.
As for what JNI us used for, these days it's mainly to call OS-specific APIs or interface with existing non-Java code. Improving performance used to be a frequently-cited reason, but considering the state of VMs and JIT compilers today, that almost never makes sense.

Yes, once you invoke native code through JNI it can do pretty much anything the current user is allowed to do - e.g. delete all their files. The Java system cannot police anything that native code does.
You don't have to use JNI for anything - it's typically used for e.g. low-level access (e.g. critical error handling for a removable drive) or to access a C API which doesn't have a pure-Java equivalent.

Related

Does Java use JNI "out-of-the-box"?

It is not conceptually clear to me as to when Java uses JNI. The literature 1,2 seems to suggest using JNI is optional - it is a useful feature for my own, existing native C applications, but it is good practice to avoid using it when possible:
Liang indicates "Remember that once an application uses the JNI, it risks losing two benefits [of portability and security]".
However, I was looking at Oracle's API implementation in the SDK, and I see public static native void arraycopy in java/lang/System.java. Questions:
Don't methods marked as such, in native, use JNI?
Doesn't Java make use JNI when making system calls?
System calls are required for any Java API implementation, so if I'm correct, it seems there is no avoiding interfacing with native code.
1: Horstmann, Core Java Volume 2
2. Liang, The Java™ Native Interface Programmer’s Guide and Specification
You list two drawbacks of JNI - portability and security. Actually, there is another one, which is more important in everyday life: JNI calls bear a significant performance cost, because they affect the global JVM state and lock some JVM features, including GC.
As detailed in the other answer, JVM does rely on JNI. But this is not a complete answer.
Your JVM may support fast JNI methods (e.g. Android ART does). These methods are guaranteed to be fast and non-blocking, and they may be performed without state change, see e.g. #FastNative. The Java SDK native methods use such improvements a lot, so they don't suffer the performance costs of conventional JNI.
These native methods do not rely on LoadLibrary() during run. This removes another significant performance cost of JNI - loading and 'binding' the native methods at runtime. The worst risk with runtime binding is that it happens at an arbitrary time, determined by the classloader, and may clash with some other urgent thing that your JVM or app must do at that time. Irrelevant for the system native methods.
Also, portability concerns are irrelevant: the Java runtime is carefully crafted for each supported platform, and in itself it is not 'portable', only the Java apps running on top of it are.
Finally, security risks of JNI are twofold: JNI is not limited by private declarations, and the native code can do dangerous things that compromise any class or app running in the same JVM. And, being loaded from a third-party library, JNI code may be hacked (e.g. it's enough to change OS environment to cause System.loadLibrary() load a fraudster's version of the lib). The system native methods are immune to such attacks.
In the nutshell, even though JVM does use JNI, this is not an excuse to indiscriminately use JNI for your own classes.
Don't methods marked as such, in native, use JNI?
Yes, that's what it means.
Doesn't Java make use JNI when making system calls?
Same question really. Only native methods can call system calls, so Java code can only call system calls via native methods.
Using JNI is optional for applications. It's essential for the JVM.

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.

Wrapping C/C++ inside Java

I develop applications/programs in C/C++. I am more versed in these two languages and love being a C++ developer. I am wondering how to create a Java program that contains all my C++ code.
I mean, I would like to wrap all my C++ code (that is already developed) inside Java class. But clueless how to do it.
Please post your responses or methods/steps on integrating C++ inside Java.
(using JNI is the way, but I could not figure it out on www how to use it)
FYI, I use Eclipse IDE to develop.
How and what packages should I include in my project workspace?
Instead of JNI, or JNI with some assist from an automatic wrapper generator like SWIG, or even JNA, you might consider separating the C/C++ and Java into separate processes and using some form of IPC and/or Java's Process abstraction to call to a program written in C/C++. This approach abandons "wrapping," so in some sense it isn't an answer to this question, but please read on before down-voting. I believe that this is a reasonable answer to the broader issue in some cases.
The reason for such an approach is that when you call C/C++ directly from Java, the JVM is put at risk of any error in the native code. The risk depends somewhat on how much of the native code is yours and how much you link to third party code (and how much access you have to the source code of such third party code).
I've run into a situation where I had to call a C/C++ library from Java and the C/C++ library had bugs that caused the JVM to crash. I didn't have the third party source code, so I couldn't fix the bug(s) in the native code. The eventual solution was to call a separate C/C++ program, linked to the third party library. The Java application then made calls to many ephemeral native processes whenever it needed to call the C/C++ stuff.
If the native code has a problem, you might be able to recover/retry in Java. If the native code is wrapped and called from the JVM process, it could take down the entire JVM.
This approach has performance/resource consumption implications and may not be a good fit for your application, but it is worth considering in certain situations.
Having a separate application that exercises the functionality of the C/C++ code is potentially useful as a stand-alone utility and for testing. And having some clean command-line or IPC interface could ease future integrations with other languages.
As another alternative, you could get into native signal handling to mitigate the risks to the integrity of the JVM process if you like and stick with a wrapping solution.
If you want to call C++ from Java, you'll need to use JNI - Java Native Interface.
Be warned that you lose some of the benefits of the garbage collector, since it can't deal with your C++ objects, and your code won't be portable anymore.
Maybe you'd be better served by learning to write 100% Java and leaving C++ behind, but that's just a suggestion.
You can't "just wrap it", you have to write some C/C++ glue.
For starters, SWIG can do most of the works for you.
There are plenty of tutorials for doing exactly what you want to do. For example, check out: http://www.javamex.com/tutorials/jni/getting_started.shtml
There are also plenty of caveats of using JNI. I've recently started working with it (just for fun, really), and it tends to be a lot less fun than I had first anticipated.
First of all, you have to deal with cryptic code such as:
#include "test_Test.h"
JNIEXPORT jint JNICALL Java_test_Test_getDoubled(JNIEnv *env, jclass clz, jint n) {
return n * 2;
}
Second of all, it tends to downplay one of the primary reasons why you use Java in the first place: WORA (Write Once, Run Anywhere). As duffymo mentioned, there can also be issues with the garbage collector, but I think that in recent years, the JVM has gotten pretty smart about JNI integration.
With that said, to port all of your C++ code to JNI, you'd need to refactor your interfaces (and maybe even do some internal gymnastics). It's not impossible, but it's really not recommended. The ideal solution is just re-writing your code in Java.
With that said, you could also "convert" your code from C/C++ into Java programatically, and there are multitudes of such utilities. But, of course, machines are dumber than people and they are also bound to make mistakes, depending how complex your class is.
I would avoid JNI because it's tedious to write, verbose, and just an altogether pain. Instead I'd use JNA library which makes writing native integration so simple.
https://github.com/twall/jna/
Good luck.
You can write C++ code through JNI but there isn't a direct mapping from C++ classes to Java classes.
I've used JNI to fix problems found in the android SDK (specifically, an incredibly slow FloatBuffer.put implementation) and I may end up using it for some performance critical areas. My advice would be to be use it sparingly and in a duck in, do the performance critical stuff and leave, without doing any memory allocation if you can help it. Also, don't forget to measure your code to see if it really is faster.
Out of interest, what platform are you developing for? The only platform where it would make sense to wrap a lot of C++ code in a light java layer would be Android - on other platforms, just compile in C++ and have done with it.
JNI module is not a Java classes. It's C. Using JNI incur many restrictions and some Java environment doesn't support JNI well.
There is no supported way of "wrap my C++ code inside Java class" (EDIT: I mean, without JNI noway but JNI is problematic.)
You could investigate custom C++ compiler emit Java byte codes, but nobody (include me) will recommend this approach.
BridJ was designed on purpose for that (and it's supported by JNAerator, which will parse your C/C++ headers and spit out the Java bindings for you).
It is a recent alternative to JNA, with support for C++.

Java DLL security general question

I understand that Java can load/execute DLL code, but I'm wondering if there are any security checks to prevent untrusted code from the system being called by a JVM. Couldn't this destroy the system -- are there any OS features that prevent this? Or can someone just write in Java itself some method that prevents untrusted code from being loaded? Thanks for your help.
No. Once you call out to native code (via JNI) then that native code is free to do anything (subject to the OS itself giving permission). There's no concept of sandboxing the native code invoked from the JVM.
Note that this is a particular headache with JNI code. Badly coded native code can take down the JVM (as opposed to simply throwing an exception) and the consequent debugging/resolution is particularly hard.
The loading of native code can itself be prevented. Typically e.g. applets run such security context that they cannot load native libraries. However, if the JVM lets your Java code call into untrusted native code, all bets are off.

Can a java module call a c module?

Just out of interest , is it possible to call a C module from a java module ? If so , how to do that ?
yes you can use Java Native Interface to do this:
Yes, you can do it. Whether you should do it is another matter.
On the pro side:
Calling C libraries from Java will avoid the need to recode the libraries in Java (but see below).
For some computational intensive algorithms, a well-written C implementation may be faster than an equivalently well-written Java version.
Some operating system specific operations cannot be implemented in pure Java.
On the con side:
There is a greater overhead in making a JNI call versus a simple Java method call.
If your C library is not thread-safe, you have to be really careful calling it from Java. And as a rule, C libraries are not implemented with thread safety in mind.
If your C library has memory management issues, it may destabilize the Java platform resulting in JVM crashes.
Calling native libraries immediately means that your application is harder to port, and requires a more complicated build process.
Yes, you call C/C++ from Java using the Java Native Interface (JNI) from this purpose.
Java Native Interface: Programmer's Guide and Specification
You can also use SWIG for this purpose:
SWIG Tutorial
Look into JNI (Java Native Interface).
Yes. As others have already mentioned, JNI or Java Native Interface is Sun's preferred way of doing this. If you feel you'll need to call the C code from other languages as well as Java, I'd look into SWIG, which will transparently generate the JNI code for you, but also allow you to do similar things with, for example, Python.
There are a number of C to (Java) bytecode compilers, which may be able to turn your C code into a .jar of portable Java classes you can call directly from Java.
Detriments versus JNI:
There is a noticeable performance penalty, typically at least 100%.
Benefits versus JNI:
Just like running pure Java code, it is safe, does not require special privileges to load, and does not require recompiling for every target platform.
(When I say "JNI" I really mean all Java interfaces to native code. For example, the same applies to CNI.)

Categories