SlideShare una empresa de Scribd logo
1 de 71
Descargar para leer sin conexión
JNI
@DroidsOnRoids
@GDG Wrocław
karol.wrotniak@droidsonroids.pl
koral--
Karol Wrótniak
karol-wrotniak
@karol.wrotniak
• Java Native Interface
• Native:
• Platform-specific shared library (.dll, .so, .dylib)
• Non-hybrid mobile app, React Native
• C, C++
• Call native functions from Java and vice versa
• Other JVM languages supported
• JNI ≠ JNA
Overview
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
static {
System.loadLibrary("foo");
}
public native int getTextLength(String text);
#include <jni.h>
JNIEXPORT
jint
JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength(
JNIEnv *env,
jobject thiz,
jstring text
) {
return (*env)->GetStringUTFLength(env, text);
}
foo.c:
Foo.java:
• Reuse existing native libraries
• Hinder reverse-engineering
• Increase performance (in certain cases only)
• computation
• Implement operations not available in Java:
• System clock - System.currentTimeMillis()
• Filesystem access
• other OS-specific features
Why JNI?
Sample projects using JNI
• System.loadLibrary("foo")
• System.mapLibraryName(“foo”) ➔ "libfoo.so"
• java.library.path property
• System.load("/usr/local/lib/libfoo.so")
Java API
• jbyte, jchar, jshort, jint, jlong, jfloat, jdouble
• jboolean: JNI_TRUE, JNI_FALSE
• jstring, jthrowable
• jarray, jintarray...
• jclass, jobject
• jmethodID, jfieldID
JNI types
Calling Java from C
jclass mathClass = (*env)->FindClass(env, "java/lang/Math");
jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass,
"min", "(JJ)J");
jlong min = (*env)->CallStaticLongMethod(env, mathClass,
minMethodID, x, y);
public static long min(long a, long b)
Calling Java from C
jclass mathClass = (*env)->FindClass(env, "java/lang/Math");
jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass,
"min", "(JJ)J");
jlong min = (*env)->CallStaticLongMethod(env, mathClass,
minMethodID, x, y);
public static long min(long a, long b)
Calling Java from C
jclass mathClass = (*env)->FindClass(env, "java/lang/Math");
jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass,
"min", "(JJ)J");
jlong min = (*env)->CallStaticLongMethod(env, mathClass,
minMethodID, x, y);
public static long min(long a, long b)
Calling Java from C
jclass mathClass = (*env)->FindClass(env, "java/lang/Math");
jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass,
"min", "(JJ)J");
jlong min = (*env)->CallStaticLongMethod(env, mathClass,
minMethodID, x, y);
public static long min(long a, long b)
Calling Java methods
jclass mathClass = (*env)->FindClass(env, "java/lang/Math");
jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass,
"min", "(JJ)J");
jlong min = (*env)->CallStaticLongMethod(env, mathClass,
minMethodID, x, y);
public static long min(long a, long b)
Accessing Java fields
jobject calendar = …
jclass calendar_class = (*env)->GetObjectClass(env, calendar);
jfieldID time_field_id = (*env)->GetFieldID(env, calendar_class,
"time", "J");
jlong time = (*env)->GetLongField(env, calendar, time_field_id);
Creating Java objects
jclass foo_class = (*env)->FindClass(env,
"pl/droidsonroids/ndkdemo/Foo");
jmethodID constructor_id = (*env)->GetMethodID(env, foo_class,
"<init>", "()V");
jobject foo = (*env)->NewObject(env, foo_class, constructor_id);
Creating Java objects
jclass foo_class = (*env)->FindClass(env,
"pl/droidsonroids/ndkdemo/Foo");
jmethodID constructor_id = (*env)->GetMethodID(env, foo_class,
"<init>", "()V");
jobject foo = (*env)->NewObject(env, foo_class, constructor_id);
Creating Java objects
jobject foo = (*env)->AllocObject(env, foo_class);
Type signatures
Type signature Java type Example
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L<FQCN>; FQCN Lcom/foo/Foo;
[<type> type[] [Z
V void
javap -s <class file>
abstract ArrayList<String> foo(String[] a, boolean b);
([Ljava/lang/String;Z)Ljava/util/ArrayList;
• Local
• Global
• WeakGlobal (weaker than Java Weak and Soft)
Reference types
Local references
jobject persistent_foo;
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(
JNIEnv *env,
jobject thiz,
jobject foo
) {
persistent_foo = foo;
printf("foo");
}
Local reference
Global References
jobject persistent_foo;
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(
JNIEnv *env,
jobject thiz,
jobject foo
) {
persistent_foo = (*env)->NewGlobalRef(env, foo);
printf("foo");
}
(*env)->DeleteGlobalRef(env, persistent_foo);
Finalizers
public final class Foo {
@Override
protected void finalize() throws Throwable {
releaseBar(bar);
super.finalize();
}
private final long bar;
public Foo() {
bar = createBar();
}
private native long createBar();
private native void releaseBar(long bar);
}
Finalizers
public final class Foo {
@Override
protected void finalize() throws Throwable {
releaseBar(bar);
super.finalize();
}
private final long bar;
public Foo() {
bar = createBar();
}
private native long createBar();
private native void releaseBar(long bar);
}
Finalizers
public final class Foo {
@Override
protected void finalize() throws Throwable {
releaseBar(bar);
super.finalize();
}
private final long bar;
public Foo() {
bar = createBar();
}
private native long createBar();
private native void releaseBar(long bar);
}
Finalizer guardian
public class Foo {
@SuppressWarnings("unused")
private final Object finalizer = new Object() {
@Override
protected void finalize() throws Throwable {
releaseBar(bar);
}
};
private final long bar;
public Foo() {
bar = createBar();
}
private native long createBar();
private native void releaseBar(long bar);
}
JNI_OnLoad JNI_OnUnload
void *foo;
JavaVM *global_vm;
JNIEXPORT
jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
global_vm = vm;
if (!init()) {
return JNI_ERR;
}
foo = malloc(1);
return JNI_VERSION_1_8;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
free(foo);
}
JNI_OnLoad JNI_OnUnload
void *foo;
JavaVM *global_vm;
JNIEXPORT
jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
global_vm = vm;
if (!init()) {
return JNI_ERR;
}
foo = malloc(1);
return JNI_VERSION_1_8;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
free(foo);
}
JNI_OnLoad JNI_OnUnload
void *foo;
JavaVM *global_vm;
JNIEXPORT
jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
global_vm = vm;
if (!init()) {
return JNI_ERR;
}
foo = malloc(1);
return JNI_VERSION_1_8;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
free(foo);
}
JNI_OnLoad JNI_OnUnload
void *foo;
JavaVM *global_vm;
JNIEXPORT
jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
global_vm = vm;
if (!init()) {
return JNI_ERR;
}
foo = malloc(1);
return JNI_VERSION_1_8;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
free(foo);
}
Attaching to native threads
void *doSomething(void *args) {
JavaVMAttachArgs attach_args = {
.group = NULL,
.name = "WorkerThread",
.version = JNI_VERSION_1_6
};
JNIEnv *env;
if ((*global_vm)->AttachCurrentThread(global_vm, &env,
&attach_args) == JNI_OK) {
//JNI function calls
(*global_vm)->DetachCurrentThread(global_vm);
}
}
Attaching to native threads
void *doSomething(void *args) {
JavaVMAttachArgs attach_args = {
.group = NULL,
.name = "WorkerThread",
.version = JNI_VERSION_1_6
};
JNIEnv *env;
if ((*global_vm)->AttachCurrentThread(global_vm, &env,
&attach_args) == JNI_OK) {
//JNI function calls
(*global_vm)->DetachCurrentThread(global_vm);
}
}
Attaching to native threads
void *doSomething(void *args) {
JavaVMAttachArgs attach_args = {
.group = NULL,
.name = "WorkerThread",
.version = JNI_VERSION_1_6
};
JNIEnv *env;
if ((*global_vm)->AttachCurrentThread(global_vm, &env,
&attach_args) == JNI_OK) {
//JNI function calls
(*global_vm)->DetachCurrentThread(global_vm);
}
}
• AttachCurrentThreadAsDaemon
• Detach using pthread_key_create destructor
Registering native methods
//Foo.java
public native int plus(int a, int b);
//Foo.c
static jint add(JNIEnv *env, jobject thiz, jint a, jint b) {
return a + b;
}
JNIEXPORT
jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNINativeMethod methods[] = {
{"plus", "(II)I", (void *) add}
};
return JNI_VERSION_1_6;
}
Registering native methods
//Foo.java
public native int plus(int a, int b);
//Foo.c
static jint add(JNIEnv *env, jobject thiz, jint a, jint b) {
return a + b;
}
JNIEXPORT
jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNINativeMethod methods[] = {
{"plus", "(II)I", (void *) add}
};
JNIEnv *env;
(*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6);
jclass foo_class = (*env)->FindClass(env,
"pl/droidsonroids/ndkdemo/Foo");
(*env)->RegisterNatives(env, foo_class, methods, 1);
return JNI_VERSION_1_6;
}
Registering native methods
//Foo.java
public native int plus(int a, int b);
//Foo.c
static jint add(JNIEnv *env, jobject thiz, jint a, jint b) {
return a + b;
}
• C++ exceptions are not converted to Java counterparts
• JNI functions:
• ExceptionCheck
• ExceptionOccured
• ExceptionClear
• FatalError
• ExceptionDescribe
Handling exceptions
(*env)->CallVoidMethod(env, foo, fooMethodID);
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
(*env)->ExceptionClear(env);
(*env)->CallVoidMethod(env, foo, barMethodID);
}
Catching exceptions
catch
• Need to clear exception or return before JNI calls
jclass exceptionClass = (*env)->FindClass(env, "android/system/
ErrnoException");
jmethodID const constructorID = (*env)->GetMethodID(env,
exceptionClass, "<init>", "(Ljava/lang/String;I)V");
jobject exception = (*env)->NewObject(env, exceptionClass,
constructorID, number);
(*env)->Throw(env, exception);
Throwing Exceptions
jclass exceptionClass = ...
(*env)->ThrowNew(env, exceptionClass, "Foo failed");
Throwing Exceptions
Arrays
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz,
jintArray points) {
jsize length = (*env)->GetArrayLength(env, points);
jint *native_points = (*env)->GetIntArrayElements(env, points,
NULL);
//...
(*env)->ReleaseIntArrayElements(env, points, native_points, 0);
}
Arrays
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz,
jintArray points) {
jsize length = (*env)->GetArrayLength(env, points);
jint *native_points = (*env)->GetIntArrayElements(env, points,
NULL);
//...
(*env)->ReleaseIntArrayElements(env, points, native_points, 0);
}
Arrays
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz,
jintArray points) {
jsize length = (*env)->GetArrayLength(env, points);
jint *native_points = (*env)->GetIntArrayElements(env, points,
NULL);
//...
(*env)->ReleaseIntArrayElements(env, points, native_points, 0);
}
Release mode
Arrays
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz,
jintArray points) {
jsize length = (*env)->GetArrayLength(env, points);
jint *native_points = (*env)->GetIntArrayElements(env, points,
NULL);
//...
(*env)->ReleaseIntArrayElements(env, points, native_points, 0);
}
*isCopy
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray
points) {
jsize start = 0;
jsize size = 2;
jint native_points[2];
(*env)->GetIntArrayRegion(env, points, start, size, native_points);
native_points[0] = native_points[1];
(*env)->SetIntArrayRegion(env, points, start, size, native_points);
}
Arrays
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz,
jintArray points) {
jsize length = (*env)->GetArrayLength(env, points);
jint *native_points = (*env)->GetIntArrayElements(env, points,
NULL);
//...
(*env)->ReleaseIntArrayElements(env, points, native_points, 0);
}
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray
points) {
jsize start = 0;
jsize size = 2;
jint native_points[2];
(*env)->GetIntArrayRegion(env, points, start, size, native_points);
native_points[0] = native_points[1];
(*env)->SetIntArrayRegion(env, points, start, size, native_points);
}
Arrays
JNIEXPORT void JNICALL
Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz,
jintArray points) {
jsize length = (*env)->GetArrayLength(env, points);
jint *native_points = (*env)->GetIntArrayElements(env, points,
NULL);
//...
(*env)->ReleaseIntArrayElements(env, points, native_points, 0);
}
GC compaction
• Disable GC between Get and Release
• Pin
• Copy
Java heap
native heap
Mode Copy back Free buffer
0 ✓ ✓
JNI_COMMIT ✓ ❌
JNI_ABORT ❌ ✓
Release modes & isCopy
Need to release with another mode
*isCopy == JNI_FALSE:
• skip useless commit
• restore original contents before abort
Direct byte buffers
JNIEXPORT
jobject JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(
JNIEnv *env,
jobject thiz,
jobject buffer
) {
void *foo = (*env)->GetDirectBufferAddress(env, buffer);
jlong capacity = (*env)->GetDirectBufferCapacity(env,
buffer);
//...
}
Direct byte buffers
JNIEXPORT
jobject JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(
JNIEnv *env,
jobject thiz,
jobject buffer
) {
void *foo = (*env)->GetDirectBufferAddress(env, buffer);
jlong capacity = (*env)->GetDirectBufferCapacity(env,
buffer);
//...
}
Direct byte buffers
JNIEXPORT
jobject JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(
JNIEnv *env,
jobject thiz,
jobject buffer
) {
void* bar = mmap(…
return (*env)->NewDirectByteBuffer(env, bar, capacity);
}
• underlying buffer has to be released
• Null-terminated
• No null byte inside
• U+0000 -> 0xC0 0x80
• 4-byte UTF-8 format encoded using 2 x 3-bytes
• JNI functions:
• *StringUTF* - modified UTF-8
• native string APIs
• *String* - standard UTF-8
• raw bytes from native sources
Modified UTF-8
Synchronization
(*env)->MonitorEnter(env, thiz);
//JNI function calls
(*env)->MonitorExit(env, thiz);
//or
(*global_vm)->DetachCurrentThread(global_vm);
JNA - Java Native Access
double modf(double x, double *intptr);
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ?
"msvcrt" : "c"),
CLibrary.class);
double modf(double x, DoubleByReference intptr);
}
DoubleByReference intptrReference = new DoubleByReference();
double fraction = CLibrary.INSTANCE.modf(1.234, intptrReference);
System.out.println(fraction);
System.out.println(intptrReference.getValue());
JNA - Java Native Access
double modf(double x, double *intptr);
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ?
"msvcrt" : "c"),
CLibrary.class);
double modf(double x, DoubleByReference intptr);
}
DoubleByReference intptrReference = new DoubleByReference();
double fraction = CLibrary.INSTANCE.modf(1.234, intptrReference);
System.out.println(fraction);
System.out.println(intptrReference.getValue());
JNA - Java Native Access
double modf(double x, double *intptr);
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ?
"msvcrt" : "c"),
CLibrary.class);
double modf(double x, DoubleByReference intptr);
}
DoubleByReference intptrReference = new DoubleByReference();
double fraction = CLibrary.INSTANCE.modf(1.234, intptrReference);
System.out.println(fraction);
System.out.println(intptrReference.getValue());
JNA - Java Native Access
double modf(double x, double *intptr);
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ?
"msvcrt" : "c"),
CLibrary.class);
double modf(double x, DoubleByReference intptr);
}
DoubleByReference intptrReference = new DoubleByReference();
double fraction = CLibrary.INSTANCE.modf(1.234, intptrReference);
System.out.println(fraction);
System.out.println(intptrReference.getValue());
Android POSIX API
android.system.Os
android.system.OsConstants
static
FileDescriptor
accept(FileDescriptor fd, 
InetSocketAddress peerAddress)
See accept(2).
static void chown(String path, int uid, int gid)
See chown(2).
public static
final int
SIGSTOP
static boolean WIFEXITED(int status)
Tests whether the child exited normally.
Traps
• Signature inconsistency
• Exempt from obfuscation:
• Native methods
• Everything called from native
• Leaking this in finalize
Incomplete initialization
class Foo {
@NonNull private final File file;
private final FileOutputStream stream;
Foo(@NonNull File file) throws IOException {
stream = new FileOutputStream(file);
stream.write(0);
this.file = file;
}
@Override
protected void finalize() throws Throwable {
System.out.println("Closing " + file.getPath());
try {
stream.close();
} finally {
super.finalize();
}
}
}
IOException
NullPointerException
1. Java Native Interface Specification
2. JNI Tips
3. The Java™ Native Interface
Programmer’s Guide and Specification
References
Q&A

