JVM_ENTRY和JVM_END解析
在阅读JVM源码的时候我们会经常碰到JVM_ENTRY和JVM_END,JVM_ENTRY和JVM_END是Hotspot源码中经常出现的宏定义,其功能是将一些需要重复编写的事务性代码提取了出来,如处理接口返回值类型,JNI声明、获取当前线程和调试开关等。
下面我们具体分析下JVM_ENTRY和JVM_END的功能:
源码
这里以openjdk7为例,JVM_ENTRY和JVM_END的定义位于文件hotspot/src/share/vm/runtime/interfaceSupport.hpp
,主要代码如下所示:
#define JVM_ENTRY(result_type, header) \
extern "C" { \
result_type JNICALL header { \
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
ThreadInVMfromNative __tiv(thread); \
debug_only(VMNativeEntryWrapper __vew;) \
VM_ENTRY_BASE(result_type, header, thread)
#define VM_ENTRY_BASE(result_type, header, thread) \
TRACE_CALL(result_type, header) \
HandleMarkCleaner __hm(thread); \
Thread* THREAD = thread; \
os::verify_stack_alignment(); \
/* begin of body */
#define JVM_END } }
源码分析
-
首先分析
extern "C"
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言(而不是C++)的方式进行编译。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。
这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。
-
JVM_END
JVM_END是JVM_ENTRY的伴生宏定义,实质上相当于
}}
,其功能比较简单,表示函数定义的结束,用于闭合JVM_ENTRY产生的函数。 -
接下来分析JVM_ENTRY的主要逻辑:
JVM_ENTRY
里面又使用了宏VM_ENTRY_BASE
和宏TRACE_CALL
,整体来看JVM_ENTRY
的作用是生成一个返回值为result_type的C语言函数,其函数名和参数由header确定。假设有以下定义:
JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)) // 用户代码 JVM_END
则经过预处理后实际生成的代码为:
extern "C" { jobject JNICALL jmm_GetMemoryUsage(JNIEnv* env, jboolean heap) { JavaThread* thread=JavaThread::thread_from_jni_environment(env); ThreadInVMfromNative __tiv(thread); debug_only(VMNativeEntryWrapper __vew;) TRACE_CALL(result_type, header) HandleMarkCleaner __hm(thread); Thread* THREAD = thread; os::verify_stack_alignment(); // 用户代码 // return ... } }
生成的函数主要做了以下几个事情:
(1) 获取当前线程:
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ ThreadInVMfromNative __tiv(thread); Thread* THREAD = thread;
(2)打印调试信息:
debug_only(VMNativeEntryWrapper __vew;)
(3) 记录调用轨迹:
TRACE_CALL(result_type, header)
(4)检查栈是否对齐:
os::verify_stack_alignment();
(5) 执行用户自定义代码:
// 用户代码 // return ...