古人学问无遗力,少壮工夫老始成。这篇文章主要讲述JNI on Chromium for Android相关的知识,希望能为你提供帮助。
OverviewJNI (java Native Interface) is the mechanism that enables Java code to call native functions, and native code to call Java functions.
- Native code calls into Java using apis from
< jni.h>
, which basically mirror Java‘s reflection APIs. - Java code calls native functions by declaring body-less functions with the
native
keyword, and then calling them as normal Java functions.
jni_generator
generates boiler-plate code with the goal of making our code:- easier to write, and
- typesafe.
jni_generator
uses regular expressions to parse .Java files, so don‘t do anything too fancy. E.g.:- Classes must be either explicitly imported, or are assumed to be in the same package. To use
java.lang
classes, add an explicit import. - Inner classes need to be referenced through the outer class. E.g.:
void call(Outer.Inner inner)
Exposing Native Methods
Without Crazy Linker:
- Java->
Native calls are exported from the shared library and lazily resolved by the runtime (via
dlsym()
).
- Java->
Native calls are explicitly registered with JNI on the native side. Explicit registration is necessary because crazy linker provides its own
dlsym()
, but JNI is hardcoded to use the system‘sdlsym()
.- The logic to explicitly register stubs is generated by
jni_registration_generator.py
.- This script finds all native methods by scanning all source
.java
files of an APK. Inefficient, but very convenient.
- This script finds all native methods by scanning all source
- Since
dlsym()
is not used in this case, we use a linker script to avoid the cost of exporting symbols from the shared library (refer to//build/config/android:hide_all_but_jni_onload
).
- The logic to explicitly register stubs is generated by
jni_registration_generator.py
exposes two registrations methods:RegisterNonMainDexNatives
- Registers native functions needed by multiple process types (e.g. Rendereres, GPU process).RegisterMainDexNatives
- Registers native functions needed only by the browser process.
Java methods just need to be annotated with
@CalledByNative
. The generated functions can be put into a namespace using
@JNINamespace("your_namespace")
.UsageBecause the generator does not generate any source files, generated headers must not be
#included
by multiple sources. If there are Java functions that need to be called by multiple sources, one source should be chosen to expose the functions to the others via additional wrapper functions.Calling Java -> Native
- Methods marked as
native
will have stubs generated for them that forward calls to C++ function (that you must write). - If the first parameter is a C++ object (e.g.
long mNativePointer
), then the bindings will automatically generate the appropriate cast and call into C++ code (JNI itself is only C).
- Methods annotated with
@CalledByNative
will have stubs generated for them. - Just call the generated stubs defined in generated
.h
files.
All pointers to Java objects must be registered with JNI in order to prevent garbage collection from invalidating them.
For Strings & Arrays - it‘s common practice to use the
//base/android/jni_*
helpers to convert them to
std::vectors
and
std::strings
as soon as possible.For other objects - use smart pointers to store them:
ScopedJavaLocalRef< >
- When lifetime is the current function‘s scope.ScopedJavaGlobalRef< >
- When lifetime is longer than the current function‘s scope.JavaObjectWeakGlobalRef< >
- Weak reference (do not prevent garbage collection).JavaParamRef< >
- Use to accept any of the above as a parameter to a function without creating a redundant registration.
Minimize the surface API between the two sides. Rather than calling multiple functions across boundaries, call only one (and then on the other side, call as many little functions as required).
If a Java object “owns” a native one, store the pointer via
"long mNativeClassName"
. Ensure to eventually call a native method to delete the object. For example, have a
close()
that deletes the native object.The best way to pass “compound” types across in either direction is to create an inner class with PODs and a factory function. If possible, make mark all the fields as “final”.
Build Rules
generate_jni
- Generates a header file with stubs for given.java
filesgenerate_jar_jni
- Generates a header file with stubs for a given.jar
filegenerate_jni_registration
- Generates a header file with functions to register native-side JNI methods (required only when using crazy linker).
Changing
jni_generator
- python unit tests live in
jni_generator_tests.py
- A working demo app exists as
//base/android/jni_generator:sample_jni_apk
推荐阅读
- Androidadb调试
- Android刷机的一般步骤
- Appscan使用说明
- 安卓编程之自定义字体控件导致应用闪退
- Could not GET 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.1.2/grad
- YII视图介绍和用法示例
- YII会话介绍和用法示例
- YII模块介绍和用法示例
- Yii模型介绍和用法示例