目录
一、概述
1、通灵之术
通灵之术:在《火影忍者》中,通灵之术,属于时空间忍术的一种。
如下图,可以召唤通灵兽。
那么,"通灵之术",在Java领域,代表什么意思呢?
就是将正在运行的JVM当中的class进行导出。
借助Java Agent将class文件从JVM当中导出。
HelloWorld.class在JVM中运行,通过Java Agent把 HelloWorld.class从JVM中下载出来。
2、Java Agent
曾经有一篇文章《Retrieving .class files from a running app》,最初是发表在Sun公司的网站,后来转移到了Oracle的网站,再后来就从Oracle网站消失了。
Sometimes it is better to dump .class files of generated/modified classes for off-line debugging - for example, we may want to view such classes using tools like jclasslib.
===============================================================
ClassDumpAgent.java
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.util.ArrayList;
import java.util.List;
/**
* This is a java.lang.instrument agent to dump .class files
* from a running Java application.
*/
public class ClassDumpAgent {
public static void premain(String agentArgs, Instrumentation inst) {
agentmain(agentArgs, inst);
}
/**
*
* @param agentArgs:输出路径/正则表达式
* @param inst:JVM传参
*/
@SuppressWarnings("rawtypes")
public static void agentmain(String agentArgs, Instrumentation inst) {
System.out.println("agentArgs: " + agentArgs);
ClassDumpUtils.parseArgs(agentArgs);
inst.addTransformer(new ClassDumpTransformer(), true);
// by the time we are attached, the classes to be
// dumped may have been loaded already.
// So, check for candidates in the loaded classes.
Class[] classes = inst.getAllLoadedClasses();
List<Class> candidates = new ArrayList<>();
for (Class c : classes) {
String className = c.getName();
// 第一步,排除法:不考虑JDK自带的类
if (className.startsWith("java")) continue;
if (className.startsWith("javax")) continue;
if (className.startsWith("jdk")) continue;
if (className.startsWith("sun")) continue;
if (className.startsWith("com.sun")) continue;
// 第二步,筛选法:只留下感兴趣的类(正则表达式匹配)
boolean isModifiable = inst.isModifiableClass(c);
boolean isCandidate = ClassDumpUtils.isCandidate(className);
if (isModifiable && isCandidate) {
candidates.add(c);
}
// 不重要:打印调试信息
String message = String.format("[DEBUG] Loaded Class: %s ---> Modifiable: %s, Candidate: %s", className, isModifiable, isCandidate);
System.out.println(message);
}
try {
// 第三步,将具体的class进行dump操作
// if we have matching candidates, then retransform those classes
// so that we will get callback to transform.
if (!candidates.isEmpty()) {
inst.retransformClasses(candidates.toArray(new Class[0]));
// 不重要:打印调试信息
String message = String.format("[DEBUG] candidates size: %d", cand