Java type and Native type [duplicate] - java

I need to call external DLL library function from Java code. I use Netbeans 7.2.
My dll's functions are:
Boolean isValid(string word)
List<String> getWords(String word)
I'm following this example. But I don't know how declare my dll functions.
And I found another link. But it doesn't work for me.

I stumbled upon the same problem of "calling DLL from Java" and first was frustrated about the complexity. Yet, there is an elegant solution (might also be interesting for the people over there in the processing.org habitat..)
Given the rather "general" form of the question (maybe, downrating is not justified for that), I suppose, a rather easy-going solution would be indicated. In other words, a solution that avoids messing aronud with header files, extra conversions, etc., just as the source code is not necessarily available.
My recommendation for that would be JNA (https://github.com/twall/jna), which basically is a simplifying wrapper around JNI. It works great, type mapping is straightforward (e.g. pchar = lpcstr buffer -> string), though I am using it only towards Windows DLLs and my own C-style DLLs created using Delphi-Pascal. The only thing to consider is that return values should be exported through functions rather than "out" flagged reference variables.
The question already points to a linked source that provides an example for that (so, answers around JNI may be misplaced here). Note that the link I provided also contains axamples for the transfer of arrays and pointers.

You will need to use the Java Native Interface (JNI), which is a set of C/C++ functions that allow native code to interface with java code (i.e. receiving parameters from java function calls, returning results, etc). Write a wrapper C library that receive JNI calls and then call your external library.
For instance, the following function invokes a method updateHandlers on a native object (that is stored as long in the Java side).
class MyImpl {
void updateHandlers(JNIEnv *env) {
this->contentHandler = ....;
}
}
JNIEXPORT void JNICALL Java_package_Classname_updateHandlers0
(JNIEnv *env, jobject obj, jlong ptr)
{
((MyImpl*)ptr)->updateHandlers(env);
}
The corresponding declarations in package.ClassName are:
private long ptr; //assigned from JNI
public void updateHandlers() {
if (ptr==0) throw new NullPointerException();
updateHandlers0(ptr);
}
private native void updateHandlers0(long ptr);
static {
try {
/*try preloading the library external.dll*/
System.loadLibrary("external");
} catch (UnsatisfiedLinkError e) {
/*library will be resolved when loading myjni*/
}
System.loadLibrary("myjni"); //load myjni.dll
}

I did write some time ago sample tutorial, maybe it will help.
http://wendro.blogspot.com/2010/03/jni-example-eclipse-dev-cpp.html

You declare your native functions in java (native private ...) with the signature that you need; then run javah (a tool that is provided with the JDK) in order to generate the native headers. A List<String> (actually a List, because of type erasure) is a jobject in native code.
The corresponding C method, would be:
JNIEXPORT jobject JNICALL package_Classname_getWords(JNIEnv *env, jobject jobj, jstring word)
I think it would be easier to return an array of strings jobjectArray, and instantiate the List in java from the returned values. See this example.

Related

Can I create a c++ class instance and use it as an entity in Android JNI?

Let's say I create a class 'Car' in cpp.
I want to creat an instance of that class with it's empty constructor in cpp.
Can I do it and use it in java code on android?
For instance:
Java code
Car myCar = new Car();
CPP class
class Car{
std::string model;
int creationYear;
Car(){}
}
thanks for the help
Yes. You can easily have a native object that shadows a Java object - assuming you can call the C++ Car() constructor. You could use a public static method in the C++ Car class to do that.
It's a bit of a hack, but a Java long is guaranteed to be 64 bits, so it's long enough to hold a native pointer value.
In Java:
public class Car
{
// A Java long is 64 bits, so it will
// hold a native pointer
private long nativeCar;
private native long newNativeCar();
private native void deleteNativeCar( long car );
public Car()
{
this.nativeCar = newNativeCar();
}
// allow for explicit native cleanup by caller
public synchronized deleteCar()
{
if ( 0 != this.nativeCar )
{
deleteNativeCar( nativeCar );
nativeCar = 0;
}
}
// handle cases where the native cleanup code
// was not called
#Override
protected void finalize() throws Throwable
{
deleteCar();
super.finalize();
}
}
Compile that, then use javah on the class file to create your C header file. (Note that JNI uses C, not C++. You can write C++ code to implement your logic, but the interface presented to the JVM must be a C interface.)
You'll get a couple of functions in your native header, something like this (I've stripped off the annotation from javah - you will need to keep that...):
jlong some_class_path_newNativeCar( JNIEnv *, jobject );
void some_class_path_deleteNativeCar( JNIEnv *, jobject, jlong );
You can implement your C++ code then:
jlong some_class_path_newNativeCar(
JNIEnv *env, jobject obj )
{
Car *nativeCar = new Car();
// C cast - we're returning a C value
return( ( jlong ) nativeCar );
}
void some_class_path_deleteNativeCar(
JNIEnv *env, jobject obj, jlong jNativeCar )
{
Car *cppNativeCar = ( Car * ) jNativeCar;
delete cppNativeCar;
}
I've deliberately kept the code simple - there's quite a bit I left out. javah can be a bit tricky to figure out how to use properly, for example. But if you can't figure out how to use javah properly you shouldn't be writing JNI code anyway.
Because JNI code is fragile. You can't make any mistakes, or you will wind up getting seemingly random failures or having your JVM crash, and the crash will likely not be easily traced to the bad code that caused the problem. There are lots of rules for making JNI calls using the JNIEnv * pointer supplied to a native call. For example, in general you can't save the values passed to you by the JVM and use them outside of the context you received them in - using them in another thread, or after the function where they were passed to you returns is a great way to cause those JVM crashes I mentioned above.
Nor can you make any JNI calls to Java if there are any exceptions pending from previous calls - again, you risk unpredictable errors and crashes if you do.
So keep your native code simple.
Keep all the logic and processing on only one side of the Java/native interface if you can.
Pass only C or Java strings, primitives or primitive arrays across the Java/native interface if you can.
Interacting with actual complex Java object from native code will take many, many lines of C or C++ code to safely replicate what can be done in Java with one or two lines of code. Even simple one-line get*()/set*() Java calls become 20 or 30 lines or more of C or C++ code if you replicate all the exception and failure checks you need in order to guarantee safe JVM execution after the native call no matter what data gets passed in. If you pass null to a Java method that can't handle a null value it will throw a NullPointerException that you can catch and your JVM runs happily or shuts down cleanly with an uncaught exception. Pass NULL to a JNI function that can't handle it, and if you don't properly check for any failure or any exception and then properly handle it, your JVM will exhibit seemingly unrelated failures or just crash.