Más contenido relacionado

La actualidad más candente

Fast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaFast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaCharles Nutter
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기Arawn Park
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeAijaz Ansari
 
3. Объекты, классы и пакеты в Java
3. Объекты, классы и пакеты в Java3. Объекты, классы и пакеты в Java
3. Объекты, классы и пакеты в JavaDEVTYPE
 
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBTDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBtdc-globalcode
 
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...tdc-globalcode
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns ReconsideredAlex Miller
 
Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012Anton Arhipov
 
Objective-C Crash Course for Web Developers
Objective-C Crash Course for Web DevelopersObjective-C Crash Course for Web Developers
Objective-C Crash Course for Web DevelopersJoris Verbogt
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftGiordano Scalzo
 
The Macronomicon
The MacronomiconThe Macronomicon
The MacronomiconMike Fogus
 
Do we need Unsafe in Java?
Do we need Unsafe in Java?Do we need Unsafe in Java?
Do we need Unsafe in Java?Andrei Pangin
 
JavaScript Survival Guide
JavaScript Survival GuideJavaScript Survival Guide
JavaScript Survival GuideGiordano Scalzo
 

La actualidad más candente (20)

Fast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaFast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible Java
 
The Xtext Grammar Language
The Xtext Grammar LanguageThe Xtext Grammar Language
The Xtext Grammar Language
 
