我们知道以下调用对话这个帖子, What's the calling convention for the Java code in Linux platform? 而且它解释了
“你可能会注意到Java调用约定看起来类似于C调用约定但是正确地移动了一个参数。这是为了避免在调用JNI方法时额外的寄存器重排(你知道,JNI方法之前有额外的JNIEnv *参数)方法参数)。“
当我们调用JNI函数,例如jclass FindClass(JNIEnv * env,const char * name)时,它意味着什么呢?然后将JNIEnv值env传递给rdi,并将名称传递给rsi,但是当我们调用一般的非JNI Java方法,如void printClassName(int Integer1,Object obj)时,则将Integer1传递给rsi,并且obj为传递到堆栈,因为它不是整数,它是对的?
如果我错了,请纠正我。|-------------------------------------------------------|
| c_rarg0 c_rarg1 c_rarg2 c_rarg3 c_rarg4 c_rarg5 |
|-------------------------------------------------------|
| rcx rdx r8 r9 rdi* rsi* | windows (* not a c_rarg)
| rdi rsi rdx rcx r8 r9 | solaris/linux
|-------------------------------------------------------|
| j_rarg5 j_rarg0 j_rarg1 j_rarg2 j_rarg3 j_rarg4 |
|-------------------------------------------------------|
答案 0 :(得分:1)
给定表描述了VM如何调用 Java 方法。
E.g。在调用Java方法void print(int i, Object o)
时,它会传递
this
中RSI (j_rarg0)
在i
RDX (j_rarg1)
在o
中的RCX (j_rarg2)
- 对象引用也在通用寄存器中传递。调用约定是相同的,无论方法是否声明为native
。对于本机方法,将有一个本机实现
void Java_ClassName_print(JNIEnv* env, jobject this, jint i, jobject o);
此本机函数遵循标准platform ABI,即
env
转到RDI (c_rarg0)
this
至RSI (c_rarg1)
i
至RDX (c_rarg2)
o
至RCX (c_rarg3)
请注意,由于明智地选择j_rargs
与c_rargs
,参数仍保留在相同的寄存器中。
FindClass
这样的JNI函数与VM调用约定无关。他们必须关注平台ABI。因此,第一个参数JNIEnv*
在Linux / x64上的RDI
中传递。