当用到JNI时,总不明白JNIEnv这个东东是个啥,有啥用;这次总算在源码中找到了它的实现,做个记录。。。。
android_source_code_dir\dalvik\libnativehelper\include\nativehelper\Jni.h
/*
* C++ object wrapper.
*
* This is usually overlaid on a C struct whose first element is a
* JNINativeInterface*. We rely somewhat on compiler behavior.
*/
struct _JNIEnv {
/* do not rename this; it does not seem to be entirely opaque */
const struct JNINativeInterface* functions;
#if defined(__cplusplus)
jint GetVersion()
{ return functions->GetVersion(this); }
jclass DefineClass(const char *name, jobject loader, const jbyte* buf,
jsize bufLen)
{ return functions->DefineClass(this, name, loader, buf, bufLen); }
jclass FindClass(const char* name)
{ return functions->FindClass(this, name); }
jmethodID FromReflectedMethod(jobject method)
{ return functions->FromReflectedMethod(this, method); }
jfieldID FromReflectedField(jobject field)
{ return functions->FromReflectedField(this, field); }
jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic)
{ return functions->ToReflectedMethod(this, cls, methodID, isStatic); }
jclass GetSuperclass(jclass clazz)
{ return functions->GetSuperclass(this, clazz); }
jboolean IsAssignableFrom(jclass clazz1, jclass clazz2)
{ return functions->IsAssignableFrom(this, clazz1, clazz2); }
jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic)
{ return functions->ToReflectedField(this, cls, fieldID, isStatic); }
jint Throw(jthrowable obj)
{ return functions->Throw(this, obj); }
jint ThrowNew(jclass clazz, const char* message)
{ return functions->ThrowNew(this, clazz, message); }
jthrowable ExceptionOccurred()
{ return functions->ExceptionOccurred(this); }
void ExceptionDescribe()
{ functions->ExceptionDescribe(this); }
void ExceptionClear()
{ functions->ExceptionClear(this); }
void FatalError(const char* msg)
{ functions->FatalError(this, msg); }
jint PushLocalFrame(jint capacity)
{ return functions->PushLocalFrame(this, capacity); }
jobject PopLocalFrame(jobject result)
{ return functions->PopLocalFrame(this, result); }
jobject NewGlobalRef(jobject obj)
{ return functions->NewGlobalRef(this, obj); }
void DeleteGlobalRef(jobject globalRef)
{ functions->DeleteGlobalRef(this, globalRef); }
void DeleteLocalRef(jobject localRef)
{ functions->DeleteLocalRef(this, localRef); }
jboolean IsSameObject(jobject ref1, jobject ref2)
{ return functions->IsSameObject(this, ref1, ref2); }
jobject NewLocalRef(jobject ref)
{ return functions->NewLocalRef(this, ref); }
jint EnsureLocalCapacity(jint capacity)
{ return functions->EnsureLocalCapacity(this, capacity); }
jobject AllocObject(jclass clazz)
{ return functions->AllocObject(this, clazz); }
jobject NewObject(jclass clazz, jmethodID methodID, ...)
{
va_list args;
va_start(args, methodID);
jobject result = functions->NewObjectV(this, clazz, methodID, args);
va_end(args);
return result;
}
jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args)
{ return functions->NewObjectV(this, clazz, methodID, args); }
jobject NewObjectA(jclass clazz, jmethodID methodID, jvalue* args)
{ return functions->NewObjectA(this, clazz, methodID, args); }
jclass GetObjectClass(jobject obj)
{ return functions->GetObjectClass(this, obj); }
jboolean IsInstanceOf(jobject obj, jclass clazz)
{ return functions->IsInstanceOf(this, obj, clazz); }
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
{ return functions->GetMethodID(this, clazz, name, sig); }
#define CALL_TYPE_METHOD(_jtype, _jname) \
_jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...) \
{ \
_jtype result; \
va_list args; \
va_start(args, methodID); \
result = functions->Call##_jname##MethodV(this, obj, methodID, \
args); \
va_end(args); \
return result; \
}
#define CALL_TYPE_METHODV(_jtype, _jname) \
_jtype Call##_jname##MethodV(jobject obj, jmethodID methodID, \
va_list args) \
{ return functions->Call##_jname##MethodV(this, obj, methodID, args); }
#define CALL_TYPE_METHODA(_jtype, _jname) \
_jtype Call##_jname##MethodA(jobject obj, jmethodID methodID, \
jvalue* args) \
{ return functions->Call##_jname##MethodA(this, obj, methodID, args); }
#define CALL_TYPE(_jtype, _jname) \
CALL_TYPE_METHOD(_jtype, _jname) \
CALL_TYPE_METHODV(_jtype, _jname) \
CALL_TYPE_METHODA(_jtype, _jname)
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)
void CallVoidMethod(jobject obj, jmethodID methodID, ...)
{
va_list args;
va_start(args, methodID);
functions->CallVoidMethodV(this, obj, methodID, args);
va_end(args);
}
.
.
省略一部分
#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif
/*
* Table of interface function pointers.
*/
struct JNINativeInterface {
void* reserved0;
void* reserved1;
void* reserved2;
void* reserved3;
jint (*GetVersion)(JNIEnv *);
jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,
jsize);
jclass (*FindClass)(JNIEnv*, const char*);
jmethodID (*FromReflectedMethod)(JNIEnv*, jobject);
jfieldID (*FromReflectedField)(JNIEnv*, jobject);
/* spec doesn't show jboolean parameter */
jobject (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);
jclass (*GetSuperclass)(JNIEnv*, jclass);
jboolean (*IsAssignableFrom)(JNIEnv*, jclass, jclass);
/* spec doesn't show jboolean parameter */
jobject (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);
jint (*Throw)(JNIEnv*, jthrowable);
jint (*ThrowNew)(JNIEnv *, jclass, const char *);
jthrowable (*ExceptionOccurred)(JNIEnv*);
void (*ExceptionDescribe)(JNIEnv*);
void (*ExceptionClear)(JNIEnv*);
void (*FatalError)(JNIEnv*, const char*);
jint (*PushLocalFrame)(JNIEnv*, jint);
jobject (*PopLocalFrame)(JNIEnv*, jobject);
jobject (*NewGlobalRef)(JNIEnv*, jobject);
void (*DeleteGlobalRef)(JNIEnv*, jobject);
void (*DeleteLocalRef)(JNIEnv*, jobject);
jboolean (*IsSameObject)(JNIEnv*, jobject, jobject);
jobject (*NewLocalRef)(JNIEnv*, jobject);
jint (*EnsureLocalCapacity)(JNIEnv*, jint);
jobject (*AllocObject)(JNIEnv*, jclass);
jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...);
jobject (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list);
jobject (*NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*);
jclass (*GetObjectClass)(JNIEnv*, jobject);
jboolean (*IsInstanceOf)(JNIEnv*, jobject, jclass);
jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
/*
* Dalvik implementation of JNI interfaces.
*/
#include "Dalvik.h"
#include "JniInternal.h"
#include "ScopedPthreadMutexLock.h"
#include "UniquePtr.h"
#include
#include
#include
/*
* ===========================================================================
* JNI implementation
* ===========================================================================
*/
/*
* Return the version of the native method interface.
*/
static jint GetVersion(JNIEnv* env) {
/*
* There is absolutely no need to toggle the mode for correct behavior.
* However, it does provide native code with a simple "suspend self
* if necessary" call.
*/
ScopedJniThreadState ts(env);
return JNI_VERSION_1_6;
}
/*
* Create a new class from a bag of bytes.
*
* This is not currently supported within Dalvik.
*/
static jclass DefineClass(JNIEnv* env, const char *name, jobject loader,
const jbyte* buf, jsize bufLen)
{
UNUSED_PARAMETER(name);
UNUSED_PARAMETER(loader);
UNUSED_PARAMETER(buf);
UNUSED_PARAMETER(bufLen);
ScopedJniThreadState ts(env);
LOGW("JNI DefineClass is not supported");
return NULL;
}
/*
* Find a class by name.
*
* We have to use the "no init" version of FindClass here, because we might
* be getting the class prior to registering native methods that will be
* used in .
*
* We need to get the class loader associated with the current native
* method. If there is no native method, e.g. we're calling this from native
* code right after creating the VM, the spec says we need to use the class
* loader returned by "ClassLoader.getBaseClassLoader". There is no such
* method, but it's likely they meant ClassLoader.getSystemClassLoader.
* We can't get that until after the VM has initialized though.
*/
static jclass FindClass(JNIEnv* env, const char* name) {
ScopedJniThreadState ts(env);
const Method* thisMethod = dvmGetCurrentJNIMethod();
assert(thisMethod != NULL);
Object* loader;
Object* trackedLoader = NULL;
if (ts.self()->classLoaderOverride != NULL) {
/* hack for JNI_OnLoad */
assert(strcmp(thisMethod->name, "nativeLoad") == 0);
loader = ts.self()->classLoaderOverride;
} else if (thisMethod == gDvm.methDalvikSystemNativeStart_main ||
thisMethod == gDvm.methDalvikSystemNativeStart_run) {
/* start point of invocation interface */
if (!gDvm.initializing) {
loader = trackedLoader = dvmGetSystemClassLoader();
} else {
loader = NULL;
}
} else {
loader = thisMethod->clazz->classLoader;
}
char* descriptor = dvmNameToDescriptor(name);
if (descriptor == NULL) {
return NULL;
}
ClassObject* clazz = dvmFindClassNoInit(descriptor, loader);
free(descriptor);
jclass jclazz = (jclass) addLocalReference(ts.self(), (Object*) clazz);
dvmReleaseTrackedAlloc(trackedLoader, ts.self());
return jclazz;
}
/*
* Return the superclass of a class.
*/
static jclass GetSuperclass(JNIEnv* env, jclass jclazz) {
ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
return (jclass) addLocalReference(ts.self(), (Object*)clazz->super);
}
/*
* Determine whether an object of clazz1 can be safely cast to clazz2.
*
* Like IsInstanceOf, but with a pair of class objects instead of obj+class.
*/
static jboolean IsAssignableFrom(JNIEnv* env, jclass jclazz1, jclass jclazz2) {
ScopedJniThreadState ts(env);
ClassObject* clazz1 = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz1);
ClassObject* clazz2 = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz2);
return dvmInstanceof(clazz1, clazz2);
}
/*
* Given a java.lang.reflect.Method or .Constructor, return a methodID.
*/
static jmethodID FromReflectedMethod(JNIEnv* env, jobject jmethod) {
ScopedJniThreadState ts(env);
Object* method = dvmDecodeIndirectRef(ts.self(), jmethod);
return (jmethodID) dvmGetMethodFromReflectObj(method);
}
/*
* Given a java.lang.reflect.Field, return a fieldID.
*/
static jfieldID FromReflectedField(JNIEnv* env, jobject jfield) {
ScopedJniThreadState ts(env);
Object* field = dvmDecodeIndirectRef(ts.self(), jfield);
return (jfieldID) dvmGetFieldFromReflectObj(field);
}