groovy & grails - lecture 3
groovy & grails - lecture 3groovy & grails - lecture 3
groovy & grails - lecture 3
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCode
 
Presentatie - Introductie in Groovy
Presentatie - Introductie in GroovyPresentatie - Introductie in Groovy
Presentatie - Introductie in Groovy
 
NIO and NIO2
NIO and NIO2NIO and NIO2
NIO and NIO2
 
3. Объекты, классы и пакеты в Java
3. Объекты, классы и пакеты в Java3. Объекты, классы и пакеты в Java
3. Объекты, классы и пакеты в Java
 
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBTDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
 
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns Reconsidered
 
Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012
 
Objective-C Crash Course for Web Developers
Objective-C Crash Course for Web DevelopersObjective-C Crash Course for Web Developers
Objective-C Crash Course for Web Developers
 
Rust ⇋ JavaScript
Rust ⇋ JavaScriptRust ⇋ JavaScript
Rust ⇋ JavaScript
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in Swift
 
The Macronomicon
The MacronomiconThe Macronomicon
The Macronomicon
 
Do we need Unsafe in Java?
Do we need Unsafe in Java?Do we need Unsafe in Java?
Do we need Unsafe in Java?
 
JavaScript Survival Guide
JavaScript Survival GuideJavaScript Survival Guide
JavaScript Survival Guide
 