Modifying Java Methods/Bytecode in Runtime with C++

me and a friend of mine are working on a coding project and we ran into a little issue. We are essentially trying to modify Java Methods/Bytecode during runtime using C++. I am just curious if this is possible or how it is possible. We have already tried using JVMTI and JNI to accomplish this but it seems that you can only modify classes that are currently being loaded into the JVM. We are loading our code in as a DLL while the process is running so we can not do this. We also thought assembly might work by accomplishing this. A little demonstration of what we are trying to do can be seen below.
public boolean Method()
{
boolean value = true;
return value; //<- Value that we want to modify (in java)
}
jclass JVMUtilities::getClass(std::string clazzname) {
jstring name = Wrapper::getJVMHook().getJNI()->NewStringUTF(clazzname.c_str());
jobject classLoader = getclassloader();
jmethodID mid = Wrapper::getJVMHook().getJNI()->GetMethodID(Wrapper::getJVMHook().getJNI()->GetObjectClass(classLoader), "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
return (jclass)Wrapper::getJVMHook().getJNI()->CallObjectMethod(classLoader, mid, name);
//This is the function we use for geting the class information in c++ including location
}
Basically going by above, we want to change the return value to what we want during run time by manipulating the byte code.
There is a public standard API to do this - JVM TI RedefineClasses and RetransformClasses.

how to modify the value of a primitive data passed to a C++ routine using Java and JNI?

Can I pass a primitive from Java to my C++ function using JNI function calls and modify its value in the C++ function ?
So far, I have seen examples of returning jstring,jint,jboolean etc, which I do not want to do. The other option that I know about is to get the ID of the primitive variable within C++ and set its value.
For Example :
JNIEXPORT void JNICALL Java_myFunction
(JNIEnv *, jobject obj, jboolean retJava)
Here i am passing boolean from java and want to change it in C++ depending on my computation without return statement.
Unfortunately you can not do this with JNI.
You can hack it with using boxed types (see an example here) but it is strongly discouraged, as it can break all kinds of things easily (as to what exactly, see the comments in the linked question).

Return MPI::Request[] type from JNI and access elements of Request in Java

I'm looking to return an MPI::Request[] type from a native C++ function to Java (via JNI) and subsequently access elements in the MPI::Request[] array from the Java side.
JNIEXPORT jobjectArray JNICALL Java_mpiJNI_mpiTEST(JNIEnv *env, jobject obj) {
MPI::Request req[8];
return req; // Error: Can't convert req to jobjectArray type
}
The only return types I know of that would be close are jobjectArrays and this does not work. Java doesn't know what an MPI::Request[] type is.
I've not wanted to use things like MPJ or MPIJava because I don't know that there is much support for future MPI work in Java and want to have code that will persist through many cluster updates and configurations. If someone knows more about this matter I would be interested to hear more.
You need to return a JNI type of type jobjectArray. JNI will not convert that req pointer to a jobjectArray for you. Also note that how java lays out object arrays and
First off, you are allocating an array on the C++ stack. This is not a persistent memory and thus req pointer will be garbage when your JNI method returns. So if you want to preserve or allocate the native array storage, you will need to allocate the memory with 'new' and have a persistent pointer to your array.
What I would suggest, is that instead of returning and creating a object array, you return a single "pointer" value back to java to the begining of the the Request array, just like you would do in C++.
In order to preserve a native pointer inside a Java object, the typical trick is to convert the pointer to a java 'long' primitive type, which is long enough to hold the actual native address on most platforms. The store the return 'long' in your java class as field.
Next time you need access to the native MPI::Request array, you make a call to a native java method and pass it the address value stored as 'long' and in you corresponding JNI method, convert the JNI jlong parameter back to a pointer and typecast it to MPI::Request *req and thus you will have successfully created the request in your java/jni method, returned it, and stored inside a java class and then again used it natively in a second method where you can make the C++ calls to create/send those requests and so on.
Lastly, since you dynamically allocated the native memory for the MPI::Result[], remember to make another java native method that will again convert the long value to a pointer and release the memory with C++ delete statement, after you no longer need that array. Otherwise you will have a memory leak.
So here is how I would rewrite your JNI method:
JNIEXPORT jlong JNICALL Java_mpiJNI_mpiTEST(JNIEnv *env, jobject obj) {
MPI::Request *req = new MPI::Request[8]; // Don't forget to release memory leater
uintptr_t storage = (uintptr_t)ptr
return (jlong) storage;
}

How do 256 java bytecodes translate to everything java does (graphics, IO, etc)

I'm looking at java bytecode listings and Wikipedia, and they all seem to be basic operations (branch, push, pop, cast, etc.). And many articles use these basic examples. But what happens when I read a line from the console, or create a new JButton? Where's the bytecode for opening a port?
I believe I saw something for "making a system call" (although I didn't find it today, skimming through the list several times). Do these "special" calls have their own code, which are directly delegated (don't know how to say it technically) to the OS by the VM? I know there are ways to open up the bytecode, but I'm looking for a general explanation, not weeks of learning advanced bytecode.
There is no byte code for opening a port or drawing graphics to the screen. There are classes that perform these tasks. These classes have native methods, those are methods written in C (or any other language that can be compiled to a native library) and as they are native, they can access the network and graphcis libraries of your operating system to perform those tasks. So you are instantiating these classes and call some of their methods. Java Byte Code offers byte code for instantiating classes and for calling methods of objects. If the JVM sees that this is a native method, it will call the native code that belongs to this method and this native code can do pretty much anything a C or C++ program could do.
So for example, if you call System.out.println in Java, roughly the following happens:
System is a class with a static variable out. This variable points to an object of type java.io.PrintStream which has already been created by the JVM before your main method is ever executed. The out variable is initialized like this:
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
And the method setOut0 is defined as
private static native void setOut0(PrintStream out);
This means setOut0 is a native method, written in C, or some other language that can be compiled and linked to a native library, though at least the interface between Java and this library is usually written in C.
Java will search in all loaded libraries for a symbol (in that case symbol means function name) with the name Java_java_lang_System_setOut0, this is Java_ClassName_MethodName and call it. A sample C code I have found for this method looked like this:
JNIEXPORT void JNICALL
Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream)
{
jfieldID fid =
(*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
if (fid == 0)
return;
(*env)->SetStaticObjectField(env,cla,fid,stream);
}
Yet this is not the real magic, the real magic happens elsewhere. PrintStream.write() calls BufferedWriter.write(). This method again calls OutputStreamWriter.write() (not directly, but sooner or later it ends up there) and this method calls StreamEncoder.write(). Wow, it's getting hard to trace that call. The StreamEncoder calls BufferedOutputStream.write(), this one calls FileOutputStream.write() and this one calls FileOutputStream.writeBytes() and finally, finally we are there! FileOutputStream.writeBytes() is a native method. It will look something like this:
JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_writeBytes(JNIEnv *env,
jobject this, jbyteArray bytes, jint off, jint len) {
writeBytes(env, this, bytes, off, len, fos_fd);
}
So it calls a function named writeBytes and this function looks different depending on your operating system, e.g. whether this is Windows, Linux or OS X. On UNIX/Linux systems this function may call another function (and so on), but somewhere is a simple C function call to write something to a C FILE * stream or a file descriptor (which is just an int in C). So it could be a printf()/fprintf() or a puts()/fputs() call that writes to stdout or a write() call that writes to STDOUT_FILENO. In Windows it is usually a call to WriteFile(), though it could also be a printf()/fprintf() (those are C standard functions, all platforms must support them).

Categories

Resources