1. 程式人生 > >使用sa-jdi.jar dump 內存中的class

使用sa-jdi.jar dump 內存中的class

src att tdi ssd jre 發現 命令 tool over

前言

在分析一個 jar 包時發現他把關鍵類采用了運行時使用 classloader 的方式加載了。懶得分析算法了,可以使用 jdk 自帶的工具 dump 出需要的class.

正文

從運行的java進程裏dump出運行中的類的class文件的方法,所知道的有兩種

  • 用agent attatch 到進程,然後利用 Instrumentation和 ClassFileTransformer就可以獲取 到類的字節碼了。

  • 使用 sd-jdi.jar裏的工具

本文介紹的就是使用 sd-jdi.jar 來dump. sd-jdi.jar裏自帶的的 sun.jvm.hotspot.tools.jcore.ClassDump

可以把類的class內容dump到文件裏。

ClassDump 裏可以設置兩個 System properties

  • sun.jvm.hotspot.tools.jcore.filter Filter的類名
  • sun.jvm.hotspot.tools.jcore.outputDir 輸出的目錄

示例

首先寫一個 filter


import sun.jvm.hotspot.tools.jcore.ClassFilter;
import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.tools.jcore.ClassDump;
public class MyFilter implements ClassFilter {
    @Override
    public boolean canInclude(InstanceKlass kls) {
        String klassName = kls.getName().asString();
        return klassName.startsWith("com/fr/license/selector/");
    }
}  

代碼很顯而易見了, 作用是 dump 所有 以 com/fr/license/selector/ 開頭的 類的· 字節碼。

然後編譯成class文件

要使用這個首先需要把 sa-jdi.jar 加到 javaclasspath 裏。

技術分享圖片

進入 剛剛寫的 filter 類的class文件的目錄下。執行


java  -Dsun.jvm.hotspot.tools.jcore.filter=MyFilter  -Dsun.jvm.hotspot.tools.jcore.outputDir=d:\dump  sun.jvm.hotspot.tools.jcore.ClassDump 5308

MyFilter

改為你自己的類名, 5308 為目標 java進程的 pid(可以使用 jps 查看)。然後就會在 d:\dump 產生相應的 class 文件。

問題解決

  • 如果直接點擊應用的 exe, 來啟動應用,使用 jps 獲取到的 pid, 可能沒有辦法附加, 所以我們要找到啟動的命令, 比如 bat腳本裏面。

  • 一般大型應用會自帶 jre, 我們要使用上面的技術,替換 jre,為我們的,才能正常dump, 否則會出現版本不匹配。
  • windows下還需把 sawindbg.dll 放到 jre/bin/ 和java.exe 同目錄下。否則可能會遇到 加載不了這個 dll 的問題。

技術分享圖片

最後

搞java應用第一步還是找到啟動的命令,便於後面的分析。一般別使用 exe啟動應用

使用sa-jdi.jar dump 內存中的class