Linux平台中Java代码的调用约定是什么? [英] What's the calling convention for the Java code in Linux platform?

查看:116
本文介绍了Linux平台中Java代码的调用约定是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们知道调用约定前六个整数或指针参数在寄存器RDI,RSI,RDX,RCX(Linux内核接口中的R10 [124]:124),R8和R9中传递给c / Linux平台中的c ++代码基于以下文章。
https://en.wikipedia.org/wiki/X86_calling_conventions#x86- 64_calling_conventions

We know the calling convention that "first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX (R10 in the Linux kernel interface[17]:124), R8, and R9" for the c/c++ code in the Linux platform based on the following article. https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions

然而,Linux平台中Java代码的调用约定是什么(假设JVM是热点)?以下是示例,什么寄存器存储四个参数?

However what's the calling convention for the Java code in Linux platform (suppose the JVM is hotspot)? The following is example, what's registers store the four parameters?

protected void caller( ) {
callee(1,"123", 123,1)
}

protected void callee(int a,String b, Integer c,Object d) {

}


推荐答案

未指定JVM如何在内部调用Java方法。各种JVM实现可以遵循不同的调用约定。以下是 Linux x64 HotSpot JVM 的工作原理。

It is not specified how JVM calls Java methods internally. Various JVM implementations may follow different calling conventions. Here is how it works in HotSpot JVM on Linux x64.


  • Java方法可以在解释器中运行,也可以进行JIT编译。

  • 解释和编译的代码使用不同的调用约定。

每个Java方法都有一个进入解释器的入口点。此条目用于从解释方法跳转到另一个解释方法。

Each Java method has an entry point into the interpreter. This entry is used to jump from an interpreted method to another interpreted method.


  • 所有参数都在堆栈中传递,从下到上。

  • rbx 包含指向方法* 结构的指针 - $的内部元数据b $ b方法被调用。

  • r13 持有 sender_sp - 堆栈指针调用方法。它可能与 rsp + 8 不同,如果使用 c2i 适配器(见下文)。

  • All arguments are passed on stack, from bottom to top.
  • rbx contains a pointer to Method* structure - internal metadata of a method being called.
  • r13 holds sender_sp - stack pointer of a caller method. It may differ from rsp + 8 if c2i adapter is used (see below).

有关HotSpot源代码中解释器条目的更多详细信息: templateInterpreter_x86_64.cpp

More details about interpreter entries in HotSpot source code: templateInterpreter_x86_64.cpp.

编译方法有自己的入口点。编译代码通过此条目调用编译的方法。

A compiled method has its own entry point. Compiled code calls compiled methods via this entry.


  • 寄存器中最多传递6个第一个整数参数: rsi rdx rcx r8 r9 rdi 。非静态方法接收引用作为 rsi 中的第一个参数。

  • xmm0 ... xmm7 寄存器中最多传递8个浮点参数。

  • 所有其他参数都是从上到下传递给堆栈。

  • Up to 6 first integer arguments are passed in registers: rsi, rdx, rcx, r8, r9, rdi. Non-static methods receive this reference as the first argument in rsi.
  • Up to 8 floating point arguments are passed in xmm0 ... xmm7 registers.
  • All other arguments are passed on stack from top to bottom.

这个约定在 assembler_x86.hpp

    |-------------------------------------------------------|
    | 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    |
    |-------------------------------------------------------|

您可能会注意到Java调用约定看起来类似于C调用约定但右移一个参数。这样做是为了避免在调用JNI方法时额外的寄存器重排(你知道,JNI方法在方法参数之前有额外的 JNIEnv * 参数)。

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).

Java方法可能还有两个入口点: c2i i2c 适配器。这些适配器是动态生成的代码片段,它们将编译的调用约定转换为解释器布局,反之亦然。 с2i i2c 入口点分别用于从已编译的代码和已解释的代码中编译的方法调用解释的方法。

Java methods may have two more entry points: c2i and i2c adapters. These adapters are pieces of dynamically generated code that convert compiled calling convention to interpreter layout and vice versa. с2i and i2c entry points are used to call interpreted method from compiled code and compiled method from interpreted code respectively.

PS JVM内部调用方法通常无关紧要,因为这些只是实现细节不透明到最终用户。此外,即使在较小的JDK更新中,这些细节也可能会发生变化。但是,我知道至少有一种情况,当Java调用约定的知识可能看起来很有用时 - 分析JVM崩溃转储时。

P.S. It does not usually matter how JVM calls methods internally, because these are just implementation details opaque to end-user. Moreover, these details may change even in a minor JDK update. However, I know at least one case when the knowledge of Java calling convention may appear useful - when analysing JVM crash dumps.

这篇关于Linux平台中Java代码的调用约定是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