引入:

上篇文章讲解了Agent利用环境指针访问VM的线程组操作,这里讨论下堆栈操作。


分类4:堆栈操作

a. GetStackTrace.获取某线程的堆栈。

jvmtiError
GetStackTrace(jvmtiEnv* env,
            jthread thread,
            jint start_depth,
            jint max_frame_count,
            jvmtiFrameInfo* frame_buffer,
            jint* count_ptr)

入参thread表示要分析的线程,如果不设置值则为当前线程。start_depth表示要分析的起始深度,0表示当前frame,1 表示调用者的frame,2表示调用者的调用者的frame. max_frame_count表示最大frame数。返回frame_buffer包含了巨大的想要的堆栈信息。


b.GetAllStackTraces.获取所有活着的线程的堆栈信息。

jvmtiError
GetAllStackTraces(jvmtiEnv* env,
            jint max_frame_count,
            jvmtiStackInfo** stack_info_ptr,
            jint* thread_count_ptr)

所有活着的线程的堆栈信息数组被放在返回值stack_info_ptr中。


c.GetThreadListStackTraces。获取给定线程列表的堆栈信息。

jvmtiError
GetThreadListStackTraces(jvmtiEnv* env,
            jint thread_count,
            const jthread* thread_list,
            jint max_frame_count,
            jvmtiStackInfo** stack_info_ptr)


d.GetFrameCount.获取给定线程调用堆栈中的当前帧数。

jvmtiError
GetFrameCount(jvmtiEnv* env,
            jthread thread,
            jint* count_ptr)


e.PopFrame.弹出给定线程堆栈的最上层的frame.

jvmtiError
PopFrame(jvmtiEnv* env,
            jthread thread)

这时候

(1)当前的frame就会被丢弃而之前的frame就会成为当前的frame.

(2)运算子(operand)的堆栈被恢复。

(3)操作码(opcode)恢复到之前的调用指令。


f.GetFrameLocation.返回当前执行的指令frame的位置。

jvmtiError
GetFrameLocation(jvmtiEnv* env,
            jthread thread,
            jint depth,
            jmethodID* method_ptr,
            jlocation* location_ptr)

从返回可以看出,这个返回位置包含深度,方法指针,位置指针。


g.NotifyFramePop. 当某Frame从堆栈中弹出时候,产生一个FramePop事件。

jvmtiError
NotifyFramePop(jvmtiEnv* env,
            jthread thread,
            jint depth)