java - 如何通过汇编代码从 JVM 核心转储中检查 jitted Java 方法参数?

标签 java jvm gdb

我想获取jitted代码的汇编代码,以根据Java调用约定获取参数值。 假设 JVM 是热点,平台是 Linux 64 位,我们有以下调用者和被调用者,我想检查从 JVM 核心转储传递给被调用者的参数。

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

}

protected void callee(int a,String b, Integer c,Object d) {
 Thread.sleep(11111111);
}

根据下面的Java调用约定,我们知道我们可以从寄存器中获取参数,例如寄存器中最多传递6个第一个整数参数:rsi,rdx,rcx,r8,r9,rdi http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/b4bdf3484720/src/cpu/x86/vm/assembler_x86.hpp#l91

对于c/c++方法,我们可以顺便使用gdb,通过命令 backtrace 打印调用堆栈,然后帧N(N是线程号),然后 x/20i $pc-64 得到汇编代码,我们可以从相关的框架上下文寄存器中获取值。 但是Java方法调用栈无法从gdb中打印出来,而且我们不知道帧号,那么我们就不能像c/c++一样获取汇编代码,那么如何查看Java的汇编代码呢?来自核心转储的 jitted 方法?

PS, 有人提到了 PrintOptoAssembly,但是我需要汇编代码通过调用约定(例如通过 backtrace ,然后是frame N ,然后通过 gdb x/20i $pc-64 )从寄存器获取参数值,而不仅仅是汇编代码。

最佳答案

使用 gdb backtrace 命令您不会看到 Java 帧。但是,您不需要手动从核心转储中提取虚拟机结构 - 有更好的选择。

1。热点服务能力代理

Serviceability Agent是专门为分析Java进程内存或核心转储而设计的工具。它有Java API可在标准 JDK 包提供的 sa-jdi.jar 中找到。

这是一个example打印带有局部变量信息的扩展 Java 堆栈跟踪。它还可以解析核心转储。

2。 HotSpot调试功能

HotSpot JVM 的调试版本包括可以从 gdb 调用的特殊调试函数。例如

  • psf() 打印堆栈帧;
  • pfl() 打印框架布局;
  • disnm(intptr_t addr) 在给定地址反汇编已编译的 Java 方法;
  • pp(intptr_t addr) 在给定地址打印 Java 对象;
  • 等等。请参阅 debug.cpp 中的其他命令.

这些函数在调试 Activity 进程时起作用;但不适合核心转储。

顺便说一句,一个quick guide自己构建JVM的调试版本。

关于java - 如何通过汇编代码从 JVM 核心转储中检查 jitted Java 方法参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41715532/

相关文章:

bash - 为什么 '<<<' 会过滤 gdb 中的空字节,而 '<()' 不会?

Java 电子邮件 - 异常服务器不受信任

java - JVM - 我应该分配多少 RAM

java - 为什么运行无限循环的非守护线程会停止?

linux - 如何了解和调试Linux中线程的执行顺序

c - 从核心转储中获取被调用函数的返回值

java - 延迟获取数据时出现异常 - JUnit 测试

java - 我正在尝试使用 zip4j jar 文件提取受密码保护的 ZIP 文件,但出现以下错误

java - 在 Eclipse 中运行程序时播放音乐,但在运行 Jar 可执行文件时不播放

java - java 9 中 javax.activation 包的替代品是什么?