美文网首页
(6)Method的invoke方法解析

(6)Method的invoke方法解析

作者: Mrsunup | 来源:发表于2018-10-06 11:10 被阅读0次

    网上有一遍文章讲解得比较深入也比较详细,地址如下:https://www.cnblogs.com/onlywujun/p/3519037.html

    我这边就简单演示一下,invoke的调用链过程 ,先准备演示类:

    public class A {
        public void foo(String name) {
            System.out.println("Hello, " + name);
        }
    }
    
    
    public class TestClassLoad {
        public static void main(String[] args) throws Exception {
            Class<?> clz = Class.forName(A.class.getName());
            Object o = clz.newInstance();
            Method m = clz.getMethod("foo", String.class);
            for (int i = 0; i < 16; i++) {
                if(i==15){
                    m.invoke(o, Integer.toString(i));
                }else{
                    m.invoke(o, Integer.toString(i));
                }
            }
        }
    }
    

    在控制台加上-XX:+TraceClassLoading的参数 ,运行


    image.png
    [Loaded java.lang.Void from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded com.java.reflect.invoke.A from file:/D:/Eclipse2018Data/personProject/jdk/java-lang-reflect/target/classes/]
    Hello, 0
    Hello, 1
    Hello, 2
    Hello, 3
    Hello, 4
    Hello, 5
    Hello, 6
    Hello, 7
    Hello, 8
    Hello, 9
    Hello, 10
    Hello, 11
    Hello, 12
    Hello, 13
    Hello, 14
    [Loaded sun.reflect.ClassFileConstants from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.AccessorGenerator from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.MethodAccessorGenerator from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.ByteVectorFactory from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.ByteVector from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.ByteVectorImpl from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.ClassFileAssembler from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.UTF8 from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.Label from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.Label$PatchInfo from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.MethodAccessorGenerator$1 from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.ClassDefiner from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.ClassDefiner$1 from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded sun.reflect.GeneratedMethodAccessor1 from __JVM_DefineClass__]
    Hello, 15
    [Loaded java.lang.Shutdown from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    [Loaded java.lang.Shutdown$Lock from C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar]
    

    主要看Loaded sun.reflect.GeneratedMethodAccessor1 这一句,表示在invoke调用15次之后用了jdk自带的方法生成器来进行调用

    invoke 调用是由MethodAccessor来进行调用的,而具体的NativeMethodAccessorImpl和DelegatingMethodAccessorImpl是由ReflectionFactory创建而来的,DelegatingMethodAccessorImpl这里是一个委托,会把调用链关系转换为NativeMethodAccessorImpl的invoke方法进行调用

        public MethodAccessor newMethodAccessor(Method var1) {
            checkInitted();
            if (noInflation && !ReflectUtil.isVMAnonymousClass(var1.getDeclaringClass())) {
                return (new MethodAccessorGenerator()).generateMethod(var1.getDeclaringClass(), var1.getName(), var1.getParameterTypes(), var1.getReturnType(), var1.getExceptionTypes(), var1.getModifiers());
            } else {
                NativeMethodAccessorImpl var2 = new NativeMethodAccessorImpl(var1);
                DelegatingMethodAccessorImpl var3 = new DelegatingMethodAccessorImpl(var2);
                var2.setParent(var3);
                return var3;
            }
        }
    

    而NativeMethodAccessorImpl的invoke方法如下,默认调用的是本地的invoke0方法,但是会有一个调用次数的判断,如果调用次数大于15,则由MethodAccessorGenerator生成方法的MethodAccessorImpl的实现,然后改变DelegatingMethodAccessorImpl的委托类设置为jdk生成方法访问器,则调用次数大于15的时候是由jdk的生成方法访问器进行方法调用的

        public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
            if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
                MethodAccessorImpl var3 = (MethodAccessorImpl)(new MethodAccessorGenerator()).generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());
                this.parent.setDelegate(var3);
            }
    
            return invoke0(this.method, var1, var2);
        }
      private static native Object invoke0(Method var0, Object var1, Object[] var2);
    

    相关文章

      网友评论

          本文标题:(6)Method的invoke方法解析

          本文链接:https://www.haomeiwen.com/subject/dcacaftx.html