这里我有一个简单的添加java程序
import java.util.Scanner;
public class Main {
public static int add(int a, int b)
{
return a+b;
}
public static void main(String [] argv)
{
String a="Hello world";
int b=499,c=599;
int v= add(b,c);
}
}
现在我正在使用一个操作程序来操作java程序的类文件。
package com.seriouscompany.program;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodNode;
public class Manipulator {
//!!Change this to the path to your application's path!!
public static final File PROGRAM_APPLICATION_JAR = new File("C:\\Users\\jayarasr\\Desktop\\SeriousProgram.jar");
private static List<ClassNode> classNodes = new ArrayList<>();
public static void main(String[] args) throws FileNotFoundException {
PrintStream o = new PrintStream(new File("A.txt"));
System.setOut(o);
classNodes = load(PROGRAM_APPLICATION_JAR);
for(ClassNode classNode : classNodes) {
System.out.println("------------------");
System.out.println("Class Node :"+classNode.name);
for(Object methodNodeObj : classNode.methods) {
MethodNode methodNode = (MethodNode)methodNodeObj;
System.out.println("Method Node :"+methodNode.name);
// if(methodNode.name.toString()=="main") {}
for(AbstractInsnNode abstractInsnNode : methodNode.instructions.toArray()) {
System.out.println("Abstract : "+abstractInsnNode.getOpcode());
if(abstractInsnNode instanceof LdcInsnNode) {
LdcInsnNode ldcInsn = (LdcInsnNode)abstractInsnNode;
System.out.println("Value :"+ldcInsn.cst);
}
}
}
}
save(new File(PROGRAM_APPLICATION_JAR.getAbsolutePath().replace(".jar", "dumped.jar")), classNodes);
}
public static void save(File jar, final List<ClassNode> nodes) {
try {
try(final JarOutputStream output = new JarOutputStream(new FileOutputStream(jar))) {
for(ClassNode element : nodes) {
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
output.putNextEntry(new JarEntry(element.name.replaceAll("\\.", "/") + ".class"));
output.write(writer.toByteArray());
output.closeEntry();
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
public static List<ClassNode> load(File file) {
try {
JarFile jar = new JarFile(file);
List<ClassNode> list = new ArrayList<>();
Enumeration<JarEntry> enumeration = jar.entries();
while(enumeration.hasMoreElements()) {
JarEntry next = enumeration.nextElement();
if(next.getName().endsWith(".class")) {
ClassReader reader = new ClassReader(jar.getInputStream(next));
ClassNode node = new ClassNode();
reader.accept(node, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
list.add(node);
}
}
jar.close();
return list;
} catch(IOException e) {
e.printStackTrace();
}
return null;
}
}
在这里,我可以打印类名,方法名和常量值。 现在我的查询是如何打印变量名称,称为函数名称(调用一个)(我只能找到操作码) 我阅读了ASM的文档,然后去了解这个, 请帮我找到上面提到的查询。
答案 0 :(得分:0)
要掌握调用方法的名称,您必须检查MethodNodeInsn
的属性,该属性定义任何被调用方法的所有者,方法名称和描述符。要掌握变量名称,您需要阅读local variable table什么是调试信息,这些信息不一定存在于所有类中。