哪个寄存器用于在solaris / linux中为JNI方法传递JNIEnv?

时间:2017-02-18 09:59:18

标签: jvm jit

我们知道以下调用对话这个帖子, 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    |
|-------------------------------------------------------|

1 个答案:

答案 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)
  • thisRSI (c_rarg1)
  • iRDX (c_rarg2)
  • oRCX (c_rarg3)

请注意,由于明智地选择j_rargsc_rargs,参数仍保留在相同的寄存器中。

FindClass这样的JNI函数与VM调用约定无关。他们必须关注平台ABI。因此,第一个参数JNIEnv*在Linux / x64上的RDI中传递。