java - Java内部如何维护函数StackTrace

标签 java jvm

Java 如何生成线程的堆栈跟踪?

例子:

考虑 functionA 调用 functionB 调用 functionC 调用 functionD。如果在 functionD 中的任何一点使用了 getStackTraceElementArray,它将给出函数调用数组:

functionC->functionB->functionA

Java 在运行时如何填充StackTraceElement 数组?假设它到达被调用函数内部时填充调用函数,那么JVM如何在被调用方法内部获取调用方法的引用?

最佳答案

在最简单的情况下,堆栈跟踪是从...堆栈中获取的! enter image description here
每个线程都有一个帧指针 (FP) 寄存器,指向当前堆栈帧的基地址。当一个 Java 方法被调用时,它首先创建一个新的栈帧,即将一堆信息压入栈中:

  • 返回地址(调用方法的地方);
  • 当前 FP(指向调用者框架);
  • 被调用方法的方法ID;
  • 指向常量池缓存等的指针。

然后它更新 FP 以指向新创建的框架。

这样,你看,帧指针构成了一个链表:如果我读取 FP 指向的值,我将获得前一帧的基地址。

现在请注意,对于每一帧,方法 ID 始终与 FP 具有相同的偏移量。因此,堆栈遍历就像 while 循环一样简单(用伪代码编写):

address fp = currentThread.getFP();
while (fp != null) {
    methodID m = (methodID) read_stack_at(fp + METHOD_OFFSET);
    print_method(m);
    fp = (address) read_stack_at(fp);
}

这就是它在 JVM 中为解释方法工作的方式。编译方法有点复杂。它们通常不会在堆栈上保存方法引用。相反,有一个结构将编译代码的地址映射到包含编译方法信息的元数据。但是堆栈遍历的思想仍然是一样的。

关于java - Java内部如何维护函数StackTrace,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37290028/

相关文章:

使用 int 与 long 的 Java For 循环

java - Hotspot JVM - G1GC 堆大小调整问题

Java CMS GC,系统空闲时GC线程占用CPU

java - 在 Java 中扩展静态类是什么意思?

java - 我在使用 EJB 时收到错误 `java.lang.ClassNotFoundException`

java - 如何对 Android Studio 中动态创建的多个按钮执行 onclick 操作

java - 当我使用套接字通过本地网络传输文件时,如何防止文件损坏?

Java - 处理大文件

java - NewRatio 参数不适用于 CMS 垃圾收集器

linux - 将 JVM 移植到 MINIX