JNI entrance
1.WebCoreJniOnLoad.cpp,
EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JSC::Bindings::setJavaVM(vm);
.....
const RegistrationMethod* method = gWebCoreRegMethods;
const RegistrationMethod* end = method + sizeof(gWebCoreRegMethods)
/sizeof(RegistrationMethod);
while (method != end) {
if (method->func(env) < 0) {
LOGE("%s registration failed!", method->name);
return result;
}
method++;
}
return JNI_VERSION_1_4;
}
register the JNI functions for every class
static RegistrationMethod gWebCoreRegMethods[] = {
{ "JavaBridge", android::registerJavaBridge },
{ "JniUtil", android::registerJniUtil },
{ "WebFrame", android::registerWebFrame },
{ "WebCoreResourceLoader", android::registerResourceLoader },
{ "WebViewCore", android::registerWebViewCore },
........
};
so registerJavaBridge registerJniUtil.... will be called.
2. class's JNI register methods
take registerWebViewCore for example
int registerWebViewCore(JNIEnv* env)
{
jclass widget = env->FindClass("android/webkit/WebViewCore");
LOG_ASSERT(widget,
"Unable to find class android/webkit/WebViewCore");
gWebViewCoreFields.m_nativeClass = env->GetFieldID(widget, "mNativeClass",
"I");
.........
return jniRegisterNativeMethods(env, "android/webkit/WebViewCore",
gJavaWebViewCoreMethods, NELEM(gJavaWebViewCoreMethods));
}
register every method for the class
3. JNINativeMethod structure
static JNINativeMethod gJavaWebViewCoreMethods[] = {
{ "nativeClearContent", "()V", (void*) ClearContent },
...
}
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
function name(the name for java to call), signature, and function pointer.
4. native method parameters
take "ClearContent" for example
static void ClearContent(JNIEnv *env, jobject obj)
it has two parameters, one is JNIEvn, the other is it's java object in the vm.
some may have more
static void SetSelection(JNIEnv *env, jobject obj, jint start, jint end)
each function has at least two parameter which are "JNIEnv" and "jobject"
the first is the JNI pointer, the second is the java class who owns the method.
other parameters depends on the implementation of the function.
JAVA's class and method in CPP
1. find class from java in cpp code
jclass widget = env->FindClass("android/webkit/WebViewCore");
jclass FindClass(const char* name)
2. find field from a class
gWebViewCoreFields.m_nativeClass = env->GetFieldID(widget, "mNativeClass","I");
struct WebViewCoreFields {
jfieldID m_nativeClass;
jfieldID m_viewportWidth;
.......
jfieldID m_highUsageDeltaMb;
} gWebViewCoreFields;
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig);
here is use a opaque structure
struct _jfieldID; /* opaque structure */
typedef struct _jfieldID* jfieldID; /* field IDs */
so it just return a jfieldID pointer. (as my understanding it should be a pointer)
struct _jfieldID is an opaque structure, we can only use it's pointer, because we don't know it size.It can be used when ourselves know what the return type is, andconvert the point to the type we want.
3. setIntField and getIntField
void SetIntField(jobject obj, jfieldID fieldID, jint value)
{ functions->SetIntField(this, obj, fieldID, value); }
jint GetIntField(jobject obj, jfieldID fieldID)
{ return functions->GetIntField(this, obj, fieldID); }
fieldID is a pointer in Java Class
a. setIntField means we assign value to the pointer.
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
so the value of the gWebViewCoreFields.m_nativeClass will be the value of pointer "this", that's "WebViewCore"
b. getIntField means we get the value of the pointer .
#define GET_NATIVE_VIEW(env, obj) ((WebViewCore*)env->GetIntField(obj,
gWebViewCoreFields.m_nativeClass))
so we could get the "WebViewCore" pointer back in some other place.
4. is this necessary to use the global variant?
I think it do that so we don't have to call findClass GetXXField in every function.
(maybe findClass and GetXXField the two will be enough for us wherever we want to use it)
5.GetMethodID
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
get a method from a class.
struct _jmethodID; /* opaque structure */
typedef struct _jmethodID* jmethodID; /* method IDs */
also opaque structure.
jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
get method "hasNext" of class "iteratorClass"
6. call a method in java
env->CallBooleanMethod(iter, hasNext)
we got the method, and we know what type it is, call the corresponding function.
jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
ps:
iteratorClass is the class namefor the class, jobject is the object instance of the class that we are using.
macro defined in jni.h
1.
#define CALL_TYPE_METHOD(_jtype, _jname)
_jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...)
#define CALL_TYPE_METHODA(_jtype, _jname)
#define CALL_TYPE_METHODA(_jtype, _jname)
(it's a method a defination of a current jname and method)
define call_type_method for a specific jtype and jname.
2.
#define CALL_TYPE(_jtype, _jname)\
CALL_TYPE_METHOD(_jtype, _jname)\
CALL_TYPE_METHODV(_jtype, _jname)\
CALL_TYPE_METHODA(_jtype, _jname)
define three functions of a current type and name.
3.
CALL_TYPE(jobject, Object)
CALL_TYPE(jboolean, Boolean)
CALL_TYPE(jbyte, Byte)
CALL_TYPE(jchar, Char)
CALL_TYPE(jshort, Short)
CALL_TYPE(jint, Int)
CALL_TYPE(jlong, Long)
CALL_TYPE(jfloat, Float)
CALL_TYPE(jdouble, Double)
define the type of all type in Java.
4.
void CallVoidMethod(jobject obj, jmethodID methodID, ...)
void CallVoidMethodV(jobject obj, jmethodID methodID, va_list args)
void CallVoidMethodA(jobject obj, jmethodID methodID, jvalue* args)
5.
#define CALL_NONVIRT_TYPE_METHOD(_jtype, _jname)
#define CALL_NONVIRT_TYPE_METHODV(_jtype, _jname)
#define CALL_NONVIRT_TYPE_METHODA(_jtype, _jname)
....
void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,jmethodID methodID, jvalue* args)
same as above
6.
getFieldId
setIntField
getIntField