如何获得JVM执行过程中调用的方法名
2023-09-14 09:07:42 时间
这应该分成两个问题,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文件做了加密混淆吧局部变量表里面的变量名改变了,那就没法获得源码级别的参数名了。
相关文章
- JVM内存与垃圾回收篇第1章JVM和Java体系架构
- 阿里巴巴JVM调优工具arthas「建议收藏」
- jvm最全详解-05-JVM调优工具详解及调优实战[通俗易懂]
- 第一章、JVM和Java体系架构
- JVM面试题详解
- jvm基础_java实现栈四个方法
- 暴力解析美团最新JVM面试题:无限执行
- JVM 面试基础准备篇(一)
- 【Java 虚拟机原理】栈帧 | 局部变量表 | 操作数栈 | 方法出口 | JVM 指令逐条解析
- JVM垃圾回收的 “三色标记算法” 实现,内容太干!
- java 检测 Java 是否运行在64bit 的JVM上详解编程语言
- Tomcat的JVM和连接数设置详解编程语言
- 改变JVM中的参数以提高Eclipse的运行速度详解编程语言
- JVM的内部组成详解编程语言
- 理解JVM——JVM的结构详解编程语言
- Linux监控JVM系统性能优化实战(linux监控jvm)
- 深入了解Linux与JVM编码技术(linuxjvm编码)
- 如何在Linux系统上安装JVM?-教你简单易懂的方法(linux安装jvm)
- 如何在Linux上查看JVM运行信息(Linux查看jvm)
- Linux JVM GC管理追求极致性能(linux jvm gc)
- 如何在Linux下修改JVM参数配置(linux修改jvm参数)
- Oracle控制下的JVM开启新的技术时代(jvm受oracle控制)
- Oracle的JVM实现高性能成就突破(jvm属于oracle)
- 解锁Oracle指引你的JVM下载之旅(jvm下载oracle)
- Oracle中Java虚拟机的应用与研究(oracle中jvm)
- Redis引发JVM崩溃一个值得警惕的潜在风险(redis造成jvm死掉)
- Oracle JVM组件值得信赖的可靠性(oracle jvm组件)
- 在Oracle JVM环境下进行下载的指南(oracle jvm下载)