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

which register used to pass the JNIEnv for JNI methods in solaris/linux?

我们知道这个线程的以下调用对话, 它还解释说

"You may notice that Java calling convention looks similar to C calling convention but shifted by one argument right. This is done intentionally to avoid extra register shuffling when calling JNI methods (you know, JNI methods have extra JNIEnv* argument prepended to method parameters)."

那么我们调用jclass FindClass(JNIEnv *env, const char *name);之类的JNI函数是不是也意味着然后 JNIEnv 值 env 将传递给 rdi,name 传递给 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    |
|-------------------------------------------------------|

给定的 table 描述了 VM 如何调用 Java 方法。

例如当调用 Java 方法时 void print(int i, Object o) 它通过

  • thisRSI (j_rarg0)
  • iRDX (j_rarg1)
  • o in 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*RDI 中传递给 Linux/x64。