Similar a JNI - Java & C in the same project

A topology of memory leaks on the JVM
A topology of memory leaks on the JVMA topology of memory leaks on the JVM
A topology of memory leaks on the JVMRafael Winterhalter
 
Patterns for JVM languages JokerConf
Patterns for JVM languages JokerConfPatterns for JVM languages JokerConf
Patterns for JVM languages JokerConfJaroslaw Palka
 
The definitive guide to java agents
The definitive guide to java agentsThe definitive guide to java agents
The definitive guide to java agentsRafael Winterhalter
 
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018 Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018 Codemotion
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниStfalcon Meetups
 
AST Transformations
AST TransformationsAST Transformations
AST TransformationsHamletDRC
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)HamletDRC
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015Charles Nutter
 
Ast transformations
Ast transformationsAst transformations
Ast transformationsHamletDRC
 
Androidの本当にあった怖い話
Androidの本当にあった怖い話Androidの本当にあった怖い話
Androidの本当にあった怖い話Yusuke Yamamoto
 
Web2Day 2017 - Concilier DomainDriveDesign et API REST
Web2Day 2017 - Concilier DomainDriveDesign et API RESTWeb2Day 2017 - Concilier DomainDriveDesign et API REST
Web2Day 2017 - Concilier DomainDriveDesign et API RESTNicolas Faugout
 
Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014Jaroslaw Palka
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)James Titcumb
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationIvan Dolgushin
 

