反射的实现原理

  • 反射的demo

    package com.java.reflect;
    import java.lang.reflect.Method;
    /**
     * 反射调用的例子
     * @author helenlee
     * @date 2018/9/4
     */
    public class ReflectionDemo {
        public static void main(String[] args) throws Exception {
            Class<?> clzss = Class.forName("com.java.reflect.ReflectionDemo");
            // target方法是访问权限是public,
            // 如果是private则需要通过clzss.getDeclaredMethod()获取
            Method target = clzss.getMethod("target", int.class);
            target.invoke(null, 128);
        }
    
        public static void target(int i) {
            System.out.println("invoke target method");
        }
    }
    ###输出
    $ javac com/java/reflect/ReflectionDemo.java 
    $ java com/java/reflect/ReflectionDemo
    invoke target method
    
  • 反射的方法的执行链路

    为了看到反射调用链路我们以构造异常的方式打印堆栈信息:

    package com.java.reflect;
    import java.lang.reflect.Method;
    /**
     * 反射调用的例子
     * @author helenlee
     * @date 2018/9/4
     */
    public class ReflectionDemo {
        public static void main(String[] args) throws Exception {
            Class<?> clzss = Class.forName("com.java.reflect.ReflectionDemo");
            // target方法是访问权限是public,
            // 如果是private则需要通过clzss.getDeclaredMethod()获取
            Method target = clzss.getMethod("target", int.class);
            target.invoke(null, 128);
        }
    
        public static void target(int i) {
          //输出堆栈信息
            new Exception("#" + i).printStackTrace();
            System.out.println("invoke target method");
        }
    }
    ----------------输出---------------
    $ javac com/java/reflect/ReflectionDemo.java 
    $ java com/java/reflect/ReflectionDemo
    java.lang.Exception: #128
            at com.java.reflect.ReflectionDemo.target(ReflectionDemo.java:18)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at com.java.reflect.ReflectionDemo.main(ReflectionDemo.java:14)
    invoke target method
    

    源码分析-调用链路时序图

    反射调用链路时序图.png

    源码分析-调用链代码

    step 1:调用代码

    package com.java.reflect;
    import java.lang.reflect.Method;
    /**
     * 反射调用的例子
     * @author helenlee
     * @date 2018/9/4
     */
    public class ReflectionDemo {
        public static void main(String[] args) throws Exception {
            Class<?> clzss = Class.forName("com.java.reflect.ReflectionDemo");
            // target方法是访问权限是public,
            // 如果是private则需要通过clzss.getDeclaredMethod()获取
            Method target = clzss.getMethod("target", int.class);
            // step 2:Method执行链路
            target.invoke(null, 128);
        }
        public static void target(int i) {
            new Exception("#" + i).printStackTrace();
            System.out.println("invoke target method");
        }
        public String targetString(int i,String name){
            new Exception("#" + i).printStackTrace();
            System.out.println("invoke target method");
            return name;
        }
    }
    

    step 2:Method执行链路

    package java.lang.reflect;
    import sun.reflect.CallerSensitive;
    import sun.reflect.MethodAccessor;
    import sun.reflect.Reflection;
    import sun.reflect.generics.repository.MethodRepository;
    import sun.reflect.generics.factory.CoreReflectionFactory;
    import sun.reflect.generics.factory.GenericsFactory;
    import sun.reflect.generics.scope.MethodScope;
    import sun.reflect.annotation.AnnotationType;
    import sun.reflect.annotation.AnnotationParser;
    import java.lang.annotation.Annotation;
    import java.lang.annotation.AnnotationFormatError;
    import java.nio.ByteBuffer;
    
    public final class Method extends Executable {
        private Class<?>            clazz;
        private int                 modifiers;
        private volatile MethodAccessor methodAccessor;
        private Method              root;
    
        @CallerSensitive
        public Object invoke(Object obj, Object... args)
                throws IllegalAccessException, IllegalArgumentException,
                InvocationTargetException {
            // 1.权限检查
            if (!override) {
                if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                    Class<?> caller = Reflection.getCallerClass();
                    checkAccess(caller, clazz, obj, modifiers);
                }
            }
            // 2.获取委派的对象
            MethodAccessor ma = methodAccessor;
            if (ma == null) {
                // step 3:获取委派对象
                ma = acquireMethodAccessor();
            }
            // 3.委派或者动态实现方式执行调用,最终会调用到目标方法
            // step 4:委派或者动态实现方式执行调用
            return ma.invoke(obj, args);
        }
    }
    
    

    step 3:获取委派对象

    private MethodAccessor acquireMethodAccessor() {
            MethodAccessor tmp = null;
            // 如果缓存中有则直接返回
            if (root != null) tmp = root.getMethodAccessor();
            if (tmp != null) {
                methodAccessor = tmp;
            } else {
                // 如果不存在则创建
                // step 3.1:创建MethodAccessor
                tmp = reflectionFactory.newMethodAccessor(this);
                setMethodAccessor(tmp);
            }
            return tmp;
        }
    

    step 3.1:创建MethodAccessor

    public MethodAccessor newMethodAccessor(Method method) {
            checkInitted();
    
            //如果不使用膨胀模式-Dsun.reflect.noInflation=true
            if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
                //通过ASM动态生成
                return new MethodAccessorGenerator().
                    generateMethod(method.getDeclaringClass(),
                                   method.getName(),
                                   method.getParameterTypes(),
                                   method.getReturnType(),
                                   method.getExceptionTypes(),
                                   method.getModifiers());
            } else {
                // 委派模式,最终还是有NativeMethodAccessorImpl调用Native方法完成
                NativeMethodAccessorImpl acc =
                    new NativeMethodAccessorImpl(method);
                DelegatingMethodAccessorImpl res =
                    new DelegatingMethodAccessorImpl(acc);
                acc.setParent(res);
                return res;
            }
        }
    

    step 4:委派模式

    class DelegatingMethodAccessorImpl extends MethodAccessorImpl {
        private MethodAccessorImpl delegate;
    
        DelegatingMethodAccessorImpl(MethodAccessorImpl delegate) {
            setDelegate(delegate);
        }
    
        public Object invoke(Object obj, Object[] args)
            throws IllegalArgumentException, InvocationTargetException
        {
            // delegate是一个NativeMethodAccessorImpl对象
            return delegate.invoke(obj, args);
        }
    
        void setDelegate(MethodAccessorImpl delegate) {
            this.delegate = delegate;
        }
    }
    class NativeMethodAccessorImpl extends MethodAccessorImpl {
        private final Method method;
        private DelegatingMethodAccessorImpl parent;
        private int numInvocations;
    
        NativeMethodAccessorImpl(Method method) {
            this.method = method;
        }
    
        public Object invoke(Object obj, Object[] args)
            throws IllegalArgumentException, InvocationTargetException
        {
            // 如果执行次数超过了ReflectionFactory.inflationThreshold()则使用动态实现方式
            if (++numInvocations > ReflectionFactory.inflationThreshold()
                    && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
                MethodAccessorImpl acc = (MethodAccessorImpl)
                    new MethodAccessorGenerator().
                        generateMethod(method.getDeclaringClass(),
                                       method.getName(),
                                       method.getParameterTypes(),
                                       method.getReturnType(),
                                       method.getExceptionTypes(),
                                       method.getModifiers());
                parent.setDelegate(acc);
            }
            // 委派模式最终执行的是native方法(整个过程Java->C->Java)
            return invoke0(method, obj, args);
        }
    
        void setParent(DelegatingMethodAccessorImpl parent) {
            this.parent = parent;
        }
    
        private static native Object invoke0(Method m, Object obj, Object[] args);
    }
    

    step 4:动态模式(静态方法)

    package com.java.reflect;
    
    import sun.reflect.MethodAccessorImpl;
    
    import java.lang.reflect.InvocationTargetException;
    
    /**
     * 动态实现方式:
     * 由ASM字节码生成被调用方法的MethodAccessor类(相当于加了中间层,由中间层直接调用目标方法)
     *
     */
    public class GeneratedMethodAccessor1 extends MethodAccessorImpl {
        public GeneratedMethodAccessor1() {
        }
    
        public Object invoke(Object var1, Object[] var2) throws InvocationTargetException {
            int var10000;
            try {
                //目标方法只有一个参数
                if (var2.length != 1) {
                    throw new IllegalArgumentException();
                }
    
                Object var3 = var2[0];
                if (var3 instanceof Byte) {
                    var10000 = (Byte)var3;
                } else if (var3 instanceof Character) {
                    var10000 = (Character)var3;
                } else if (var3 instanceof Short) {
                    var10000 = (Short)var3;
                } else {
                    if (!(var3 instanceof Integer)) {
                        throw new IllegalArgumentException();
                    }
    
                    var10000 = (Integer)var3;
                }
            } catch (NullPointerException | ClassCastException var5) {
                throw new IllegalArgumentException(var5.toString());
            }
    
            try {
                //目标方法是静态方法(如果是实例方法则需要传入的实例对象发起调用)
                ReflectionDemo.target(var10000);
                return null;
            } catch (Throwable var4) {
                throw new InvocationTargetException(var4);
            }
        }
    }
    
    

    step 4:动态模式(实例方法)

    package sun.reflect;
    
    import com.java.reflect.ReflectionDemo;
    import java.lang.reflect.InvocationTargetException;
    
    /**
     * 实例方法生成动态MethodAccessor类
     * 如:public String targetString(int i,String name);
     */
    public class GeneratedMethodAccessor1 extends MethodAccessorImpl {
        public GeneratedMethodAccessor1() {
        }
    
        public Object invoke(Object var1, Object[] var2) throws InvocationTargetException {
            // 传入的实例对象不能为空
            if (var1 == null) {
                throw new NullPointerException();
            } else {
                ReflectionDemo var10000;
                int var10001;
                String var10002;
                try {
                    // 强转实例对象
                    var10000 = (ReflectionDemo)var1;
                    // 入参个数校验
                    if (var2.length != 2) {
                        throw new IllegalArgumentException();
                    }
                    // 入参类型转换
                    Object var3 = var2[0];
                    if (var3 instanceof Byte) {
                        var10001 = (Byte)var3;
                    } else if (var3 instanceof Character) {
                        var10001 = (Character)var3;
                    } else if (var3 instanceof Short) {
                        var10001 = (Short)var3;
                    } else {
                        if (!(var3 instanceof Integer)) {
                            throw new IllegalArgumentException();
                        }
                        var10001 = (Integer)var3;
                    }
                    var10002 = (String)var2[1];
                } catch (NullPointerException | ClassCastException var5) {
                    throw new IllegalArgumentException(var5.toString());
                }
    
                try {
                    // 实例对象调用目标方法
                    return var10000.targetString(var10001, var10002);
                } catch (Throwable var4) {
                    throw new InvocationTargetException(var4);
                }
            }
        }
    }
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容