class="markdown_views prism-tomorrow-night">
1、ReflectASM 简介
1.1 什么是class ="tags" href="/tags/FanShe.html" title=反射>反射?
一般情况下,我们使用某个类时已经知道它是什么类了,用来做什么的,所以我们直接将这个类 进行实例化,然后使用这个类对象进行操作 class ="tags" href="/tags/FanShe.html" title=反射>反射就是在运行的过程中才知道要操作的类是什么。Java class ="tags" href="/tags/FanShe.html" title=反射>反射实在运行的过程中,对任意一个类,都可以知道这个类的所有属性和方法,对一个对象,都能够调用任意一个方法和属性,这种动态获取的信息和调用对象方法的功能称为 class ="tags" href="/tags/JAVA.html" title=java>java 的class ="tags" href="/tags/FanShe.html" title=反射>反射机制。 我们可以使用 class ="tags" href="/tags/JAVA.html" title=java>java.lang.Class
类,这个为了实现class ="tags" href="/tags/FanShe.html" title=反射>反射体用的一个类,通过全类名获取到class ="tags" href="/tags/FanShe.html" title=反射>反射的 Class 对象,然后通过 class 对象实现调用它的方法、获取属性、获取类信息等操作
1.2 什么是 reflectASM?
ASM 可以用来进行字节码操作,可以修改现有类或者以二进制形式动态生成类,ReflectASM 使用了 ASM,使用字节码生成的方式实现了更高效的class ="tags" href="/tags/FanShe.html" title=反射>反射机制。执行时会生成一个存取类来 set/get 字段,访问方法或者创建实例。不是依赖于 Java 本身的class ="tags" href="/tags/FanShe.html" title=反射>反射机制实现的,所以更快,而且避免了访问原始类型因自动装箱而产生的问题 ReflectASM 是一个非常小的 Java 类库,只有五个类,却提供了非常高性能的属性操作、方法调用、构造方法调用等,
2、maven 依赖
class="prism language-xml">class="token tag">class="token tag">class="token punctuation">< dependency class="token punctuation">>
class="token tag">class="token tag">class="token punctuation">< groupId class="token punctuation">> com.esotericsoftwareclass="token tag">class="token tag">class="token punctuation"></ groupId class="token punctuation">>
class="token tag">class="token tag">class="token punctuation">< artifactId class="token punctuation">> reflectasmclass="token tag">class="token tag">class="token punctuation"></ artifactId class="token punctuation">>
class="token tag">class="token tag">class="token punctuation">< version class="token punctuation">> 1.11.0class="token tag">class="token tag">class="token punctuation"></ version class="token punctuation">>
class="token tag">class="token tag">class="token punctuation"></ dependency class="token punctuation">>
reflectASM 提供了根据匹配的字符串操作变量、函数的特性,reflectASM 中常用常用的类只有 MethodAccess,FieldAccess,Constructor 这几个
3、class ="tags" href="/tags/FanShe.html" title=反射>反射调用测试
class ="tags" href="/tags/FanShe.html" title=反射>反射对象
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token annotation punctuation">@Data
class="token annotation punctuation">@Builder
class="token annotation punctuation">@NoArgsConstructor
class="token annotation punctuation">@AllArgsConstructor
class="token keyword">public class="token keyword">class class="token class -name">PlanBarCodeExcel class="token punctuation">{
class="token keyword">private class="token class -name">String barCodeclass="token punctuation">;
class="token keyword">public class="token class -name">String brandNameclass="token punctuation">;
class="token keyword">private class="token class -name">String packingNumclass="token punctuation">;
class="token keyword">private class="token class -name">String channelCodeclass="token punctuation">;
class="token punctuation">}
reflectASM 使用
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">public class="token keyword">class class="token class -name">ReflectASMDemo class="token punctuation">{
class="token comment">/**
* jdk class ="tags" href="/tags/FanShe.html" title=反射>反射调用方法
* @throws Exception
*/
class="token keyword">public class="token keyword">static class="token keyword">void class="token function">jdkReflect class="token punctuation">( class="token punctuation">) class="token keyword">throws class="token class -name">Exception class="token punctuation">{
class="token class -name">PlanBarCodeExcel planBarCodeExcel class="token operator">= class="token keyword">new class="token class -name">PlanBarCodeExcel class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token class -name">Method setBarCode class="token operator">= planBarCodeExcelclass="token punctuation">. class="token function">getClass class="token punctuation">( class="token punctuation">) class="token punctuation">. class="token function">getMethod class="token punctuation">( class="token string">"setBarCode" class="token punctuation">, class="token class -name">String class="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">;
setBarCodeclass="token punctuation">. class="token function">invoke class="token punctuation">( planBarCodeExcelclass="token punctuation">, class="token string">"barCode" class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token comment">/**
* reflectASMclass ="tags" href="/tags/FanShe.html" title=反射>反射调用方法
* 需要注意的是,reflectASM 提供的方法只能调用非私有的属性和方法,私有属性需要通过 get/set 方法调用
* @throws Exception
*/
class="token keyword">public class="token keyword">static class="token keyword">void class="token function">reflectASMByName class="token punctuation">( class="token punctuation">) class="token keyword">throws class="token class -name">Exception class="token punctuation">{
class="token comment">// 使用 MethodAccess class ="tags" href="/tags/FanShe.html" title=反射>反射调用方法
class="token class -name">PlanBarCodeExcel planBarCodeExcel class="token operator">= class="token keyword">new class="token class -name">PlanBarCodeExcel class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token class -name">MethodAccess access class="token operator">= class="token class -name">MethodAccess class="token punctuation">. class="token function">get class="token punctuation">( class="token class -name">PlanBarCode class="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">;
methodAccessclass="token punctuation">. class="token function">invoke class="token punctuation">( planBarCodeExcelclass="token punctuation">, class="token string">"setBarCode" class="token punctuation">, class="token string">"barCode" class="token punctuation">) class="token punctuation">;
class="token class -name">String getBarCode class="token operator">= class="token punctuation">( class="token class -name">String class="token punctuation">) methodAccessclass="token punctuation">. class="token function">invoke class="token punctuation">( planBarCodeExcelclass="token punctuation">, class="token string">"getBarCode" class="token punctuation">) class="token punctuation">;
class="token class -name">System class="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( getBarCodeclass="token punctuation">) class="token punctuation">;
class="token comment">// 如果方法重载有同名方法的话,找到方法的索引执行方法,相比通过名称访问成员,索引的方式会更快
class="token keyword">int setChannelCodeIndex class="token operator">= methodAccessclass="token punctuation">. class="token function">getIndex class="token punctuation">( class="token string">"setChannelCode" class="token punctuation">, class="token class -name">String class="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">;
methodAccessclass="token punctuation">. class="token function">invoke class="token punctuation">( planBarCodeExcelclass="token punctuation">, setChannelCodeIndexclass="token punctuation">, class="token string">"111" class="token punctuation">) class="token punctuation">;
class="token comment">// 使用 FieldAccess class ="tags" href="/tags/FanShe.html" title=反射>反射 set/get 字段
class="token class -name">FieldAccess fieldAccess class="token operator">= class="token class -name">FieldAccess class="token punctuation">. class="token function">get class="token punctuation">( class="token class -name">PlanBarCode class="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">;
fieldAccessclass="token punctuation">. class="token function">set class="token punctuation">( planBarCodeExcelclass="token punctuation">, class="token string">"brandName" class="token punctuation">, class="token string">"brandName" class="token punctuation">) class="token punctuation">;
class="token class -name">String brandName class="token operator">= class="token punctuation">( class="token class -name">String class="token punctuation">) fieldAccessclass="token punctuation">. class="token function">get class="token punctuation">( planBarCodeExcelclass="token punctuation">, class="token string">"brandName" class="token punctuation">) class="token punctuation">;
class="token class -name">System class="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( brandNameclass="token punctuation">) class="token punctuation">;
class="token comment">// ConstructorAccessclass ="tags" href="/tags/FanShe.html" title=反射>反射调用构造方法
class="token class -name">ConstructorAccess class="token generics">class="token punctuation">< class="token class -name">PlanBarCodeExcel class="token punctuation">> planBarCodeExcelConstructorAccess class="token operator">= class="token class -name">ConstructorAccess class="token punctuation">. class="token function">get class="token punctuation">( class="token class -name">PlanBarCodeExcel class="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">;
class="token class -name">PlanBarCodeExcel planBarCodeExcel1 class="token operator">= planBarCodeExcelConstructorAccessclass="token punctuation">. class="token function">newInstance class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
4、reflectASM 原理解析
4.1 MethodAccess 源码
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">public class="token keyword">abstract class="token keyword">class class="token class -name">MethodAccess class="token punctuation">{
class="token comment">// 这三个私有变量用来存储要class ="tags" href="/tags/FanShe.html" title=反射>反射 Class 的方法名称、参数、返回值等信息
class="token keyword">private class="token class -name">String class="token punctuation">[ class="token punctuation">] methodNamesclass="token punctuation">;
class="token keyword">private class="token class -name">Class class="token punctuation">[ class="token punctuation">] class="token punctuation">[ class="token punctuation">] parameterTypesclass="token punctuation">;
class="token keyword">private class="token class -name">Class class="token punctuation">[ class="token punctuation">] returnTypesclass="token punctuation">;
class="token keyword">static class="token keyword">public class="token class -name">MethodAccess get class="token punctuation">( class="token class -name">Class typeclass="token punctuation">) class="token punctuation">{
class="token comment">// 准备class ="tags" href="/tags/FanShe.html" title=反射>反射信息
class="token class -name">ArrayList class="token generics">class="token punctuation">< class="token class -name">Method class="token punctuation">> methods class="token operator">= class="token keyword">new class="token class -name">ArrayList class="token generics">class="token punctuation">< class="token class -name">Method class="token punctuation">> class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token keyword">boolean isInterface class="token operator">= typeclass="token punctuation">. class="token function">isInterface class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token keyword">if class="token punctuation">( class="token operator">! isInterfaceclass="token punctuation">) class="token punctuation">{ class="token comment">// 判断是否为接口
class="token class -name">Class nextClass class="token operator">= typeclass="token punctuation">;
class="token keyword">while class="token punctuation">( nextClass class="token operator">!= class="token class -name">Object class="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">{
class="token comment">// 类中的公共非静态方法添加到 methods 中
class="token function">addDeclaredMethodsToList class="token punctuation">( nextClassclass="token punctuation">, methodsclass="token punctuation">) class="token punctuation">;
nextClass class="token operator">= nextClassclass="token punctuation">. class="token function">getSuperclass class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">} class="token keyword">else class="token punctuation">{
class="token function">recursiveAddInterfaceMethodsToList class="token punctuation">( typeclass="token punctuation">, methodsclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token keyword">int n class="token operator">= methodsclass="token punctuation">. class="token function">size class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token class -name">String class="token punctuation">[ class="token punctuation">] methodNames class="token operator">= class="token keyword">new class="token class -name">String class="token punctuation">[ nclass="token punctuation">] class="token punctuation">;
class="token class -name">Class class="token punctuation">[ class="token punctuation">] class="token punctuation">[ class="token punctuation">] parameterTypes class="token operator">= class="token keyword">new class="token class -name">Class class="token punctuation">[ nclass="token punctuation">] class="token punctuation">[ class="token punctuation">] class="token punctuation">;
class="token class -name">Class class="token punctuation">[ class="token punctuation">] returnTypes class="token operator">= class="token keyword">new class="token class -name">Class class="token punctuation">[ nclass="token punctuation">] class="token punctuation">;
class="token keyword">for class="token punctuation">( class="token keyword">int i class="token operator">= class="token number">0 class="token punctuation">; i class="token operator">< nclass="token punctuation">; iclass="token operator">++ class="token punctuation">) class="token punctuation">{
class="token class -name">Method method class="token operator">= methodsclass="token punctuation">. class="token function">get class="token punctuation">( iclass="token punctuation">) class="token punctuation">;
methodNamesclass="token punctuation">[ iclass="token punctuation">] class="token operator">= methodclass="token punctuation">. class="token function">getName class="token punctuation">( class="token punctuation">) class="token punctuation">;
parameterTypesclass="token punctuation">[ iclass="token punctuation">] class="token operator">= methodclass="token punctuation">. class="token function">getParameterTypes class="token punctuation">( class="token punctuation">) class="token punctuation">;
returnTypesclass="token punctuation">[ iclass="token punctuation">] class="token operator">= methodclass="token punctuation">. class="token function">getReturnType class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token class -name">String class Name class="token operator">= typeclass="token punctuation">. class="token function">getName class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token comment">// 类名进行拼接,准备要生成新类的名字
class="token class -name">String accessClassName class="token operator">= class Name class="token operator">+ class="token string">"MethodAccess" class="token punctuation">;
class="token keyword">if class="token punctuation">( accessClassNameclass="token punctuation">. class="token function">startsWith class="token punctuation">( class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java." class="token punctuation">) class="token punctuation">) accessClassName class="token operator">= class="token string">"reflectasm." class="token operator">+ accessClassNameclass="token punctuation">;
class="token class -name">Class accessClassclass="token punctuation">;
class="token comment">// 获取该类的类加载器
class="token class -name">AccessClassLoader loader class="token operator">= class="token class -name">AccessClassLoader class="token punctuation">. class="token function">get class="token punctuation">( typeclass="token punctuation">) class="token punctuation">;
class="token keyword">synchronized class="token punctuation">( loaderclass="token punctuation">) class="token punctuation">{
class="token keyword">try class="token punctuation">{
class="token comment">// 如果动态生成的类已经生成过了,第二次调用是不会操作字节码生成的
accessClass class="token operator">= loaderclass="token punctuation">. class="token function">loadClass class="token punctuation">( accessClassNameclass="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token keyword">catch class="token punctuation">( class="token class -name">ClassNotFoundException ignoredclass="token punctuation">) class="token punctuation">{
class="token class -name">String accessClassNameInternal class="token operator">= accessClassNameclass="token punctuation">. class="token function">replace class="token punctuation">( class="token string">'.' class="token punctuation">, class="token string">'/' class="token punctuation">) class="token punctuation">;
class="token class -name">String class NameInternal class="token operator">= class Nameclass="token punctuation">. class="token function">replace class="token punctuation">( class="token string">'.' class="token punctuation">, class="token string">'/' class="token punctuation">) class="token punctuation">;
class="token class -name">ClassWriter cw class="token operator">= class="token keyword">new class="token class -name">ClassWriter class="token punctuation">( class="token class -name">ClassWriter class="token punctuation">. COMPUTE_MAXSclass="token punctuation">) class="token punctuation">;
class="token class -name">MethodVisitor mvclass="token punctuation">;
class="token comment">// 生成继承于 “com/esotericsoftware/reflectasm/MethodAccess” 类的子类
class="token comment">// 参数分别为:class ="tags" href="/tags/JAVA.html" title=java>java Version、类修饰符、类名、参数类型、父类、接口
cwclass="token punctuation">. class="token function">visit class="token punctuation">( V1_1class="token punctuation">, ACC_PUBLIC class="token operator">+ ACC_SUPERclass="token punctuation">, accessClassNameInternalclass="token punctuation">, class="token keyword">null class="token punctuation">, class="token string">"com/esotericsoftware/reflectasm/MethodAccess" class="token punctuation">, class="token keyword">null class="token punctuation">) class="token punctuation">;
class="token comment">// 下面这段代码生成构造方法
class="token punctuation">{
mv class="token operator">= cwclass="token punctuation">. class="token function">visitMethod class="token punctuation">( ACC_PUBLICclass="token punctuation">, class="token string">"<init>" class="token punctuation">, class="token string">"()V" class="token punctuation">, class="token keyword">null class="token punctuation">, class="token keyword">null class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitCode class="token punctuation">( class="token punctuation">) class="token punctuation">; class="token comment">// 开始生成方法
mvclass="token punctuation">. class="token function">visitVarInsn class="token punctuation">( ALOADclass="token punctuation">, class="token number">0 class="token punctuation">) class="token punctuation">; class="token comment">// 访问局部变量指令,加载或存储局部变量值的指令,从局部变量表 load 位置为 0 的变量到操作数栈
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESPECIALclass="token punctuation">, class="token string">"com/esotericsoftware/reflectasm/MethodAccess" class="token punctuation">, class="token string">"<init>" class="token punctuation">, class="token string">"()V" class="token punctuation">) class="token punctuation">; class="token comment">// 访问方法时的指令
mvclass="token punctuation">. class="token function">visitInsn class="token punctuation">( RETURNclass="token punctuation">) class="token punctuation">; class="token comment">// 访问一个字节码指令
mvclass="token punctuation">. class="token function">visitMaxs class="token punctuation">( class="token number">0 class="token punctuation">, class="token number">0 class="token punctuation">) class="token punctuation">; class="token comment">// 方法的局部变量表和操作数栈的大小
mvclass="token punctuation">. class="token function">visitEnd class="token punctuation">( class="token punctuation">) class="token punctuation">; class="token comment">// 方法访问结束
class="token punctuation">}
class="token punctuation">{
class="token comment">// 动态生成方法,公共的可变参的 invoke 方法
mv class="token operator">= cwclass="token punctuation">. class="token function">visitMethod class="token punctuation">( ACC_PUBLIC class="token operator">+ ACC_VARARGSclass="token punctuation">, class="token string">"invoke" class="token punctuation">,
class="token string">"(Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Object;I[Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Object;)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Object;" class="token punctuation">, class="token keyword">null class="token punctuation">, class="token keyword">null class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitCode class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token keyword">if class="token punctuation">( class="token operator">! methodsclass="token punctuation">. class="token function">isEmpty class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">{
mvclass="token punctuation">. class="token function">visitVarInsn class="token punctuation">( ALOADclass="token punctuation">, class="token number">1 class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class NameInternalclass="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitVarInsn class="token punctuation">( ASTOREclass="token punctuation">, class="token number">4 class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitVarInsn class="token punctuation">( ILOADclass="token punctuation">, class="token number">2 class="token punctuation">) class="token punctuation">;
class="token class -name">Label class="token punctuation">[ class="token punctuation">] labels class="token operator">= class="token keyword">new class="token class -name">Label class="token punctuation">[ nclass="token punctuation">] class="token punctuation">;
class="token keyword">for class="token punctuation">( class="token keyword">int i class="token operator">= class="token number">0 class="token punctuation">; i class="token operator">< nclass="token punctuation">; iclass="token operator">++ class="token punctuation">)
labelsclass="token punctuation">[ iclass="token punctuation">] class="token operator">= class="token keyword">new class="token class -name">Label class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token class -name">Label defaultLabel class="token operator">= class="token keyword">new class="token class -name">Label class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token comment">// label 代表的是跳转的字节码位置,对应一条指令
mvclass="token punctuation">. class="token function">visitTableSwitchInsn class="token punctuation">( class="token number">0 class="token punctuation">, labelsclass="token punctuation">. length class="token operator">- class="token number">1 class="token punctuation">, defaultLabelclass="token punctuation">, labelsclass="token punctuation">) class="token punctuation">;
class="token class -name">StringBuilder buffer class="token operator">= class="token keyword">new class="token class -name">StringBuilder class="token punctuation">( class="token number">128 class="token punctuation">) class="token punctuation">;
class="token keyword">for class="token punctuation">( class="token keyword">int i class="token operator">= class="token number">0 class="token punctuation">; i class="token operator">< nclass="token punctuation">; iclass="token operator">++ class="token punctuation">) class="token punctuation">{ class="token comment">// n = methods.size();
class="token comment">// 跳转到指定字节码位置
mvclass="token punctuation">. class="token function">visitLabel class="token punctuation">( labelsclass="token punctuation">[ iclass="token punctuation">] class="token punctuation">) class="token punctuation">;
class="token keyword">if class="token punctuation">( i class="token operator">== class="token number">0 class="token punctuation">)
mvclass="token punctuation">. class="token function">visitFrame class="token punctuation">( class="token class -name">Opcodes class="token punctuation">. F_APPENDclass="token punctuation">, class="token number">1 class="token punctuation">, class="token keyword">new class="token class -name">Object class="token punctuation">[ class="token punctuation">] class="token punctuation">{ class NameInternalclass="token punctuation">} class="token punctuation">, class="token number">0 class="token punctuation">, class="token keyword">null class="token punctuation">) class="token punctuation">;
class="token keyword">else
mvclass="token punctuation">. class="token function">visitFrame class="token punctuation">( class="token class -name">Opcodes class="token punctuation">. F_SAMEclass="token punctuation">, class="token number">0 class="token punctuation">, class="token keyword">null class="token punctuation">, class="token number">0 class="token punctuation">, class="token keyword">null class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitVarInsn class="token punctuation">( ALOADclass="token punctuation">, class="token number">4 class="token punctuation">) class="token punctuation">;
bufferclass="token punctuation">. class="token function">setLength class="token punctuation">( class="token number">0 class="token punctuation">) class="token punctuation">;
bufferclass="token punctuation">. class="token function">append class="token punctuation">( class="token string">'(' class="token punctuation">) class="token punctuation">;
class="token class -name">Class class="token punctuation">[ class="token punctuation">] paramTypes class="token operator">= parameterTypesclass="token punctuation">[ iclass="token punctuation">] class="token punctuation">;
class="token class -name">Class returnType class="token operator">= returnTypesclass="token punctuation">[ iclass="token punctuation">] class="token punctuation">;
class="token keyword">for class="token punctuation">( class="token keyword">int paramIndex class="token operator">= class="token number">0 class="token punctuation">; paramIndex class="token operator">< paramTypesclass="token punctuation">. lengthclass="token punctuation">; paramIndexclass="token operator">++ class="token punctuation">) class="token punctuation">{
mvclass="token punctuation">. class="token function">visitVarInsn class="token punctuation">( ALOADclass="token punctuation">, class="token number">3 class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitIntInsn class="token punctuation">( BIPUSHclass="token punctuation">, paramIndexclass="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitInsn class="token punctuation">( AALOADclass="token punctuation">) class="token punctuation">;
class="token comment">// 获取到参数类型
class="token class -name">Type paramType class="token operator">= class="token class -name">Type class="token punctuation">. class="token function">getType class="token punctuation">( paramTypesclass="token punctuation">[ paramIndexclass="token punctuation">] class="token punctuation">) class="token punctuation">;
class="token comment">// 根据参数类型的 sort 使用 switch 判断是否为基本数据类型,避免基本数据类型的自动装箱操作,避免创建不必要的对象
class="token keyword">switch class="token punctuation">( paramTypeclass="token punctuation">. class="token function">getSort class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">{
class="token keyword">case class="token class -name">Type class="token punctuation">. BOOLEANclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Boolean" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Boolean" class="token punctuation">, class="token string">"booleanValue" class="token punctuation">, class="token string">"()Z" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. BYTEclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Byte" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Byte" class="token punctuation">, class="token string">"byteValue" class="token punctuation">, class="token string">"()B" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. CHARclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Character" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Character" class="token punctuation">, class="token string">"charValue" class="token punctuation">, class="token string">"()C" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. SHORTclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Short" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Short" class="token punctuation">, class="token string">"shortValue" class="token punctuation">, class="token string">"()S" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. INTclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Integer" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Integer" class="token punctuation">, class="token string">"intValue" class="token punctuation">, class="token string">"()I" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. FLOATclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Float" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Float" class="token punctuation">, class="token string">"floatValue" class="token punctuation">, class="token string">"()F" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. LONGclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Long" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Long" class="token punctuation">, class="token string">"longValue" class="token punctuation">, class="token string">"()J" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. DOUBLEclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Double" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Double" class="token punctuation">, class="token string">"doubleValue" class="token punctuation">, class="token string">"()D" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. ARRAYclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, paramTypeclass="token punctuation">. class="token function">getDescriptor class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. OBJECTclass="token operator">:
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( CHECKCASTclass="token punctuation">, paramTypeclass="token punctuation">. class="token function">getInternalName class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token punctuation">}
class="token comment">// 拼接参数类型描述
bufferclass="token punctuation">. class="token function">append class="token punctuation">( paramTypeclass="token punctuation">. class="token function">getDescriptor class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
class="token punctuation">}
bufferclass="token punctuation">. class="token function">append class="token punctuation">( class="token string">')' class="token punctuation">) class="token punctuation">;
class="token comment">// 拼接返回参数类型描述
bufferclass="token punctuation">. class="token function">append class="token punctuation">( class="token class -name">Type class="token punctuation">. class="token function">getDescriptor class="token punctuation">( returnTypeclass="token punctuation">) class="token punctuation">) class="token punctuation">;
class="token keyword">int invokeclass="token punctuation">;
class="token keyword">if class="token punctuation">( isInterfaceclass="token punctuation">)
invoke class="token operator">= INVOKEINTERFACEclass="token punctuation">; class="token comment">// 调用接口方法
class="token keyword">else class="token keyword">if class="token punctuation">( class="token class -name">Modifier class="token punctuation">. class="token function">isStatic class="token punctuation">( methodsclass="token punctuation">. class="token function">get class="token punctuation">( iclass="token punctuation">) class="token punctuation">. class="token function">getModifiers class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">)
class="token comment">// 调用静态方法
invoke class="token operator">= INVOKESTATICclass="token punctuation">;
class="token keyword">else
class="token comment">// 调用普通方法
invoke class="token operator">= INVOKEVIRTUALclass="token punctuation">;
class="token comment">// 对字节码进行注入
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( invokeclass="token punctuation">, class NameInternalclass="token punctuation">, methodNamesclass="token punctuation">[ iclass="token punctuation">] class="token punctuation">, bufferclass="token punctuation">. class="token function">toString class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
class="token comment">// 判断返回值与参数同操作
class="token keyword">switch class="token punctuation">( class="token class -name">Type class="token punctuation">. class="token function">getType class="token punctuation">( returnTypeclass="token punctuation">) class="token punctuation">. class="token function">getSort class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">{
class="token keyword">case class="token class -name">Type class="token punctuation">. VOIDclass="token operator">:
mvclass="token punctuation">. class="token function">visitInsn class="token punctuation">( ACONST_NULLclass="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. BOOLEANclass="token operator">:
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESTATICclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Boolean" class="token punctuation">, class="token string">"valueOf" class="token punctuation">, class="token string">"(Z)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Boolean;" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. BYTEclass="token operator">:
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESTATICclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Byte" class="token punctuation">, class="token string">"valueOf" class="token punctuation">, class="token string">"(B)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Byte;" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. CHARclass="token operator">:
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESTATICclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Character" class="token punctuation">, class="token string">"valueOf" class="token punctuation">, class="token string">"(C)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Character;" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. SHORTclass="token operator">:
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESTATICclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Short" class="token punctuation">, class="token string">"valueOf" class="token punctuation">, class="token string">"(S)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Short;" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. INTclass="token operator">:
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESTATICclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Integer" class="token punctuation">, class="token string">"valueOf" class="token punctuation">, class="token string">"(I)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Integer;" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. FLOATclass="token operator">:
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESTATICclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Float" class="token punctuation">, class="token string">"valueOf" class="token punctuation">, class="token string">"(F)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Float;" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. LONGclass="token operator">:
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESTATICclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Long" class="token punctuation">, class="token string">"valueOf" class="token punctuation">, class="token string">"(J)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Long;" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token keyword">case class="token class -name">Type class="token punctuation">. DOUBLEclass="token operator">:
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESTATICclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/Double" class="token punctuation">, class="token string">"valueOf" class="token punctuation">, class="token string">"(D)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/Double;" class="token punctuation">) class="token punctuation">;
class="token keyword">break class="token punctuation">;
class="token punctuation">}
mvclass="token punctuation">. class="token function">visitInsn class="token punctuation">( ARETURNclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
mvclass="token punctuation">. class="token function">visitLabel class="token punctuation">( defaultLabelclass="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitFrame class="token punctuation">( class="token class -name">Opcodes class="token punctuation">. F_SAMEclass="token punctuation">, class="token number">0 class="token punctuation">, class="token keyword">null class="token punctuation">, class="token number">0 class="token punctuation">, class="token keyword">null class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token comment">// 下面是一些新建和调用的操作
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( NEWclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/IllegalArgumentException" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitInsn class="token punctuation">( DUPclass="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitTypeInsn class="token punctuation">( NEWclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/StringBuilder" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitInsn class="token punctuation">( DUPclass="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitLdcInsn class="token punctuation">( class="token string">"Method not found: " class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESPECIALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/StringBuilder" class="token punctuation">, class="token string">"<init>" class="token punctuation">, class="token string">"(Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/String;)V" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitVarInsn class="token punctuation">( ILOADclass="token punctuation">, class="token number">2 class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/StringBuilder" class="token punctuation">, class="token string">"append" class="token punctuation">, class="token string">"(I)Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/StringBuilder;" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKEVIRTUALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/StringBuilder" class="token punctuation">, class="token string">"toString" class="token punctuation">, class="token string">"()Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/String;" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMethodInsn class="token punctuation">( INVOKESPECIALclass="token punctuation">, class="token string">"class ="tags" href="/tags/JAVA.html" title=java>java/lang/IllegalArgumentException" class="token punctuation">, class="token string">"<init>" class="token punctuation">, class="token string">"(Lclass ="tags" href="/tags/JAVA.html" title=java>java/lang/String;)V" class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitInsn class="token punctuation">( ATHROWclass="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitMaxs class="token punctuation">( class="token number">0 class="token punctuation">, class="token number">0 class="token punctuation">) class="token punctuation">;
mvclass="token punctuation">. class="token function">visitEnd class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token comment">// method 没有其它调用了,结束创建过程
cwclass="token punctuation">. class="token function">visitEnd class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token comment">// 字节码生成,使用 ClassWriter 的 toByteArray() 方法,返回我们需要的代表这个类的 byte 数组
class="token keyword">byte class="token punctuation">[ class="token punctuation">] data class="token operator">= cwclass="token punctuation">. class="token function">toByteArray class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token comment">// 我们将这个 class 文件进行加载
accessClass class="token operator">= loaderclass="token punctuation">. class="token function">defineClass class="token punctuation">( accessClassNameclass="token punctuation">, dataclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
class="token keyword">try class="token punctuation">{
class="token comment">// 实例化并赋值返回结果
class="token class -name">MethodAccess access class="token operator">= class="token punctuation">( class="token class -name">MethodAccess class="token punctuation">) accessClassclass="token punctuation">. class="token function">newInstance class="token punctuation">( class="token punctuation">) class="token punctuation">;
accessclass="token punctuation">. methodNames class="token operator">= methodNamesclass="token punctuation">;
accessclass="token punctuation">. parameterTypes class="token operator">= parameterTypesclass="token punctuation">;
accessclass="token punctuation">. returnTypes class="token operator">= returnTypesclass="token punctuation">;
class="token keyword">return accessclass="token punctuation">;
class="token punctuation">} class="token keyword">catch class="token punctuation">( class="token class -name">Throwable tclass="token punctuation">) class="token punctuation">{
class="token keyword">throw class="token keyword">new class="token class -name">RuntimeException class="token punctuation">( class="token string">"Error constructing method access class : " class="token operator">+ accessClassNameclass="token punctuation">, tclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
class="token comment">// 使用class ="tags" href="/tags/FanShe.html" title=反射>反射获取到要class ="tags" href="/tags/FanShe.html" title=反射>反射类的公有非静态方法后赋值给私有变量进行存储
class="token keyword">private class="token keyword">static class="token keyword">void addDeclaredMethodsToList class="token punctuation">( class="token class -name">Class typeclass="token punctuation">, class="token class -name">ArrayList class="token generics">class="token punctuation">< class="token class -name">Method class="token punctuation">> methodsclass="token punctuation">) class="token punctuation">{
class="token class -name">Method class="token punctuation">[ class="token punctuation">] declaredMethods class="token operator">= typeclass="token punctuation">. class="token function">getDeclaredMethods class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token keyword">for class="token punctuation">( class="token keyword">int i class="token operator">= class="token number">0 class="token punctuation">, n class="token operator">= declaredMethodsclass="token punctuation">. lengthclass="token punctuation">; i class="token operator">< nclass="token punctuation">; iclass="token operator">++ class="token punctuation">) class="token punctuation">{
class="token class -name">Method method class="token operator">= declaredMethodsclass="token punctuation">[ iclass="token punctuation">] class="token punctuation">;
class="token keyword">int modifiers class="token operator">= methodclass="token punctuation">. class="token function">getModifiers class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token comment">// 判断是否为私有方法
class="token keyword">if class="token punctuation">( class="token class -name">Modifier class="token punctuation">. class="token function">isPrivate class="token punctuation">( modifiersclass="token punctuation">) class="token punctuation">) class="token keyword">continue class="token punctuation">;
methodsclass="token punctuation">. class="token function">add class="token punctuation">( methodclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
class="token keyword">private class="token keyword">static class="token keyword">void recursiveAddInterfaceMethodsToList class="token punctuation">( class="token class -name">Class interfaceTypeclass="token punctuation">, class="token class -name">ArrayList class="token generics">class="token punctuation">< class="token class -name">Method class="token punctuation">> methodsclass="token punctuation">) class="token punctuation">{
class="token function">addDeclaredMethodsToList class="token punctuation">( interfaceTypeclass="token punctuation">, methodsclass="token punctuation">) class="token punctuation">;
class="token keyword">for class="token punctuation">( class="token class -name">Class nextInterface class="token operator">: interfaceTypeclass="token punctuation">. class="token function">getInterfaces class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">{
class="token function">recursiveAddInterfaceMethodsToList class="token punctuation">( nextInterfaceclass="token punctuation">, methodsclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
class="token punctuation">}
4.2 读源码后 了解到 MethodAccess 执行流程
通过 Java class ="tags" href="/tags/FanShe.html" title=反射>反射获取 class 的公共非静态函数名、属性等 在私有变量内记录方法名称参数等信息 用 ASM 技术动态生成新的继承于 MethodAccess 的类(fileName + MethodAccess) 在类的 invoke 方法实现调用不同的方法
4.3 小结
class ="tags" href="/tags/FanShe.html" title=反射>反射的核心是 getMethod 和 invoke,reflectASM 要生成文件然后加载到 JVM,所以 reflectASM 的 get 特别慢,
使用 jar 包要注意缓存生成的 class 对象,尽量少重复生成
reflectASM 借助class ="tags" href="/tags/FanShe.html" title=反射>反射的 getDeclaredMethods 获取 class 的所有方法,然后动态生成一个继承于 MethodAccess 的子类 ,动态生成一个 class 文件并加载到 jvm 中。这个操作比较耗时,我们最好预先生成这个 MethodAccess 对象,将这个生成的对象缓存起来
子类中所有的方法名建立 index 索引,index 和方法名映射,根据方法名获取到 index,子类中的 switch 执行相应的代码,在 MethodAccess.invoke 的时候,是直接调用
如果class ="tags" href="/tags/FanShe.html" title=反射>反射调用的类函数比较多,这个遍历也可能耗时较多,可以先通过 getIndex 方法先获取到索引,然后再进行调用,这样比使用函数的名字来进行调用快的多