Similar a JNI - Java & C in the same project (20)

A topology of memory leaks on the JVM
A topology of memory leaks on the JVMA topology of memory leaks on the JVM
A topology of memory leaks on the JVM
 
Patterns for JVM languages JokerConf
Patterns for JVM languages JokerConfPatterns for JVM languages JokerConf
Patterns for JVM languages JokerConf
 
The definitive guide to java agents
The definitive guide to java agentsThe definitive guide to java agents
The definitive guide to java agents
 
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018 Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
 
Android and cpp
Android and cppAndroid and cpp
Android and cpp
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камни
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015
 
Introduzione a C#
Introduzione a C#Introduzione a C#
Introduzione a C#
 
Java byte code in practice
Java byte code in practiceJava byte code in practice
Java byte code in practice
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Object-oriented Basics
Object-oriented BasicsObject-oriented Basics
Object-oriented Basics
 
Androidの本当にあった怖い話
Androidの本当にあった怖い話Androidの本当にあった怖い話
Androidの本当にあった怖い話
 
Realm to Json & Royal
Realm to Json & RoyalRealm to Json & Royal
Realm to Json & Royal
 
Web2Day 2017 - Concilier DomainDriveDesign et API REST
Web2Day 2017 - Concilier DomainDriveDesign et API RESTWeb2Day 2017 - Concilier DomainDriveDesign et API REST
Web2Day 2017 - Concilier DomainDriveDesign et API REST
 
Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
Poly-paradigm Java
Poly-paradigm JavaPoly-paradigm Java
Poly-paradigm Java
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code Generation
 

Último

Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 

Último (20)

Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 

