java native interface jni
Download
Skip this Video
Download Presentation
Java Native Interface (JNI)

Loading in 2 Seconds...

play fullscreen
1 / 23

Java Native Interface (JNI) - PowerPoint PPT Presentation


  • 278 Views
  • Uploaded on

Java Native Interface (JNI). Phil Pratt-Szeliga Syracuse University. JNI Overview. JNI allows a developer to interop with arbitrary C/C++ code The managed to native transition can take time, so don’t expect a performance enhancement from, say, repeatedly incrementing an integer

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Java Native Interface (JNI)' - raisie


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
java native interface jni

Java Native Interface (JNI)

Phil Pratt-Szeliga

Syracuse University

jni overview
JNI Overview
  • JNI allows a developer to interop with arbitrary C/C++ code
  • The managed to native transition can take time, so don’t expect a performance enhancement from, say, repeatedly incrementing an integer
  • With JNI you need to have a .dll built for Windows and a .so built for Linux (and I guess a .so for Mac).
    • Your build process needs to be able to built the .dllon Windows and the .so on Linux and then possibly pack it in the jar file
    • You need to build two separate dll’s and so’s to cover 32bit and 64bit platforms.
calling jni code from java
Calling JNI Code From Java

package edu.syr.distobjects.jniexample;

public class FirstExample{

//it is good to make public wrappers around

//native methods

public void printString(String str){

doPrintString(str);

}

//the native keyword it present here

private native void doPrintString(String str);

}

creating the c c headers
Creating the C/C++ Headers
  • Directory structure:
    • netbeans_root
      • build
        • classes
          • edu
            • syr
              • distobjects
                • jniexample
      • src
          • edu
            • syr
              • distobjects
                • jniexample
      • native (you need to make this directory)
  • Linux:
    • $ cd /path/to/netbeans_root/build/classes
    • $ javahedu.syr.distobjects.jniexample.FirstExample
    • $ mv edu_syr_distobjects_jniexample_FirstExample.h../../native/
  • Windows:
    • $ cd \path\to\netbeans_root\build\classes
    • $ “C:\Program Files (x86)\Java\jkd1.6.0_26\bin\javah”edu.syr.distobjects.jniexample.FirstExample
    • $ move edu_syr_distobjects_jniexample_FirstExample.h..\..\native\
created c c header
Created C/C++ Header

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class edu_syr_distobjects_jniexample_FirstExample */

#ifndef _Included_edu_syr_distobjects_jniexample_FirstExample

#define _Included_edu_syr_distobjects_jniexample_FirstExample

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: edu_syr_distobjects_jniexample_FirstExample

* Method: doPrintString

* Signature: (Ljava/lang/String;)V

*/

JNIEXPORT void JNICALL Java_edu_syr_distobjects_jniexample_FirstExample_doPrintString

(JNIEnv *, jobject, jstring);

#ifdef __cplusplus

}

#endif

#endif

copy prototype to cpp file
Copy Prototype to .cpp File

#include “edu_syr_distobjects_jniexample_FirstExample.h”

JNIEXPORT void JNICALL Java_edu_syr_distobjects_jniexample_FirstExample_doPrintString

(JNIEnv* env, jobjectthis_obj, jstringstr)

{}

Note I gave names to env, this_obj, and str.

env: Every JNI function is passed a JNIEnv pointer

this_obj: Represents the managed “this” pointer

str: The only argument to the method in the Java code

implement a cout
Implement a cout

#include “edu_syr_distobjects_jniexample_FirstExample.h”

#include <iostream>

JNIEXPORT void JNICALL Java_edu_syr_distobjects_jniexample_FirstExample_doPrintString

(JNIEnv * env, jobjectthis_obj, jstringstr)

{

intlen = (*env)->GetStringLength(env, str);

char * nstr = new char[len];

(*env)->GetStringUTFRegion(env, str, 0, len, nstr);

std::cout << nstr << std::endl;

delete [] nstr;}

build the dll
Build the .dll

Put this in cl_options.txt (on one line)

/I"C:\Program Files\Java\jdk1.6.0_26\include“

/I"C:\Program Files\Java\jdk1.6.0_26\include\win32“

FirstExample.cpp

/DLL

/OUT:first_example.dll

/MACHINE:X64

Make a native_build.bat (keep lines separate)

"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" amd64

cl @cl_options.txt

load the dll in java
Load the .dll in Java

package edu.syr.distobjects.jniexample;

import java.io.File;

public class FirstExample {

//called during first initialization of FirstExampleclass

static {

//load requires an absolute path and this method ensures that File file = new File(“first_example.dll”);

System.load(file.getAbsolutePath());

}

public void printString(String str){

doPrintString(str);

}

private native void doPrintString(String str);

}

distributing the dll with a jar
Distributing the .dll with a .jar

In netbeans if you create a package (folder) and then have your build process place the .dll in the folder, it will be included in the .jar

public class BinaryLoader {

public void extractBinary(String filename) throws Exception {

String path = "/edu/syr/distobjects/jniexample/native/"+filename;

InputStreamis = BinaryLoader.class.getResourceAsStream(path);

OutputStreamos = new FileOutputStream(filename);

while(true){

byte[] buffer = new byte[32*1024];

intlen = is.read(buffer);

if(len== -1) { break; }

os.write(buffer, 0, len);

}

os.flush(); os.close(); is.close();

}

}

saving state in a cpp
Saving State In a cpp
  • You can save state in a high performance way by using static globals in a cpp
    • But all instances of a class will share that state
  • A slower way is to save state back to a Java Field

