第48篇-native方法调用解释执行的Java方法
举一个native方法调用解释执行的Java方法的实例,如下:
- public class TestJNI {
- static {
- System.load("/media/mazhi/sourcecode/workspace/projectjava/projectjava01/src/main/java/libdiaoyong.so");
- }
- public static int getResult() {
- return 2;
- }
- public static native int get();
- public static void main(String[] args) {
- TestJNI.get();
- }
- }
如上实例在main()方法中调用native方法get(),具体的调用过程在前一篇文章中已经详细介绍过。我们这个实例将介绍native方法get()调用Java方法getResult()。
调用的native方法get()的本地函数的实现如下:
- JNIEXPORT jint JNICALL Java_TestJNI_get(JNIEnv * env, jclass jc){
- jclass cls = (*env)->FindClass(env, "TestJNI");
- jmethodID id = (*env)->GetStaticMethodID(env, jc, "getResult", "()I");
- jint x = (*env)->CallStaticIntMethod(env,cls, id);
- return x;
- }
在如上的函数中,我们会调用TestJNI类的getResult()方法获取一个整数值,然后本地函数返回这个整数值。
调用的CallStaticIntMethod()函数的实现如下:
- extern "C" {
- jint jni_CallStaticIntMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...) {
- JavaThread* thread=JavaThread::thread_from_jni_environment(env);
- ThreadInVMfromNative __tiv(thread);
- HandleMarkCleaner __hm(thread);
- Thread* __the_thread__ = thread;
- os::verify_stack_alignment();
- WeakPreserveExceptionMark __wem(thread);
- jint ret = 0;
- va_list args;
- __builtin_va_start(args,methodID);
- JavaValue jvalue(T_INT);
- JNI_ArgumentPusherVaArg ap(methodID, args);
- jni_invoke_static(env, &jvalue, 0, JNI_STATIC, methodID, &ap, __the_thread__);
- // ...
- __builtin_va_end(args);
- ret = jvalue.get_jint();
- return ret;
- }
- }
调用的jni_invoke_static()函数的实现如下:
- // 通过JNI的方式调用Java静态方法
- static void jni_invoke_static(
- JNIEnv *env,
- JavaValue* result,
- jobject receiver,
- JNICallType call_type,
- jmethodID method_id,
- JNI_ArgumentPusher *args,
- TRAPS
- ){
- Method* m = Method::resolve_jmethod_id(method_id);
- methodHandle method(THREAD, m);
- ResourceMark rm(THREAD);
- int number_of_parameters = method->size_of_parameters();
- // 这里将要传给Java方法的参数转换为JavaCallArguments实例传下去
- JavaCallArguments java_args(number_of_parameters);
- args->set_java_argument_object(&java_args);
- // 通过方法指纹值填写JavaCallArguments实例
- Fingerprinter fp = Fingerprinter(method);
- uint64_t x = fp.fingerprint();
- args->iterate(x);
- // 初始化方法返回类型
- BasicType bt = args->get_ret_type();
- result->set_type(bt);
- // 调用java方法
- JavaCalls::call(result, method, &java_args, CHECK);
- // 当Java方法返回对象类型数据时,需要句柄化后存储到result中
- if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {
- oop tmp = (oop) result->get_jobject();
- jobject jobj = JNIHandles::make_local(env,tmp);
- result->set_jobject(jobj);
- }
- }
调用的JavaCalls::call()函数最终会调用到JavaCalls::call_helper()函数,这个函数在之前介绍解释执行Java方法时详细介绍过。当调用到Java方法getResult()时,栈的状态如下图所示。
其中的蓝色为C/C++函数的栈帧,而绿色为Java方法的栈帧。
现在我们要从解释执行的main()方法调用native方法get(),这在前一篇详细介绍过,而从Java_TestJNI_get()函数调用getResult()的过程非常类似于HotSpot VM调用main()方法的过程,关于HotSpot VM调用main()方法的过程在之前详细介绍过,这里不再详细介绍。这里我们介绍一下JavaCallWrapper类。
通过上图我们能够看出,Java栈和C/C++栈混合在一起,这就为不同类型栈的展开(如GC需要遍历栈帧、异常需要向上查找异常处理器等),不同类型栈帧的转换和适配增加了不少难度,这些我们在后面都会详细介绍。
公众号 深入剖析Java虚拟机HotSpot 已经更新虚拟机源代码剖析相关文章到60+,欢迎关注,如果有任何问题,可加作者微信mazhimazh,拉你入虚拟机群交流
第48篇-native方法调用解释执行的Java方法的更多相关文章
- 第47篇-解释执行的Java方法调用native方法小实例
举个小实例,如下: public class TestJNI { static { // 程序在加载时,自动加载libdiaoyong.so库 System.loadLibrary("dia ...
- 第44篇-为native方法设置解释执行入口
对于Java中的native方法来说,实际上调用的是C/C++实现的本地函数,由于可能会在Java解释执行过程中调用native方法,或在本地函数的实现过程中调用Java方法,所以当两者相互调用时,必 ...
- 意外作出了一个javascript的服务器,可以通过js调用并执行任何java(包括 所有java 内核基本库)及C#类库,并最终由 C# 执行你提交的javascript代码! 不敢藏私,特与大家分
最近研发BDC 云开发部署平台的数据路由及服务管理器意外作出了一个javascript的服务器,可以通过js调用并执行任何java(包括 所有java 内核基本库)及C#类库,并最终由 C# 执行你提 ...
- static 关键字详解 static方法调用非static属性和方法
静态的属性和方法在内存中的存放地址与非静态的是不同的,静态的是存放在static区,它意味着静态方法是没有this的,所以我们不可以从一个static方法内部发出对非static方法的调用.但是反之是 ...
- 生命周期方法调用,以及在onStop()方法中处理草稿信息
生命周期方法调用顺序 1. 从会话列表界面跳转到信息列表界面. 07-17 17:29:18.718: I/txrjsms(19370): MessageListActivity.onCreate 0 ...
- Java方法调用机制
最近在编程时,修改方法传入对象的对象引用,并没有将修改反映到调用方法中.奇怪为什么结果没有变化,原因是遗忘了Java对象引用和内存分配机制.本文介绍3个点: ① 该问题举例说明 ② 简要阐述Java内 ...
- 04 JVM是如何执行方法调用的(下)
虚方法调用 Java 里所有非私有实例方法调用都会被编译成 invokevirtual 指令,而接口方法调用会被编译成 invokeinterface 指令.这两种指令,均属于 Java 虚拟机中的虚 ...
- 第5篇-调用Java方法后弹出栈帧及处理返回结果
在前一篇 第4篇-JVM终于开始调用Java主类的main()方法啦 介绍了通过callq调用entry point,不过我们并没有看完generate_call_stub()函数的实现.接下来在ge ...
- Struts2学习笔记 - Action篇<动态方法调用>
有三种方法可以使一个Action处理多个请求 动态方法调用DMI 定义逻辑Acton 在配置文件中使用通配符 这里就说一下Dynamic Method nvocation ,动态方法调用,什么是动态方 ...
随机推荐
- C语言之内核中的struct list_head 结构体
以下地址文章解释很好 http://blog.chinaunix.net/uid-27122224-id-3277511.html 对下面的结构体分析 1 struct person 2 { 3 in ...
- HDFS05 NameNode和SecondaryNameNode
NameNode和SecondaryNameNode(了解) 目录 NameNode和SecondaryNameNode(了解) NN 和 2NN 工作机制 NameNode工作机制 Secondar ...
- nodejs-npm模块管理器
JavaScript 标准参考教程(alpha) 草稿二:Node.js npm模块管理器 GitHub TOP npm模块管理器 来自<JavaScript 标准参考教程(alpha)> ...
- Cx_Oracle 安装
1. 下载安装 2.把oci.ddl oraociei11.dll 放到C:\Python33\Lib\site-packages路径下
- tomcat源码1
Lifecycle:(接口) LifecycleBase:abstract:添加,删除Listener,各种init,start,stop,destory LifecycleMBeanBase:abs ...
- 侵入式&非侵入式
侵入式设计 引入了框架,对现有的类的结构有影响:即需要实现或继承某些特定类. 例如:Struts框架 非侵入式设计 引入了框架,对现有的类结构没有影响. 例如:Hibernate框架 / Spring ...
- IDEA 使用rest client测试
一.进入 rest 控制台 idea 导航栏 ==> Tools ==> HTTP Client ==> Test RESTFUL Web Service 如图: 一般来说,idea ...
- 记一次ssh连接慢
2020-03-28日机房搬迁完后,发现有一台60服务器ssh连接特别慢,但是其他服务器正常; 下面是解决过程: vim /etc/ssh/sshd_config (编辑配置文件) 查找F ...
- 【Xcode】sh: pause: command not found
system("pause"); 只适合于DOS和Windows系统,不适合Linux系统. 直接删掉就可以. 或者改为: #include <unistd.h> pa ...
- 【Office】【Excel】将多个工作表合为一个工作表
在工作表中按下alt+F11打开vba编辑窗口,在菜单栏中选择[插入]=>[模板],将下面的代码粘贴过去,然后运行即可 点击查看代码 Sub 合并当前工作簿下的所有工作表() On Error ...