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

Posted hac425

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用sa-jdi.jar dump 内存中的class相关的知识,希望对你有一定的参考价值。

前言

在分析一个 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的主要内容,如果未能解决你的问题,请参考以下文章

使用sos的dump***命令查看一些东西

vc 怎么 生成 dump 文件

Jvm dump介绍与使用(内存与线程)

[转载] 从正在运行的Linux进程中dump出内存内容

Linux Dump 内存

json字符串与字典之间的相互转换,即loads(load)dumps(dump)