查看运行时生成的文件, 以更清楚运行情况.
查看动态生成的类, 一般有两个方法:
1. 使用 sd-jdi.jar 里的工具.
其中, 不想自己搞, 当然就利用下, 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 输出的目录
sd-jdi.jar 里有一个 sun.jvm.hotspot.tools.jcore.PackageNameFilter, 可以指定 Dump 哪些包里的类. PackageNameFilter 里有一个 System property 可以指定过滤哪些包: sun.jvm.hotspot.tools.jcore.PackageNameFilter.pkgList.
所以可以通过这样子的命令来使用:
sudo java -classpath "$JAVA_HOME/lib/sa-jdi.jar" -Dsun.jvm.hotspot.tools.jcore.filter=sun.jvm.hotspot.tools.jcore.PackageNameFilter -Dsun.jvm.hotspot.tools.jcore.PackageNameFilter.pkgList=com.test sun.jvm.hotspot.tools.jcore.ClassDump <pid>
不过, 我在 windows 下并没有成功过, 原因是还要要求我 start SwDbgSrv.exe, 搞不了.
其中 sa-jdi.jar 文件也不那么好找呢, 不过也能找到!
所以, 还不如自己动手, 丰衣足食!
2. 自己重写一个记录工具, 用 agent attatch 到进程, 然后利用 Instrumentation 和 ClassFileTransformer 就可以获取 到类的字节码了.
工具类如下:
- package com.xxx.test;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.lang.instrument.ClassFileTransformer;
- import java.lang.instrument.IllegalClassFormatException;
- import java.lang.instrument.Instrumentation;
- import java.security.ProtectionDomain;
- /**
- * 动态生成类拦截查看工具
- *
- * @date 2018/9/15
- */
- public class ClazzDumpCustomAgent implements ClassFileTransformer {
- /**
- * 导出过滤表达式, 此处为类名前缀, 使用 -f 进行输入
- */
- private String filterStr;
- /**
- * 导出文件目录根目录, 使用 -d 进行输入
- */
- private String exportBaseDir = "/tmp/";
- public ClazzDumpCustomAgent(String exportBaseDir, String filterStr) {
- if(exportBaseDir != null) {
- this.exportBaseDir = exportBaseDir;
- }
- this.filterStr = filterStr;
- }
- /**
- * 入口地址
- *
- * @param agentArgs agent 参数
- * @param inst
- */
- public static void premain(String agentArgs, Instrumentation inst) {
- System.out.println("agentArgs:" + agentArgs);
- String exportDir = null;
- String filterStr = null;
- if(agentArgs != null) {
- if(agentArgs.contains(";")) {
- String[] args = agentArgs.split(";");
- for (String param1 : args) {
- String[] kv = param1.split("=");
- if("-d".equalsIgnoreCase(kv[0])) {
- exportDir = kv[1];
- }
- else if("-f".equalsIgnoreCase(kv[0])) {
- filterStr = kv[1];
- }
- }
- }
- else {
- filterStr = agentArgs;
- }
- }
- inst.addTransformer(new ClazzDumpCustomAgent(exportDir, filterStr));
- }
- @Override
- public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
- if (needExportClass(className)) {
- int lastSeperatorIndex = className.lastIndexOf("/") + 1;
- String fileName = className.substring(lastSeperatorIndex) + ".class";
- exportClazzToFile(exportBaseDir, fileName, classfileBuffer); //"D:/server-tool/tmp/bytecode/exported/"
- System.out.println(className + "--> EXPORTED");
- }
- return classfileBuffer;
- }
- /**
- * 检测是否需要进行文件导出
- *
- * @param className class 名, 如 com.xx.abc.AooMock
- * @return y/n
- */
- private boolean needExportClass(String className) {
- if(filterStr != null) {
- if(className.startsWith(filterStr)) {
- return true;
- }
- else {
- return false;
- }
- }
- if (!className.startsWith("java") && !className.startsWith("sun")) {
- return true;
- }
- return false;
- }
- /**
- * 执行文件导出写入
- *
- * @param dirPath 导出目录
- * @param fileName 导出文件名
- * @param data 字节流
- */
- private void exportClazzToFile(String dirPath, String fileName, byte[] data) {
- try {
- File dir = new File(dirPath);
- if(!dir.isDirectory()) {
- dir.mkdirs();
- }
- File file = new File(dirPath + fileName);
- if (!file.exists()) {
- file.createNewFile();
- }
- FileOutputStream fos = new FileOutputStream(file);
- fos.write(data);
- fos.close();
- }
- catch (Exception e) {
- System.out.println("exception occured while doing some file operation");
- e.printStackTrace();
- }
- }
- }
写好工具类后, 将其打包为 jar 包文件,(如何打包此类请查看上一篇文章: http://www.cnblogs.com/yougewe/), 假如打包后的文件命名名 clazzdumpcustagent.jar .
使用该 jar 包工具, 进行运行时 class 文件查看: idea 中如何将单个 java 类导出为 jar 包文件?
在运行项目时, 添加 javaagent, 进行代码导出:
- # 在 vm 参数中, 加入该 agent
- -javaagent:/tool/tmp/clazzdumpcustagent.jar=-d=/tmp/bytecode/exported/;-f=com/alibaba/dubbo
然后可以到指定目录下去查看生成的字节码文件了.
最后, 使用 java 反编译工具, 查看 java 代码就 ok 了.(可以直接拖进 IDE 进行解析)
如果不想自己打包, 我打了个包放在网上, 有需要可自行下载! https://download.csdn.net/download/nihe123yiyang/10670937
相信在必要的时候, 可以派上用场!
来源: https://www.cnblogs.com/yougewe/p/9651555.html