Skip to content

Thread dump like jstack in local JVM process (not interprocess like jstack in jdk) by dirty JNI way. 在本地 JVM 进程(而不是jdk中jstack的进程间)中通过粗糙的 JNI 方式进行类似 jstack 的线程转储

Notifications You must be signed in to change notification settings

zenuo/local_jstack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

local_jstack

Thread dump like jstack in local JVM process (not interprocess like jstack in jdk) by dirty JNI way.

在本地 JVM 进程(而不是jdk中jstack的进程间)中通过粗糙的 JNI 方式进行类似 jstack 的线程转储

支持的平台 Supported Platform

  • linux x64
  • macos x64
  • windows x64

上手 Get Started

  1. 首先找到JRE环境的libjvm.so中的thread_dump(AttachOperation*, outputStream*)函数的偏移量

    • unix平台,以21.0.5-ms为例,为4892880

      $ nm -t d -C /usr/local/sdkman/candidates/java/21.0.5-ms/lib/server/libjvm.so |grep -F 'thread_dump(AttachOperation*, outputStream*)'
      0000000004892880 t thread_dump(AttachOperation*, outputStream*)
    • Windows平台,则需要借助map文件来获取函数偏移量,例如microsoft-jdk-21.0.3-windows-x64.zip,需要下载微软提供的调试信息microsoft-jdk-debugsymbols-21.0.3-windows-x64.zip,然后解压调试信息

      首先是获取ImageBase,如下命令的结果第三列0000000180000000就是ImageBase的Rva+Base 16进制形式:

      findstr "__ImageBase" C:\jdk-21.0.3+9-debug-symbols\bin\server\jvm.dll.map
       0000:00000000       __ImageBase                0000000180000000     <linker-defined>
      

      再是获取thread_dump(AttachOperation*, outputStream*)方法在dll中的地址,如下命令的结果第三列00000001801315e0就是thread_dump函数Rva+Base16进制形式:

      findstr "?thread_dump@@YAJPEAVAttachOperation@@PEAVoutputStream@@@Z" C:\jdk-21.0.3+9-debug-symbols\bin\server\jvm.dll.map | findstr /V unwind
       0001:001305e0       ?thread_dump@@YAJPEAVAttachOperation@@PEAVoutputStream@@@Z 00000001801315e0 f   attachListener.obj

      然后两者做减法:00000001801315e0 - 0000000180000000的结果1315e0就是thread_dump函数在jvm.dll中的偏移量

  2. 使用java.io.Writer来承接线程栈

    import java.io.StringWriter;
    
    public class MyApp {
        public static void main(String[] args) {
            StringWriter writer = new StringWriter();;
            LocalJStack.dumpStack(writer);
            System.out.println(writer);
        }
    }
  3. 编译、运行

    $ javac -cp localjstack-0.0.1.jar MyApp.java
    $ /usr/local/sdkman/candidates/java/21.0.5-ms/bin/java -Dlocaljstack.threadDumpOffset=4892880 -cp localjstack-0.0.1.jar:. MyApp
    

    打印到标准输出:

    2025-02-19 14:58:09
    Full thread dump OpenJDK 64-Bit Server VM (21.0.5+11-LTS mixed mode, sharing):
    
    Threads class SMR info:
    _java_thread_list=0x000077b8f415e3b0, length=10, elements={
    ...
    

    如果使用Maven,在pom.xml中添加本项目:

    <dependency>
        <groupId>app</groupId>
        <artifactId>localjstack</artifactId>
        <version>0.0.1</version>
    </dependency>

编译源代码 Build From Source

$ cmake --build ./build --config Debug --target LibLocalJStack -j 4 --
$ mvn package

产出jar包为target/localjstack-0.0.1.jar

About

Thread dump like jstack in local JVM process (not interprocess like jstack in jdk) by dirty JNI way. 在本地 JVM 进程(而不是jdk中jstack的进程间)中通过粗糙的 JNI 方式进行类似 jstack 的线程转储

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published