1.JNIEnv初始化
在文章"安卓10源码学习开发定制(36)Art虚拟机中JavaVM &JNIEnv 的初始化流程"中已经分析了JNIEnv的初始化构造流程。最终JNIEnv初始化构造是在文件 artruntimethread.cc中的类中进行构造,关键代码如下:
bool Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm, JNIEnvExt* jni_env_ext) {
...
if (jni_env_ext != nullptr) {
...
tlsPtr_.jni_env = jni_env_ext;
} else {
std::string error_msg;
//创建JNIEnv结构并存储到线程局部存储变量中
tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm, &error_msg);
...
}
...
}
接下来分析JNIEnvExt中的JNINativeInterface是如何初始化的。
2.JNINativeInterface初始化流程分析
JNIEnvExt类的文件路径为:
artruntimejnijni_env_ext.cc
(1).JNIEnvExt中的调用分析
在以上分析中JNIEnv通过调用JNIEnvExt::Create进行创建,在JNIEnvExt中的Create方法实现逻辑如下:
JNIEnvExt* JNIEnvExt::Create(Thread* self_in, JavaVMExt* vm_in, std::string* error_msg) {
std::unique_ptr<JNIEnvExt> ret(new JNIEnvExt(self_in, vm_in, error_msg));
...
}
在以上代码中使用了new JNIEnvExt(self_in, vm_in, error_msg)进行初始化,下面是JNIEnvExt构造函数实现:
JNIEnvExt::JNIEnvExt(Thread* self_in, JavaVMExt* vm_in, std::string* error_msg)
: self_(self_in),
vm_(vm_in),
local_ref_cookie_(kIRTFirstSegment),
locals_(kLocalsInitial, kLocal, IndirectReferenceTable::ResizableCapacity::kYes, error_msg),
monitors_("monitors", kMonitorsInitial, kMonitorsMax),
critical_(0),
check_jni_(false),
runtime_deleted_(false) {
...
//这个地方进行了JNINativeInterface的初始化,functions 定义在JNIEnv中
functions = GetFunctionTable(check_jni_);
}
在以上代码调用中调用了GetFunctionTable()方法初始化JNIEnv中的functions变量,JNIEnv中的functions定义如下:
struct _JNIEnv {
/* do not rename this; it does not seem to be entirely opaque */
const struct JNINativeInterface* functions;
...
}
接下来分析一下GetFunctionTable方法中的实现。GetFunctionTable逻辑代码如下:
const JNINativeInterface* JNIEnvExt::GetFunctionTable(bool check_jni) {
...
//当前会根据chck_jni调用不同的JNINativeInterface初始化接口
return check_jni ? GetCheckJniNativeInterface() : GetJniNativeInterface();
}
check_jni在编译eng版本的时候会被打开,所以这个地方我们只分析user、userdebug版本的流程。所以接下来将会执行GetJniNativeInterface方法。
根据源码定位GetJniNativeInterface方法定义在如下文件:
artruntimejnijni_internal.h
定义的代码内容如下:
const JNINativeInterface* GetJniNativeInterface();
该方法实现文件路径位于:
artruntimejnijni_internal.cc
接下来分析jni_internal.cc中的流程。
(2).jni_internal.cc中的调用分析
在该文件中GetJniNativeInterface方法实现如下:
const JNINativeInterface* GetJniNativeInterface() {
return &gJniNativeInterface;
}
有以上代码分析可知返回的是gJniNativeInterface变量的值,该变量定义如下:
const JNINativeInterface gJniNativeInterface = {
nullptr, // reserved0.
nullptr, // reserved1.
nullptr, // reserved2.
nullptr, // reserved3.
JNI::GetVersion,
JNI::DefineClass,
JNI::FindClass,
...
}
有以上代码可以知道该变量为常量,使用一些列JNI类中的方法填充JNINativeInterface接口,从而完成JNIEnv中的JNINativeInterface初始化。
在jni_internal.cc中可以找到类JNI的定义实现。如下:
class JNI {
public:
static jint GetVersion(JNIEnv*) {
return JNI_VERSION_1_6;
}
static jclass DefineClass(JNIEnv*, const char*, jobject, const jbyte*, jsize) {
LOG(WARNING) << "JNI DefineClass is not supported";
return nullptr;
}
static jclass FindClass(JNIEnv* env, const char* name) {
CHECK_NON_NULL_ARGUMENT(name);
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
std::string descriptor(NormalizeJniClassDescriptor(name));
ScopedObjectAccess soa(env);
ObjPtr<mirror::Class> c = nullptr;
if (runtime->IsStarted()) {
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader(soa)));
c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader);
} else {
c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str());
}
return soa.AddLocalReference<jclass>(c);
}
...
}
以上代码可以看到JNI中真正实现了JNIEnv结构体中JNINativeInterface接口,我们平时调用的接口比如FindClass最终调用的是JNI::FindClass。
3.总结
art虚拟机中的JNIEnv中的各种接口最终实现位于"jni_internal.cc"中的class JNI中实现。
如果我们需要在系统中进行JNI trace,就可以在jni_internal.cc中进行日志输出。
如果你对安卓相关的开发学习感兴趣:
扫描下方二维码关注公众号
原文始发于微信公众号(哆啦安全):安卓10源码学习开发定制(37)Art虚拟机中JNINativeInterface初始化流程分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论