JavaCalls::call为hotspot调用java方法的实现之一。其调用os::os_exception_wrapper(call_helper, result, &method, args, THREAD);这个还是比较好看懂,通过传入call_helper函数指针,在call_helper上面封装了异常的处理,典型的回调函数用法。call_helper的实现里面的具体调用java函数的方法相对难看明白,下面进行进一步分析。
....
//函数的具体调用
{ JavaCallWrapper link(method, receiver, result, CHECK);
{ HandleMark hm(thread); // HandleMark used by HandleMarkCleaner
StubRoutines::call_stub()(
(address)&link,
// (intptr_t*)&(result->_value), // see NOTE above (compiler problem)
result_val_address, // see NOTE above (compiler problem)
result_type,
method(),
entry_point,
args->parameters(),
args->size_of_parameters(),
CHECK
);
result = link.result(); // circumvent MS C++ 5.0 compiler bug (result is clobbered across call)
// Preserve oop return value across possible gc points
if (oop_result_flag) {
thread->set_vm_result((oop) result->get_jobject());
}
}
上面代码中StubRoutines::call_stub()返回的是一个函数指针,在执行上面的call_stub()时,会先将参数先压入堆栈。
这个函数指针指向什么地方呢,这是和机器类型有关的,以X86-32为例,看stubGenerator_x86_32.cpp里面
StubGenerator::generate_call_stub。返回的是__pc()的值,这个值其实是内存的的一个动态生态的机器码的一个位置。
address generate_call_stub(address& return_address) {
StubCodeMark mark(this, "StubRoutines", "call_stub");
address start = __ pc(); //注意,这是返回的指针值,下面还继续生成机器码,也就是说在上面的javaCall
//会调用下面产生的机器码,这些才是真正调用java方法的内容。
bool sse_save = false;
const Address rsp_after_call(rbp, -4 * wordSize); // same as in generate_catch_exception()!
const int locals_count_in_bytes (4*wordSize);
const Address mxcsr_save (rbp, -4 * wordSize);
const Address saved_rbx (rbp, -3 * wordSize);
const Address saved_rsi (rbp, -2 * wordSize);
const Address saved_rdi (rbp, -1 * wordSize);
const Address result (rbp, 3 * wordSize);
const Address result_type (rbp, 4 * wordSize);
const Address method (rbp, 5 * wordSize);
const Address entry_point (rbp, 6 * wordSize);
const Address parameters (rbp, 7 * wordSize);
const Address parameter_size(rbp, 8 * wordSize);
const Address thread (rbp, 9 * wordSize); // same as in generate_catch_exception()!
sse_save = UseSSE > 0;
//上面为对调用压入的堆栈进行的处理,将具体的值赋给寄存器
//下面就是残端代码,主要是产生机器码,用类似汇编语言的格式产生
// stub code
__ enter();
__ movl(rcx, parameter_size); // parameter counter
__ shll(rcx, Interpreter::logStackElementSize()); // convert parameter count to bytes
__ addl(rcx, locals_count_in_bytes); // reserve space for register saves
__ subl(rsp, rcx);
__ andl(rsp, -(StackAlignmentInBytes)); // Align stack
.....
采用类的方法,模拟汇编语言产生机器码还是很体现了大牛们的水平。
汇编调用java方法的具体代码
// call Java function
__ BIND(parameters_done);
__ movl(rbx, method); // get methodOop
__ movl(rax, entry_point); // get entry_point
__ movl(rsi, rsp); // set sender sp
BLOCK_COMMENT("call Java function");
__ call(rax);
上面就将cpu控制转向了entry_point,这正是java方法的入口。
这个entry_point从何而来,从method->from_interpreted_entry(),从methodOopDesc::link_method中获取address entry = Interpreter::entry_for_method(h_method),也就是说如果不用jit的,直接调用解析器的入口,由解释器再进行操作。
分享到:
相关推荐
GPU显卡的Compute Capability需>=5.3,否则会提示error: (-217:Gpu API call) invalid device function in function 'make_policy' 编译本接口所用的工具及环境: Cmake-3.17.5 VS2019 opencv-4.2.0 opencv-contrib...
技能Call代码生成器 技能Call代码生成器
不说多了,绝对好用,需要的尽管拿,都说好用
云函数 调用失败 Error: errCode: -404011 cloud function execution error | errMsg: cloud.callFunction:fail requestID , cloud function service error code -504001, error message Unkown function;...
call代码测试.rar
代码注入器 CALL 代码注入器 CALL
主要功能: 远程进程CALL代码注入测试 特点:带有try异常保护的远程CALL注入执行, 即使CALL参数错误或读写空指针,目标程序不会因产生错误而崩溃。 从而带给了程序员在测试CALL代码时的便利。 *****************...
CALL调用示例分析-远程代码注入器 CodeInEX_dong代码注入 CodeInEX_dong代码注入
Keil 中的报警错误:WARNING L15: MULTIPLE CALL TO SEGMENT。
NULL 博文链接:https://hw1287789687.iteye.com/blog/1925191
import csv file=r'd:/4.csv' ... #[1:]指从1开始内容,而不是从默认的0开始 for line in all_rows_no_title: if "1" in line[2]: pm_call.append([line[3],line[4],line[5]]) else: other_call.append([line[8],line
android call: call not sent 的log 文件
IMS call flow, 详细的 SIP 调用解释
由于Drawcall 值过大所引起的卡的问题我所做的优化方式有:1.对于模型:Mesh 合并,有个不错的插件(DrawCall Minimizer --->
3、Python OpenCV配置CUDA以支持GPU加速 (不使用Visual Studio) 可以使用该OpenCV 库版本利用GPU进行图像处理 4、OpenCV是计算机视觉和机器学习软件库,功能非常强大,通过pip安装的Python版本仅支持CPU运算,可以...
代码注入器 CALL测试 代码测试 CALL注入 无病毒
x86代码虚拟器(代码混淆器)开源和精简版的应用程序使二进制代码难以理解,并给反向工程师理解代码带来了挑战。特征使用虚拟机保护来保护和混淆敏感的代码区域(将字节码转换为PCode并在虚拟机中运行它们)已使用...