文档章节

使用ASM获得JAVA类方法参数名

G
 Galanodel
发布于 2017/05/09 09:20
字数 439
阅读 13
收藏 0

在Java1.8之后,可以通过反射API java.lang.reflect.Executable.getParameters来获取到方法参数的元信息,(在使用编译器时加上-parameters参数,它会在生成的.class文件中额外存储参数的元信息)
但是在JDK1.7及以下版本的API并不能获取到函数的参数名称,这时候可以使用字节码工具ASM来实现这一功能.

package yyl.example.demo.asm;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;

/** * 使用ASM获得JAVA类方法参数名 */
public class GetMethodParamNameTest {
	static class Test {
		void method(String name, Object value) {
		}
	}

	public static void main(String[] args) throws SecurityException, NoSuchMethodException, IOException {
		Method method1 = Test.class.getDeclaredMethod("method", String.class, Object.class);
		System.out.println(Arrays.toString(getMethodParamNames(method)));
	}

	/** 使用字节码工具ASM来获取方法的参数名 */
	public static String[] getMethodParamNames(final Method method) throws IOException {
		final String methodName = method.getName();
		final Class<?>[] methodParameterTypes = method.getParameterTypes();
		final int methodParameterCount = methodParameterTypes.length;
		final String className = method.getDeclaringClass().getName();
		final boolean isStatic = Modifier.isStatic(method.getModifiers());
		final String[] methodParametersNames = new String[methodParameterCount];
		ClassReader cr = new ClassReader(className);
		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
		cr.accept(new ClassAdapter(cw) {
			public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
				MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
				final Type[] argTypes = Type.getArgumentTypes(desc); //参数类型不一致
				if (!methodName.equals(name) || !matchTypes(argTypes, methodParameterTypes)) {
					return mv;
				}
				return new MethodAdapter(mv) {
					public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { //如果是静态方法,第一个参数就是方法参数,非静态方法,则第一个参数是 this ,然后才是方法的参数
						int methodParameterIndex = isStatic ? index : index - 1;
						if (0 <= methodParameterIndex && methodParameterIndex < methodParameterCount) {
							methodParametersNames[methodParameterIndex] = name;
						}
						super.visitLocalVariable(name, desc, signature, start, end, index);
					}
				};
			}
		}, 0);
		return methodParametersNames;
	}

	/** * 比较参数是否一致 */
	private static boolean matchTypes(Type[] types, Class<?>[] parameterTypes) {
		if (types.length != parameterTypes.length) {
			return false;
		}
		for (int i = 0; i < types.length; i++) {
			if (!Type.getType(parameterTypes[i]).equals(types[i])) {
				return false;
			}
		}
		return true;
	}
}

备注:JDK 自带类 ,接口方法和抽象方法无法使用这种方式获取参数名

© 著作权归作者所有

G
粉丝 2
博文 72
码字总数 49356
作品 0
海淀
高级程序员
私信 提问
Java 字节码工具 ASM 在 web services 开发中的应用

在基于 JAX-WS 标准的 web services 的开发中,不少实际场景都是希望采用自底向上的开发方式, 即基于已有的 Java bean 来创建 web services 。WebSphere Application Server ( 以下简称 WA...

IBMdW
2011/09/26
2K
2
淘宝Tprofiler工具实现分析

项目首页:https://github.com/alibaba/TProfiler 工具介绍 TProfiler是一个可以在生产环境长期使用的性能分析工具.它同时支持剖析和采样两种方式,记录方法执行的时间和次数,生成方法热点 对...

伍咖
2015/11/14
0
0
asm学习2-java类在asm里的基本描述

上节里有关于asm的一些基本概念,比如:visit里的第一个类版本,方法的描述、引用描述等,下面将一一介绍。 类版本 一个Java二进制的类文件,都有一个版本,对应于不同的jdk版本。因此ASM中提...

messud4312
2015/02/06
0
0
Class文件格式实战:使用ASM动态生成class文件

概述 本专栏前面的文章,主要详细讲解了Class文件的格式,并且在上一篇文章中做了总结。 众所周知, JVM在运行时, 加载并执行class文件, 这个class文件基本上都是由我们所写的java源文件通...

长河
2018/09/12
0
0
关于java字节码框架ASM的学习

一、什么是ASM   ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Jav...

変態L
2014/01/14
0
1

没有更多内容

加载失败,请刷新页面

加载更多

面试爱奇艺,竟然挂在第5轮……

今天给大家分享我曾经在爱奇艺的面试,过程还是比较有意思的,可以给大家一些参考 <br> 聊骚阶段 嗲妹妹:你好,我是爱奇艺的HR,我们正在招聘运维开发岗位,请问您最近有在看工作机会吗? ...

上海小胖
33分钟前
1
0
Jenkins系列_插件安装及报错处理

进入Jenkins之后我们可以进行插件的安装,插件管理位于以下模块: 发现上面报了一堆错误,是因为插件的依赖没有安装好,那么这一节,就先把这些错误解决掉吧。解决完成后,也就基本会使用插件...

shzwork
今天
2
0
mysql mysql的所有查询语句和聚合函数(整理一下,忘记了可以随时看看)

查询所有字段 select * from 表名; 查询自定字段 select 字段名 from 表名; 查询指定数据 select * from 表名 where 条件; 带关键字IN的查询 select * from 表名 where 条件 [not] in(元素...

edison_kwok
昨天
9
0
解决多线程并行加载缓存问题(利用guava实现)

依赖 com.google.guava:guava:20.0 import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import java.util.concurrent.ExecutionException;import j......

暗中观察
昨天
4
0
利用VisualVM 内存查看

准备工作,建几个测试类。等下就是要查看这几个类里面的属性 package visualvm;public class MultiObject { private String str; private int i; MultiObject(String str...

冷基
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部