void setLongField(JNIEnv * env, jobjectobj, long value){

jclassthis_class = (*env)->GetObjectClass(env, obj);

jfieldIDfid = (*env)->GetFieldID(env, this_class, “m_FieldName”, "J");

(*env)->SetLongField(env, obj, fid, value);

}

java type strings
Java Type Strings
  • Previously we passed in “J” into GetFieldID
    • B = byte
    • C = char
    • D = double
    • F = float
    • I = int
    • J = long
    • S = short
    • V = void
    • Z = boolean
    • Ljava/lang/String; = String
    • Ljava/lang/Object; = Object
    • Lfully/qualified/Classname = fully.qualified.Classsname
    • [B – single dimensional byte array
    • [[B – two dimensional byte array
    • [Ljava/lang/String; - one dimensional string array
calling a java method
Calling a Java Method

jbyteArraylist_get(JNIEnv* env, jobjectlist, int index){

jmethodID mid;

jclasslist_interface = (*env)->FindClass(env, "java/util/List");

mid = (*env)->GetMethodID(env, list_interface, "get", "(I)Ljava/lang/Object;");

return (*env)->CallObjectMethod(env, list, mid, index);

}

  • “java/util/List” – interface or class name
  • “get” – method name
  • “(I)Ljava/lang/Object;” – a method that accepts an int as a parameter and returns a Ljava/lang/Object;
  • jbyteArray – a byte[]
  • In Java, the list was declared as:
    • List<byte[]> list;
jni field functions
JNI Field Functions
  • Based on Field Type:
    • GetObjectField
    • GetBooleanField
    • GetByteField
    • GetCharField
    • GetShortField
    • GetIntField
    • GetLongField
    • GetFloatField
    • GetDoubleField
  • Corresponding setters are like:
    • SetObjectField
jni method invocation functions
JNI Method Invocation Functions
  • Based on return type:
    • CallObjectMethod
    • CallBooleanMethod
    • CallByteMethod
    • CallCharMethod
    • CallShortMethod
    • CallIntMethod
    • CallLongMethod
    • CallFloatMethod
    • CallDoubleMethod
    • CallVoidMethod
jni array functions
JNI Array Functions
  • Based on Array Type:
    • GetBooleanArrayElements
    • GetByteArrayElements
    • GetCharArrayElements
    • GetShortArrayElements
    • GetIntArrayElements
    • GetLongArrayElements
    • GetFloatArrayElements
    • GetDoubleArrayElements
  • Corresponding releases need to be called like:
    • ReleaseBooleanArrayElements
  • Array length:
    • GetArrayLength
  • Arrays of objects: can only get one at a time because you can’t know the size of an object to store in a regular C style array
    • GetObjectArrayElement
    • SetObjectArrayElement
example of jni array copy
Example of JNI Array Copy

JNIEXPORT void JNICALL Java_edu_syr_pcpratts_rootbeer_ArrayMemory_doWriteIntArray

(JNIEnv *env, jobjectthis_obj, jintArray array, jlong ref, jintlen){

char * dest = (char *) ref;

jint* narray = (*env)->GetIntArrayElements(env, array, JNI_FALSE);

memcpy(dest, narray, len*sizeof(int));

(*env)->ReleaseIntArrayElements(env, array, narray, JNI_ABORT);

}

jlong ref was previously allocated in the C++ code using new. You can easily save any pointer in C++ in a Java field using a long. ref was saved as a member field in the Java class.

JNI_FALSE and JNI_ABORT have to deal with memory pinning and copying back of the change array into the java runtime. I can’t find a reference right now for these

real world usage of jni
Real World Usage of JNI
  • Rootbeer: tool to make it easier to program GPUs from Java
    • All the GPU vendors give C bindings to their API.
    • API allows to:
      • Create/Destroy GPU memory
      • Copy from CPU memory to GPU memory
      • Query how many sub-processors a GPU has
      • Compile CUDA programs to a binary for the GPU
      • Launch jobs onto the GPU
slide19
GPUs
  • GPU = Graphics Processing Unit
    • Specialized processor originally made only to feed Monitor with byte buffer
    • A device has on the order of 512 cores!
    • Each core is quite simple and slow:
      • No branch prediction or out of order execution
      • Clock rate is 1.3 Ghz range
    • Groups of 32 cores all have to be doing the same thing
      • They share instruction fetch hardware
    • Really hard to program
      • Need to learn special programming language to execute on the GPU (CUDA)
      • Need to manually serialize all of your complex classes in C/C++ to arrays (this may have changed recently…need to check)
      • Need to find huge amounts of parallelism in original program to get a speedup
        • Getting a speedup is the only reason to use a GPU
        • Naïve Dense matrix multiplication can easily be sped up 100X
rootbeer
Rootbeer
  • Rootbeer allows the developer to program in Java and it automatically:
    • Creates a CUDA program from analyzing Java Bytecode (with the help of the Soot Java Optimization Framework)
    • Creates Java Bytecode that can (de)serialize CPU memory to GPU memory in a high performance manner
    • Gives a Java interface for automatically launching these jobs on the GPU
rootbeer status
Rootbeer Status
  • By the end of summer 2012 there will be a public release of Rootbeer available for people to use
    • We currently have a non-optimized version that is highly tested:
      • 20K SLOC product code
      • 5k SLOC test code
      • All tests pass covering all aspects of the Java programming language except:
        • Sleeping while inside a monitor
        • Reflection
        • Dynamic methods in Java (recently added to Java, makes static analysis really hard)
        • Java Code that uses JNI…
        • Garbage collection
references
References

http://dev.kanngard.net/Permalinks/ID_20050509144235.html

http://docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html

http://java.sun.com/docs/books/jni/html/jniTOC.html

ad