JNI - Java & C in the same project

  • 2. • Java Native Interface • Native: • Platform-specific shared library (.dll, .so, .dylib) • Non-hybrid mobile app, React Native • C, C++ • Call native functions from Java and vice versa • Other JVM languages supported • JNI ≠ JNA Overview
  • 3. static { System.loadLibrary("foo"); } public native int getTextLength(String text); Foo.java:
  • 4. static { System.loadLibrary("foo"); } public native int getTextLength(String text); Foo.java:
  • 5. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 6. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 7. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 8. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 9. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 10. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 11. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 12. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 13. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 14. static { System.loadLibrary("foo"); } public native int getTextLength(String text); #include <jni.h> JNIEXPORT jint JNICALL Java_pl_droidsonroids_ndkdemo_Foo_getTextLength( JNIEnv *env, jobject thiz, jstring text ) { return (*env)->GetStringUTFLength(env, text); } foo.c: Foo.java:
  • 15. • Reuse existing native libraries • Hinder reverse-engineering • Increase performance (in certain cases only) • computation • Implement operations not available in Java: • System clock - System.currentTimeMillis() • Filesystem access • other OS-specific features Why JNI?
  • 17. • System.loadLibrary("foo") • System.mapLibraryName(“foo”) ➔ "libfoo.so" • java.library.path property • System.load("/usr/local/lib/libfoo.so") Java API
  • 18. • jbyte, jchar, jshort, jint, jlong, jfloat, jdouble • jboolean: JNI_TRUE, JNI_FALSE • jstring, jthrowable • jarray, jintarray... • jclass, jobject • jmethodID, jfieldID JNI types
  • 19. Calling Java from C jclass mathClass = (*env)->FindClass(env, "java/lang/Math"); jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass, "min", "(JJ)J"); jlong min = (*env)->CallStaticLongMethod(env, mathClass, minMethodID, x, y); public static long min(long a, long b)
  • 20. Calling Java from C jclass mathClass = (*env)->FindClass(env, "java/lang/Math"); jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass, "min", "(JJ)J"); jlong min = (*env)->CallStaticLongMethod(env, mathClass, minMethodID, x, y); public static long min(long a, long b)
  • 21. Calling Java from C jclass mathClass = (*env)->FindClass(env, "java/lang/Math"); jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass, "min", "(JJ)J"); jlong min = (*env)->CallStaticLongMethod(env, mathClass, minMethodID, x, y); public static long min(long a, long b)
  • 22. Calling Java from C jclass mathClass = (*env)->FindClass(env, "java/lang/Math"); jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass, "min", "(JJ)J"); jlong min = (*env)->CallStaticLongMethod(env, mathClass, minMethodID, x, y); public static long min(long a, long b)
  • 23. Calling Java methods jclass mathClass = (*env)->FindClass(env, "java/lang/Math"); jmethodID minMethodID = (*env)->GetStaticMethodID(env, mathClass, "min", "(JJ)J"); jlong min = (*env)->CallStaticLongMethod(env, mathClass, minMethodID, x, y); public static long min(long a, long b)
  • 24. Accessing Java fields jobject calendar = … jclass calendar_class = (*env)->GetObjectClass(env, calendar); jfieldID time_field_id = (*env)->GetFieldID(env, calendar_class, "time", "J"); jlong time = (*env)->GetLongField(env, calendar, time_field_id);
  • 25. Creating Java objects jclass foo_class = (*env)->FindClass(env, "pl/droidsonroids/ndkdemo/Foo"); jmethodID constructor_id = (*env)->GetMethodID(env, foo_class, "<init>", "()V"); jobject foo = (*env)->NewObject(env, foo_class, constructor_id);
  • 26. Creating Java objects jclass foo_class = (*env)->FindClass(env, "pl/droidsonroids/ndkdemo/Foo"); jmethodID constructor_id = (*env)->GetMethodID(env, foo_class, "<init>", "()V"); jobject foo = (*env)->NewObject(env, foo_class, constructor_id);
  • 27. Creating Java objects jobject foo = (*env)->AllocObject(env, foo_class);
  • 28. Type signatures Type signature Java type Example Z boolean B byte C char S short I int J long F float D double L<FQCN>; FQCN Lcom/foo/Foo; [<type> type[] [Z V void javap -s <class file> abstract ArrayList<String> foo(String[] a, boolean b); ([Ljava/lang/String;Z)Ljava/util/ArrayList;
  • 29. • Local • Global • WeakGlobal (weaker than Java Weak and Soft) Reference types
  • 30. Local references jobject persistent_foo; JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo( JNIEnv *env, jobject thiz, jobject foo ) { persistent_foo = foo; printf("foo"); } Local reference
  • 31. Global References jobject persistent_foo; JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo( JNIEnv *env, jobject thiz, jobject foo ) { persistent_foo = (*env)->NewGlobalRef(env, foo); printf("foo"); } (*env)->DeleteGlobalRef(env, persistent_foo);
  • 32. Finalizers public final class Foo { @Override protected void finalize() throws Throwable { releaseBar(bar); super.finalize(); } private final long bar; public Foo() { bar = createBar(); } private native long createBar(); private native void releaseBar(long bar); }
  • 33. Finalizers public final class Foo { @Override protected void finalize() throws Throwable { releaseBar(bar); super.finalize(); } private final long bar; public Foo() { bar = createBar(); } private native long createBar(); private native void releaseBar(long bar); }
  • 34. Finalizers public final class Foo { @Override protected void finalize() throws Throwable { releaseBar(bar); super.finalize(); } private final long bar; public Foo() { bar = createBar(); } private native long createBar(); private native void releaseBar(long bar); }
  • 35. Finalizer guardian public class Foo { @SuppressWarnings("unused") private final Object finalizer = new Object() { @Override protected void finalize() throws Throwable { releaseBar(bar); } }; private final long bar; public Foo() { bar = createBar(); } private native long createBar(); private native void releaseBar(long bar); }
  • 36. JNI_OnLoad JNI_OnUnload void *foo; JavaVM *global_vm; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { global_vm = vm; if (!init()) { return JNI_ERR; } foo = malloc(1); return JNI_VERSION_1_8; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { free(foo); }
  • 37. JNI_OnLoad JNI_OnUnload void *foo; JavaVM *global_vm; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { global_vm = vm; if (!init()) { return JNI_ERR; } foo = malloc(1); return JNI_VERSION_1_8; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { free(foo); }
  • 38. JNI_OnLoad JNI_OnUnload void *foo; JavaVM *global_vm; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { global_vm = vm; if (!init()) { return JNI_ERR; } foo = malloc(1); return JNI_VERSION_1_8; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { free(foo); }
  • 39. JNI_OnLoad JNI_OnUnload void *foo; JavaVM *global_vm; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { global_vm = vm; if (!init()) { return JNI_ERR; } foo = malloc(1); return JNI_VERSION_1_8; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { free(foo); }
  • 40. Attaching to native threads void *doSomething(void *args) { JavaVMAttachArgs attach_args = { .group = NULL, .name = "WorkerThread", .version = JNI_VERSION_1_6 }; JNIEnv *env; if ((*global_vm)->AttachCurrentThread(global_vm, &env, &attach_args) == JNI_OK) { //JNI function calls (*global_vm)->DetachCurrentThread(global_vm); } }
  • 41. Attaching to native threads void *doSomething(void *args) { JavaVMAttachArgs attach_args = { .group = NULL, .name = "WorkerThread", .version = JNI_VERSION_1_6 }; JNIEnv *env; if ((*global_vm)->AttachCurrentThread(global_vm, &env, &attach_args) == JNI_OK) { //JNI function calls (*global_vm)->DetachCurrentThread(global_vm); } }
  • 42. Attaching to native threads void *doSomething(void *args) { JavaVMAttachArgs attach_args = { .group = NULL, .name = "WorkerThread", .version = JNI_VERSION_1_6 }; JNIEnv *env; if ((*global_vm)->AttachCurrentThread(global_vm, &env, &attach_args) == JNI_OK) { //JNI function calls (*global_vm)->DetachCurrentThread(global_vm); } } • AttachCurrentThreadAsDaemon • Detach using pthread_key_create destructor
  • 43. Registering native methods //Foo.java public native int plus(int a, int b); //Foo.c static jint add(JNIEnv *env, jobject thiz, jint a, jint b) { return a + b; }
  • 44. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNINativeMethod methods[] = { {"plus", "(II)I", (void *) add} }; return JNI_VERSION_1_6; } Registering native methods //Foo.java public native int plus(int a, int b); //Foo.c static jint add(JNIEnv *env, jobject thiz, jint a, jint b) { return a + b; }
  • 45. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNINativeMethod methods[] = { {"plus", "(II)I", (void *) add} }; JNIEnv *env; (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6); jclass foo_class = (*env)->FindClass(env, "pl/droidsonroids/ndkdemo/Foo"); (*env)->RegisterNatives(env, foo_class, methods, 1); return JNI_VERSION_1_6; } Registering native methods //Foo.java public native int plus(int a, int b); //Foo.c static jint add(JNIEnv *env, jobject thiz, jint a, jint b) { return a + b; }
  • 46. • C++ exceptions are not converted to Java counterparts • JNI functions: • ExceptionCheck • ExceptionOccured • ExceptionClear • FatalError • ExceptionDescribe Handling exceptions
  • 47. (*env)->CallVoidMethod(env, foo, fooMethodID); if ((*env)->ExceptionCheck(env) == JNI_TRUE) { (*env)->ExceptionClear(env); (*env)->CallVoidMethod(env, foo, barMethodID); } Catching exceptions catch • Need to clear exception or return before JNI calls
  • 48. jclass exceptionClass = (*env)->FindClass(env, "android/system/ ErrnoException"); jmethodID const constructorID = (*env)->GetMethodID(env, exceptionClass, "<init>", "(Ljava/lang/String;I)V"); jobject exception = (*env)->NewObject(env, exceptionClass, constructorID, number); (*env)->Throw(env, exception); Throwing Exceptions
  • 49. jclass exceptionClass = ... (*env)->ThrowNew(env, exceptionClass, "Foo failed"); Throwing Exceptions
  • 50. Arrays JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray points) { jsize length = (*env)->GetArrayLength(env, points); jint *native_points = (*env)->GetIntArrayElements(env, points, NULL); //... (*env)->ReleaseIntArrayElements(env, points, native_points, 0); }
  • 51. Arrays JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray points) { jsize length = (*env)->GetArrayLength(env, points); jint *native_points = (*env)->GetIntArrayElements(env, points, NULL); //... (*env)->ReleaseIntArrayElements(env, points, native_points, 0); }
  • 52. Arrays JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray points) { jsize length = (*env)->GetArrayLength(env, points); jint *native_points = (*env)->GetIntArrayElements(env, points, NULL); //... (*env)->ReleaseIntArrayElements(env, points, native_points, 0); } Release mode
  • 53. Arrays JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray points) { jsize length = (*env)->GetArrayLength(env, points); jint *native_points = (*env)->GetIntArrayElements(env, points, NULL); //... (*env)->ReleaseIntArrayElements(env, points, native_points, 0); } *isCopy
  • 54. JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray points) { jsize start = 0; jsize size = 2; jint native_points[2]; (*env)->GetIntArrayRegion(env, points, start, size, native_points); native_points[0] = native_points[1]; (*env)->SetIntArrayRegion(env, points, start, size, native_points); } Arrays JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray points) { jsize length = (*env)->GetArrayLength(env, points); jint *native_points = (*env)->GetIntArrayElements(env, points, NULL); //... (*env)->ReleaseIntArrayElements(env, points, native_points, 0); }
  • 55. JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray points) { jsize start = 0; jsize size = 2; jint native_points[2]; (*env)->GetIntArrayRegion(env, points, start, size, native_points); native_points[0] = native_points[1]; (*env)->SetIntArrayRegion(env, points, start, size, native_points); } Arrays JNIEXPORT void JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo(JNIEnv *env, jobject thiz, jintArray points) { jsize length = (*env)->GetArrayLength(env, points); jint *native_points = (*env)->GetIntArrayElements(env, points, NULL); //... (*env)->ReleaseIntArrayElements(env, points, native_points, 0); }
  • 56. GC compaction • Disable GC between Get and Release • Pin • Copy Java heap native heap
  • 57. Mode Copy back Free buffer 0 ✓ ✓ JNI_COMMIT ✓ ❌ JNI_ABORT ❌ ✓ Release modes & isCopy Need to release with another mode *isCopy == JNI_FALSE: • skip useless commit • restore original contents before abort
  • 58. Direct byte buffers JNIEXPORT jobject JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo( JNIEnv *env, jobject thiz, jobject buffer ) { void *foo = (*env)->GetDirectBufferAddress(env, buffer); jlong capacity = (*env)->GetDirectBufferCapacity(env, buffer); //... }
  • 59. Direct byte buffers JNIEXPORT jobject JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo( JNIEnv *env, jobject thiz, jobject buffer ) { void *foo = (*env)->GetDirectBufferAddress(env, buffer); jlong capacity = (*env)->GetDirectBufferCapacity(env, buffer); //... }
  • 60. Direct byte buffers JNIEXPORT jobject JNICALL Java_pl_droidsonroids_ndkdemo_Foo_foo( JNIEnv *env, jobject thiz, jobject buffer ) { void* bar = mmap(… return (*env)->NewDirectByteBuffer(env, bar, capacity); } • underlying buffer has to be released
  • 61. • Null-terminated • No null byte inside • U+0000 -> 0xC0 0x80 • 4-byte UTF-8 format encoded using 2 x 3-bytes • JNI functions: • *StringUTF* - modified UTF-8 • native string APIs • *String* - standard UTF-8 • raw bytes from native sources Modified UTF-8
  • 62. Synchronization (*env)->MonitorEnter(env, thiz); //JNI function calls (*env)->MonitorExit(env, thiz); //or (*global_vm)->DetachCurrentThread(global_vm);
  • 63. JNA - Java Native Access double modf(double x, double *intptr); public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class); double modf(double x, DoubleByReference intptr); } DoubleByReference intptrReference = new DoubleByReference(); double fraction = CLibrary.INSTANCE.modf(1.234, intptrReference); System.out.println(fraction); System.out.println(intptrReference.getValue());
  • 64. JNA - Java Native Access double modf(double x, double *intptr); public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class); double modf(double x, DoubleByReference intptr); } DoubleByReference intptrReference = new DoubleByReference(); double fraction = CLibrary.INSTANCE.modf(1.234, intptrReference); System.out.println(fraction); System.out.println(intptrReference.getValue());
  • 65. JNA - Java Native Access double modf(double x, double *intptr); public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class); double modf(double x, DoubleByReference intptr); } DoubleByReference intptrReference = new DoubleByReference(); double fraction = CLibrary.INSTANCE.modf(1.234, intptrReference); System.out.println(fraction); System.out.println(intptrReference.getValue());
  • 66. JNA - Java Native Access double modf(double x, double *intptr); public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class); double modf(double x, DoubleByReference intptr); } DoubleByReference intptrReference = new DoubleByReference(); double fraction = CLibrary.INSTANCE.modf(1.234, intptrReference); System.out.println(fraction); System.out.println(intptrReference.getValue());
  • 67. Android POSIX API android.system.Os android.system.OsConstants static FileDescriptor accept(FileDescriptor fd,  InetSocketAddress peerAddress) See accept(2). static void chown(String path, int uid, int gid) See chown(2). public static final int SIGSTOP static boolean WIFEXITED(int status) Tests whether the child exited normally.
  • 68. Traps • Signature inconsistency • Exempt from obfuscation: • Native methods • Everything called from native • Leaking this in finalize
  • 69. Incomplete initialization class Foo { @NonNull private final File file; private final FileOutputStream stream; Foo(@NonNull File file) throws IOException { stream = new FileOutputStream(file); stream.write(0); this.file = file; } @Override protected void finalize() throws Throwable { System.out.println("Closing " + file.getPath()); try { stream.close(); } finally { super.finalize(); } } } IOException NullPointerException
  • 70. 1. Java Native Interface Specification 2. JNI Tips 3. The Java™ Native Interface Programmer’s Guide and Specification References
  • 71. Q&A