Java基础:JDK动态代理源码分析

来源:互联网 发布:地下室防水算法 编辑:程序博客网 时间:2024/06/05 08:46

前言

在《设计模式之:代理模式》一文中介绍了代理的设计架构,其中提到了代理模式的两种分类:普通代理和动态代理。动态代理的实现流程:创建一个被代理对象、创建一个基础InvocationHandler的接口类对象、创建一个代理对象。这一个过程是如何实现的?接下来这一节介绍动态代理在源码层面上实现原理。

正题

在使用动态代理过程中,都是通过Proxy##ProxyInstance来实例化一个代理对象。

Proxy##newProxyInstance

    public static Object newProxyInstance(ClassLoader loader,                                          Class<?>[] interfaces,                                          InvocationHandler h)        throws IllegalArgumentException    {        Objects.requireNonNull(h);        final Class<?>[] intfs = interfaces.clone();        final SecurityManager sm = System.getSecurityManager();        if (sm != null) {            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);        }        /*         * Look up or generate the designated proxy class.//查找或生成代理         */        Class<?> cl = getProxyClass0(loader, intfs);        /*         * Invoke its constructor with the designated invocation handler.         */        try {            if (sm != null) {                checkNewProxyPermission(Reflection.getCallerClass(), cl);            }            //获取构造器            final Constructor<?> cons = cl.getConstructor(constructorParams);            final InvocationHandler ih = h;            if (!Modifier.isPublic(cl.getModifiers())) {                AccessController.doPrivileged(new PrivilegedAction<Void>() {                    public Void run() {                        cons.setAccessible(true);                        return null;                    }                });            }          //返回代理实例         return cons.newInstance(new Object[]{h});        } catch (IllegalAccessException|InstantiationException e) {            throw new InternalError(e.toString(), e);        } catch (InvocationTargetException e) {            Throwable t = e.getCause();            if (t instanceof RuntimeException) {                throw (RuntimeException) t;            } else {                throw new InternalError(t.toString(), t);            }        } catch (NoSuchMethodException e) {            throw new InternalError(e.toString(), e);        }    }
其实最主要的是生成Class代理对象,接下来看看是如何生成的。

Proxy##getProxy0Class

    /**     * Generate a proxy class.  Must call the checkProxyAccess method     * to perform permission checks before calling this.     */    private static Class<?> getProxyClass0(ClassLoader loader,                                           Class<?>... interfaces) {        if (interfaces.length > 65535) {            throw new IllegalArgumentException("interface limit exceeded");        }        // If the proxy class defined by the given loader implementing        // the given interfaces exists, this will simply return the cached copy;        // otherwise, it will create the proxy class via the ProxyClassFactory        return proxyClassCache.get(loader, interfaces);    }
JVM内部使用缓存来保存已创建的Class代理实例。
    /**     * a cache of proxy classes     */    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
在Proxy内部有一个WeakCache类型的类变量来保存已经创建的代理Class对象。

注意创建WeakCache实例时会创建一个ProxyClassFactory实例

WeakCache##get

    public V get(K key, P parameter) {        Objects.requireNonNull(parameter);        expungeStaleEntries();        Object cacheKey = CacheKey.valueOf(key, refQueue);        // lazily install the 2nd level valuesMap for the particular cacheKey        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);        if (valuesMap == null) {            ConcurrentMap<Object, Supplier<V>> oldValuesMap                = map.putIfAbsent(cacheKey,                                  valuesMap = new ConcurrentHashMap<>());            if (oldValuesMap != null) {                valuesMap = oldValuesMap;            }        }        // create subKey and retrieve the possible Supplier<V> stored by that        // subKey from valuesMap        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));        Supplier<V> supplier = valuesMap.get(subKey);        Factory factory = null;        while (true) {            if (supplier != null) {                // supplier might be a Factory or a CacheValue<V> instance                V value = supplier.get();                if (value != null) {                    return value;                }            }            // else no supplier in cache            // or a supplier that returned null (could be a cleared CacheValue            // or a Factory that wasn't successful in installing the CacheValue)            // lazily construct a Factory            if (factory == null) {                factory = new Factory(key, parameter, subKey, valuesMap);            }            if (supplier == null) {                supplier = valuesMap.putIfAbsent(subKey, factory);                if (supplier == null) {                    // successfully installed Factory                    supplier = factory;                }                // else retry with winning supplier            } else {                if (valuesMap.replace(subKey, supplier, factory)) {                    // successfully replaced                    // cleared CacheEntry / unsuccessful Factory                    // with our Factory                    supplier = factory;                } else {                    // retry with current supplier                    supplier = valuesMap.get(subKey);                }            }        }    }
从上面代码可知:已存在内存中的Class代理对象都保存到ConcurrentMap容器中,所以这一步会先在容器里查找对应的Class代理对象,如果不存在就new 一个Factory对象,如果存在则会调用Factory##get方法返回一个代理对象。

Factory##get

public synchronized V get() { // serialize access            // re-check            Supplier<V> supplier = valuesMap.get(subKey);            if (supplier != this) {                // something changed while we were waiting:                // might be that we were replaced by a CacheValue                // or were removed because of failure ->                // return null to signal WeakCache.get() to retry                // the loop                return null;            }            // else still us (supplier == this)            // create new value            V value = null;            try {                value = Objects.requireNonNull(valueFactory.apply(key, parameter));            } finally {                if (value == null) { // remove us on failure                    valuesMap.remove(subKey, this);                }            }            // the only path to reach here is with non-null value            assert value != null;            // wrap value with CacheValue (WeakReference)            CacheValue<V> cacheValue = new CacheValue<>(value);            // try replacing us with CacheValue (this should always succeed)            if (valuesMap.replace(subKey, this, cacheValue)) {                // put also in reverseMap                reverseMap.put(cacheValue, Boolean.TRUE);            } else {                throw new AssertionError("Should not reach here");            }            // successfully replaced us with new CacheValue -> return the value            // wrapped by it            return value;        }    }
初始化WeakCache对象时会创建一个ProxyClassFactory实例,所以会调用ProxyClassFactory##apply获取Class代理对象。

ProxyClassFactory##apply

        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);            for (Class<?> intf : interfaces) {                /*                 * Verify that the class loader resolves the name of this                 * interface to the same Class object.                 */                Class<?> interfaceClass = null;                try {                    interfaceClass = Class.forName(intf.getName(), false, loader);                } catch (ClassNotFoundException e) {                }                if (interfaceClass != intf) {                    throw new IllegalArgumentException(                        intf + " is not visible from class loader");                }                /*                 * Verify that the Class object actually represents an                 * interface.                 */                if (!interfaceClass.isInterface()) {                    throw new IllegalArgumentException(                        interfaceClass.getName() + " is not an interface");                }                /*                 * Verify that this interface is not a duplicate.                 */                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {                    throw new IllegalArgumentException(                        "repeated interface: " + interfaceClass.getName());                }            }            String proxyPkg = null;     // package to define proxy class in            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;            /*             * Record the package of a non-public proxy interface so that the             * proxy class will be defined in the same package.  Verify that             * all non-public proxy interfaces are in the same package.             */            for (Class<?> intf : interfaces) {                int flags = intf.getModifiers();                if (!Modifier.isPublic(flags)) {                    accessFlags = Modifier.FINAL;                    String name = intf.getName();                    int n = name.lastIndexOf('.');                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));                    if (proxyPkg == null) {                        proxyPkg = pkg;                    } else if (!pkg.equals(proxyPkg)) {                        throw new IllegalArgumentException(                            "non-public interfaces from different packages");                    }                }            }            if (proxyPkg == null) {                // if no non-public proxy interfaces, use com.sun.proxy package                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";            }            /*             * Choose a name for the proxy class to generate.             */            long num = nextUniqueNumber.getAndIncrement();            String proxyName = proxyPkg + proxyClassNamePrefix + num;            /*             * Generate the specified proxy class.             */            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(                proxyName, interfaces, accessFlags);            try {                return defineClass0(loader, proxyName,                                    proxyClassFile, 0, proxyClassFile.length);            } catch (ClassFormatError e) {                /*                 * A ClassFormatError here means that (barring bugs in the                 * proxy class generation code) there was some other                 * invalid aspect of the arguments supplied to the proxy                 * class creation (such as virtual machine limitations                 * exceeded).                 */                throw new IllegalArgumentException(e.toString());            }        }    }
最终会调用ProxyGennerator类来生成Class代理类的二进制字节数组。

ProxyGennerator##generatorProxyClass

    public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {        ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);        final byte[] var4 = var3.generateClassFile();        if (saveGeneratedFiles) {            AccessController.doPrivileged(new PrivilegedAction<Void>() {                public Void run() {                    try {                        int var1 = var0.lastIndexOf(46);                        Path var2;                        if (var1 > 0) {                            Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));                            Files.createDirectories(var3);                            var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");                        } else {                            var2 = Paths.get(var0 + ".class");                        }                        Files.write(var2, var4, new OpenOption[0]);                        return null;                    } catch (IOException var4x) {                        throw new InternalError("I/O exception saving generated file: " + var4x);                    }                }            });        }        return var4;    }

ProxyGenerator##generateClassFile

    private byte[] generateClassFile() {       /* ============================================================        * Step 1: Assemble ProxyMethod objects for all methods to generate proxy dispatching code for.        * 步骤1:为所有方法生成代理调度代码,将代理方法对象集合起来。        */        //添加hashCode、equals、toString方法        this.addProxyMethod(hashCodeMethod, Object.class);        this.addProxyMethod(equalsMethod, Object.class);        this.addProxyMethod(toStringMethod, Object.class);        Class[] var1 = this.interfaces;        int var2 = var1.length;        int var3;        Class var4;        for(var3 = 0; var3 < var2; ++var3) {            var4 = var1[var3];            Method[] var5 = var4.getMethods();            int var6 = var5.length;            for(int var7 = 0; var7 < var6; ++var7) {                Method var8 = var5[var7];                this.addProxyMethod(var8, var4);            }        }        Iterator var11 = this.proxyMethods.values().iterator();        List var12;        while(var11.hasNext()) {            var12 = (List)var11.next();            checkReturnTypes(var12);        }         /* ============================================================         * Step 2: Assemble FieldInfo and MethodInfo structs for all of fields and methods in the class we are generating.         * 为类中的字段、方法生成对应的字段信息、方法信息         */        Iterator var15;        try {            this.methods.add(this.generateConstructor());            var11 = this.proxyMethods.values().iterator();            while(var11.hasNext()) {                var12 = (List)var11.next();                var15 = var12.iterator();                while(var15.hasNext()) {                    ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();                    this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));                    this.methods.add(var16.generateMethod());                }            }            this.methods.add(this.generateStaticInitializer());        } catch (IOException var10) {            throw new InternalError("unexpected I/O Exception", var10);        }        if (this.methods.size() > 65535) {            throw new IllegalArgumentException("method limit exceeded");        } else if (this.fields.size() > 65535) {            throw new IllegalArgumentException("field limit exceeded");        } else {          /* ============================================================           * Step 3: Write the final class file.           * 步骤3:编写最终类文件           */            this.cp.getClass(dotToSlash(this.className));            this.cp.getClass("java/lang/reflect/Proxy");            var1 = this.interfaces;            var2 = var1.length;            for(var3 = 0; var3 < var2; ++var3) {                var4 = var1[var3];                this.cp.getClass(dotToSlash(var4.getName()));            }            this.cp.setReadOnly();            ByteArrayOutputStream var13 = new ByteArrayOutputStream();            DataOutputStream var14 = new DataOutputStream(var13);            try {                var14.writeInt(-889275714);                var14.writeShort(0);                var14.writeShort(49);                this.cp.write(var14);                var14.writeShort(this.accessFlags);                var14.writeShort(this.cp.getClass(dotToSlash(this.className)));                var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));                var14.writeShort(this.interfaces.length);                Class[] var17 = this.interfaces;                int var18 = var17.length;                for(int var19 = 0; var19 < var18; ++var19) {                    Class var22 = var17[var19];                    var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));                }                var14.writeShort(this.fields.size());                var15 = this.fields.iterator();                while(var15.hasNext()) {                    ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();                    var20.write(var14);                }                var14.writeShort(this.methods.size());                var15 = this.methods.iterator();                while(var15.hasNext()) {                    ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();                    var21.write(var14);                }                var14.writeShort(0);                return var13.toByteArray();            } catch (IOException var9) {                throw new InternalError("unexpected I/O Exception", var9);            }        }    }

使用ProxyGenerator##generatorProxyClassFactory来生成一个class文件

public static void main(String[] args) {        String path = "D://subject.class";        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0",RealSubject.class.getInterfaces());        FileOutputStream out = null;        try {            out = new FileOutputStream(path);            out.write(classFile);            out.flush();        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                out.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }

生成的class文件内容如下:

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//import com.smart.proxy.Subject;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements Subject {    private static Method m1;    private static Method m2;    private static Method m3;    private static Method m0;    public $Proxy0(InvocationHandler var1) throws  {        super(var1);    }    public final boolean equals(Object var1) throws  {        try {            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();        } catch (RuntimeException | Error var3) {            throw var3;        } catch (Throwable var4) {            throw new UndeclaredThrowableException(var4);        }    }    public final String toString() throws  {        try {            return (String)super.h.invoke(this, m2, (Object[])null);        } catch (RuntimeException | Error var2) {            throw var2;        } catch (Throwable var3) {            throw new UndeclaredThrowableException(var3);        }    }    public final void doSomething(String var1) throws  {        try {            super.h.invoke(this, m3, new Object[]{var1});        } catch (RuntimeException | Error var3) {            throw var3;        } catch (Throwable var4) {            throw new UndeclaredThrowableException(var4);        }    }    public final int hashCode() throws  {        try {            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();        } catch (RuntimeException | Error var2) {            throw var2;        } catch (Throwable var3) {            throw new UndeclaredThrowableException(var3);        }    }    static {        try {            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));            m2 = Class.forName("java.lang.Object").getMethod("toString");            m3 = Class.forName("com.smart.proxy.Subject").getMethod("doSomething", Class.forName("java.lang.String"));            m0 = Class.forName("java.lang.Object").getMethod("hashCode");        } catch (NoSuchMethodException var2) {            throw new NoSuchMethodError(var2.getMessage());        } catch (ClassNotFoundException var3) {            throw new NoClassDefFoundError(var3.getMessage());        }    }}
在创建一个代理对象时会传一个InvocationHandler引用,而把该引用保存到Proxy实例的h域中。在$Proxy0文件可以看出doSomething方法通过InvocationHandler##invoke实现的。

类的调用流程图:

创建对象流程:


原创粉丝点击