这应该分成两个问题,1.如何获取参数值. 2.如何获取参数名, 1.如何获取参数值。这个是运行时的数据,你程序处理下获取就好了。比如写一个代理 2.参数名是在编译的时候就写入到class文件的。,而这些方法的参数在class中就是一个局部变量。class对于局部变量的定义和存储专门有张表。 单纯通过反射目前好像没有办法,通过字节码解析倒是可以 比如下面代码 public static void staticMethod(String args1, String args2) { } 局部变量表: [pc: 0, pc: 1] local: args1 index: 0 type: java.lang.String [pc: 0, pc: 1] local: args2 index: 1 type: java.lang.String pc 0是每个字节码指令的程序计数器。[pc: 0, pc: 1] local: args1 index: 0 type: java.lang.String就是说在程序第0个指令到第1个指令的局部变量数组下标为0的变量类型是String变量名是args1. public static void nonStaticMethod(String args1, String args2) { } 局部变量表; [pc: 0, pc: 1] local: this index: 0 type: asmtest.Test [pc: 0, pc: 1] local: args1 index: 1 type: java.lang.String [pc: 0, pc: 1] local: args2 index: 2 type: java.lang.String 这个方法比上面的方法多了一个this。因为这个方法是非静态方法。 所以如果要获取参数名需要解析字节码。这里给你一段代码使用ASM import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map; import org.objectweb.asm.ClassVisitor;import org.objectweb.asm.MethodVisitor;import org.objectweb.asm.Opcodes;import org.objectweb.asm.Type; public class ReadMethodArgNameClassVisitor extends ClassVisitor { public Map<String, List<String>> nameArgMap = new HashMap<String, List<String>>(); public ReadMethodArgNameClassVisitor() { super(Opcodes.ASM5); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { Type methodType = Type.getMethodType(desc); int len = methodType.getArgumentTypes().length; List<String> argumentNames = new ArrayList<String>(); nameArgMap.put(name, argumentNames); ReadMethodArgNameMethodVisitor visitor = new ReadMethodArgNameMethodVisitor(Opcodes.ASM5); visitor.argumentNames = argumentNames; visitor.argLen = len; return visitor; }} import java.util.List; import org.objectweb.asm.Label;import org.objectweb.asm.MethodVisitor; public class ReadMethodArgNameMethodVisitor extends MethodVisitor { public List<String> argumentNames; public int argLen; public ReadMethodArgNameMethodVisitor(int api) { super(api); } @Override public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { if("this".equals(name)) { return; } if(argLen-- > 0) { argumentNames.add(name); } } } public class POJO { public void say(String message, int times){ } } import java.io.IOException;import java.util.List;import java.util.Map.Entry; import org.objectweb.asm.ClassReader; public class Test { public static void main(String... args1) throws IOException { ClassReader cr = new ClassReader("POJO"); ReadMethodArgNameClassVisitor classVisitor = new ReadMethodArgNameClassVisitor(); cr.accept(classVisitor, 0); for(Entry<String, List<String>> entry : classVisitor.nameArgMap.entrySet()) { System.out.println(entry.getKey()); for(String s : entry.getValue()) { System.out.println(" " + s); } } } } 使用asm版本是 <dependency> <groupId>org.ow2.asm</groupId> <artifactId>asm-all</artifactId> <version>5.0.3</version></dependency> 这里存在一个隐患,如果有些class文件做了加密混淆吧局部变量表里面的变量名改变了,那就没法获得源码级别的参数名了。
时间: 2025-01-02 17:22:25