package command;
import enhancer.AsmEnhancer;
import enhancer.MyAdvice;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatchers;
import org.jd.core.v1.ClassFileToJavaSourceDecompiler;
import org.jd.core.v1.api.loader.Loader;
import org.jd.core.v1.api.loader.LoaderException;
import org.jd.core.v1.api.printer.Printer;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.stream.Collectors;
public class ClassCommand {
/**
* 打印所有的类加载器
* 形参直接用Instrumentation对象,在premain或者agentmain方法中,JDK会自己注入
*/
public static void printAllClassLoader(Instrumentation inst) {
//获取所有已加载的类
Class[] allLoadedClasses = inst.getAllLoadedClasses();
//用于去重,因为类加载器就那几种
Set<ClassLoader> classLoaderSet = new HashSet<>();
for (Class loadedClass : allLoadedClasses) {
ClassLoader classLoader = loadedClass.getClassLoader();
classLoaderSet.add(classLoader);
}
//打印类加载器
String classLoaderInfo = classLoaderSet.stream()
.map(x -> {
//获取启动类加载器的结果为null,这里我直接给个固定的名字
if (x == null) {
return "BootStrapClassLoader";
}
//其他的类加载器就正常输出
return x.getName();
})
//类加载器名字为空的不要
.filter(x -> x != null)
.distinct()
.sorted(String::compareTo)
.collect(Collectors.joining(","));
System.out.println(classLoaderInfo);
}
/**
* 打印类的源代码
*/
public static void printClassSourceCode(Instrumentation inst) {
//输入全类名
System.out.println("请输入全类名:");
Scanner scanner = new Scanner(System.in);
String className = scanner.next();
//获取所有已加载的类,从中找到用户要的类的class对象
Class[] allLoadedClasses = inst.getAllLoadedClasses();
for (Class loadedClass : allLoadedClasses) {
//找到了
if (className.equals(loadedClass.getName())) {
//转换器
ClassFileTransformer transformer = new ClassFileTransformer() {
@Override
//transform方法传入一个字节码信息,返回一个增强后的字节码信息,以下代码的写法,返回null即不增强,这里只要原来的字节码
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
//通过jd-code反编译,打印出源码
printJdCoreSourceCode(classfileBuffer, className);
return ClassFileTransformer.super.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer); //直接调用以有的父类,返回null,即不改,因为这里只要获取最初的字节码
}
};
//添加转换器,让转换器生效,参数二为true即可手动触发
inst.addTransformer(transformer, true);
//触发转换器
try {
inst.retransformClasses(loadedClass);
} catch (UnmodifiableClassException e) {
e.printStackTrace();
} finally {
//使用完之后删除转换器
inst.removeTransformer(transformer);
}
}
}
}
/**
* jd-code打印源码
* bytes 字节码信息
*/
private static void printJdCoreSourceCode(byte[] bytes, String className) {
//loader对象
Loader loader = new Loader() {
@Override
public byte[] load(String internalName) throws LoaderException {
return bytes;
}
@Override
public boolean canLoad(String internalName) {
return true; //类可加载
}
};
//Printer对象,注意重写end方法,打印源代码
Printer printer = new Printer() {
protected static final String TAB = " ";
protected static final String NEWLINE = "\n";
protected int indentationCount = 0;
protected StringBuilder sb = new StringBuilder();
@Override
public String toString() {
return sb.toString();
}
@Override
public void start(int maxLineNumber, int majorVersion, int minorVersion) {
}
@Override
public void end() {
//打印源代码
System.out.println(sb);
}
@Override
public void printText(String text) {
sb.append(text);
}
@Override
public void printNumericConstant(String constant) {
sb.append(constant);
}
@Override
public void printStringConstant(String constant, String ownerInternalName) {
sb.append(constant);
}
@Override
public void printKeyword(String keyword) {
sb.append(keyword);
}
@Override
public void printDeclaration(int type, String internalTypeName, String name, String descriptor) {
sb.append(name);
}
@Override
public void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName) {
sb.append(name);
}
@Override
public void indent() {
this.indentationCount++;
}
@Override
public void unindent() {
this.indentationCount--;
}
@Override
public void startLine(int lineNumber) {
for (int i = 0; i < indentationCount; i++) sb.append(TAB);
}
@Override
public void endLine() {
sb.append(NEWLINE);
}
@Override
public void extraLine(int count) {
while (count-- > 0) sb.append(NEWLINE);
}
@Override
public void startMarker(int type) {
}
@Override
public void endMarker(int type) {
}
};
//通过jd-code打印
ClassFileToJavaSourceDecompiler decompiler = new ClassFileToJavaSourceDecompiler();
try {
decompiler.decompile(loader, printer, className);
} catch (Exception e) {
e.printStackTrace();
}
}
//对类进行增强
public static void enhanceClass(Instrumentation inst) {
System.out.println("请输入类名:");
//让用户输入类名
Scanner scanner = new Scanner(System.in);
String className = scanner.next();
//根据类名找到class对象
Class[] allLoadedClasses = inst.getAll