Proxy源码分析

openstack 源码分析之swift proxy 服务启动 1 test 阅读详情

1.验证InvocationHandler是否空

2.生成代理类的Class对象,这里戏份比较多,代码中详细注释。

(1).通过类加载器去加载得到Class实例,比较是否想通的Class

(2).判断是否是接口

(3).去重Class,并通过String[]保存接口名

(4).从缓存中创建根据类加载器取得Map,如果没有则创建一个,保存到WeakHashMap

(5). put key,value<一堆接口,正在创建代理的标志> into Map

(6).记录包可见的代理接口,for循环中是校验非公有接口是否在同一包下

(7).生成类名,并生成代理类

(8).把代理类放入代理类缓存

(9).获得有一个InvocationHandler对象参数的构造函数,并创建实例.

 

Java还是外层的东东

Java代码 
  1. package com.alipay.home.proxy;  
  2.   
  3. import java.lang.ref.Reference;  
  4. import java.lang.ref.WeakReference;  
  5. import java.lang.reflect.Constructor;  
  6. import java.lang.reflect.InvocationHandler;  
  7. import java.lang.reflect.InvocationTargetException;  
  8. import java.lang.reflect.Modifier;  
  9. import java.util.Arrays;  
  10. import java.util.Collections;  
  11. import java.util.HashMap;  
  12. import java.util.HashSet;  
  13. import java.util.Map;  
  14. import java.util.Set;  
  15. import java.util.WeakHashMap;  
  16. import sun.misc.ProxyGenerator;  
  17.   
  18. /** 
  19.  * <code>Proxy</code> provides static methods for creating dynamic proxy 
  20.  * classes and instances, and it is also the superclass of all 
  21.  * dynamic proxy classes created by those methods. 
  22.  * 
  23.  * <p>To create a proxy for some interface <code>Foo</code>: 
  24.  * <pre> 
  25.  *     InvocationHandler handler = new MyInvocationHandler(...); 
  26.  *     Class proxyClass = Proxy.getProxyClass( 
  27.  *         Foo.class.getClassLoader(), new Class[] { Foo.class }); 
  28.  *     Foo f = (Foo) proxyClass. 
  29.  *         getConstructor(new Class[] { InvocationHandler.class }). 
  30.  *         newInstance(new Object[] { handler }); 
  31.  * </pre> 
  32.  * or more simply: 
  33.  * <pre> 
  34.  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), 
  35.  *                                          new Class[] { Foo.class }, 
  36.  *                                          handler); 
  37.  * </pre> 
  38.  * 
  39.  * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy 
  40.  * class</i> below) is a class that implements a list of interfaces 
  41.  * specified at runtime when the class is created, with behavior as 
  42.  * described below. 
  43.  * 
  44.  * A <i>proxy interface</i> is such an interface that is implemented 
  45.  * by a proxy class. 
  46.  * 
  47.  * A <i>proxy instance</i> is an instance of a proxy class. 
  48.  * 
  49.  * Each proxy instance has an associated <i>invocation handler</i> 
  50.  * object, which implements the interface {@link InvocationHandler}. 
  51.  * A method invocation on a proxy instance through one of its proxy 
  52.  * interfaces will be dispatched to the {@link InvocationHandler#invoke 
  53.  * invoke} method of the instance's invocation handler, passing the proxy 
  54.  * instance, a <code>java.lang.reflect.Method</code> object identifying 
  55.  * the method that was invoked, and an array of type <code>Object</code> 
  56.  * containing the arguments.  The invocation handler processes the 
  57.  * encoded method invocation as appropriate and the result that it 
  58.  * returns will be returned as the result of the method invocation on 
  59.  * the proxy instance. 
  60.  * 
  61.  * <p>A proxy class has the following properties: 
  62.  * 
  63.  * <ul> 
  64.  * <li>Proxy classes are public, final, and not abstract. 
  65.  * 
  66.  * <li>The unqualified name of a proxy class is unspecified.  The space 
  67.  * of class names that begin with the string <code>"$Proxy"</code> 
  68.  * should be, however, reserved for proxy classes. 
  69.  * 
  70.  * <li>A proxy class extends <code>java.lang.reflect.Proxy</code>. 
  71.  * 
  72.  * <li>A proxy class implements exactly the interfaces specified at its 
  73.  * creation, in the same order. 
  74.  * 
  75.  * <li>If a proxy class implements a non-public interface, then it will 
  76.  * be defined in the same package as that interface.  Otherwise, the 
  77.  * package of a proxy class is also unspecified.  Note that package 
  78.  * sealing will not prevent a proxy class from being successfully defined 
  79.  * in a particular package at runtime, and neither will classes already 
  80.  * defined by the same class loader and the same package with particular 
  81.  * signers. 
  82.  * 
  83.  * <li>Since a proxy class implements all of the interfaces specified at 
  84.  * its creation, invoking <code>getInterfaces</code> on its 
  85.  * <code>Class</code> object will return an array containing the same 
  86.  * list of interfaces (in the order specified at its creation), invoking 
  87.  * <code>getMethods</code> on its <code>Class</code> object will return 
  88.  * an array of <code>Method</code> objects that include all of the 
  89.  * methods in those interfaces, and invoking <code>getMethod</code> will 
  90.  * find methods in the proxy interfaces as would be expected. 
  91.  * 
  92.  * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will 
  93.  * return true if it is passed a proxy class-- a class returned by 
  94.  * <code>Proxy.getProxyClass</code> or the class of an object returned by 
  95.  * <code>Proxy.newProxyInstance</code>-- and false otherwise. 
  96.  * 
  97.  * <li>The <code>java.security.ProtectionDomain</code> of a proxy class 
  98.  * is the same as that of system classes loaded by the bootstrap class 
  99.  * loader, such as <code>java.lang.Object</code>, because the code for a 
  100.  * proxy class is generated by trusted system code.  This protection 
  101.  * domain will typically be granted 
  102.  * <code>java.security.AllPermission</code>. 
  103.  * 
  104.  * <li>Each proxy class has one public constructor that takes one argument, 
  105.  * an implementation of the interface {@link InvocationHandler}, to set 
  106.  * the invocation handler for a proxy instance.  Rather than having to use 
  107.  * the reflection API to access the public constructor, a proxy instance 
  108.  * can be also be created by calling the {@link Proxy#newProxyInstance 
  109.  * Proxy.newInstance} method, which combines the actions of calling 
  110.  * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the 
  111.  * constructor with an invocation handler. 
  112.  * </ul> 
  113.  * 
  114.  * <p>A proxy instance has the following properties: 
  115.  * 
  116.  * <ul> 
  117.  * <li>Given a proxy instance <code>proxy</code> and one of the 
  118.  * interfaces implemented by its proxy class <code>Foo</code>, the 
  119.  * following expression will return true: 
  120.  * <pre> 
  121.  *     <code>proxy instanceof Foo</code> 
  122.  * </pre> 
  123.  * and the following cast operation will succeed (rather than throwing 
  124.  * a <code>ClassCastException</code>): 
  125.  * <pre> 
  126.  *     <code>(Foo) proxy</code> 
  127.  * </pre> 
  128.  * 
  129.  * <li>Each proxy instance has an associated invocation handler, the one 
  130.  * that was passed to its constructor.  The static 
  131.  * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method 
  132.  * will return the invocation handler associated with the proxy instance 
  133.  * passed as its argument. 
  134.  * 
  135.  * <li>An interface method invocation on a proxy instance will be 
  136.  * encoded and dispatched to the invocation handler's {@link 
  137.  * InvocationHandler#invoke invoke} method as described in the 
  138.  * documentation for that method. 
  139.  * 
  140.  * <li>An invocation of the <code>hashCode</code>, 
  141.  * <code>equals</code>, or <code>toString</code> methods declared in 
  142.  * <code>java.lang.Object</code> on a proxy instance will be encoded and 
  143.  * dispatched to the invocation handler's <code>invoke</code> method in 
  144.  * the same manner as interface method invocations are encoded and 
  145.  * dispatched, as described above.  The declaring class of the 
  146.  * <code>Method</code> object passed to <code>invoke</code> will be 
  147.  * <code>java.lang.Object</code>.  Other public methods of a proxy 
  148.  * instance inherited from <code>java.lang.Object</code> are not 
  149.  * overridden by a proxy class, so invocations of those methods behave 
  150.  * like they do for instances of <code>java.lang.Object</code>. 
  151.  * </ul> 
  152.  * 
  153.  * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3> 
  154.  * 
  155.  * <p>When two or more interfaces of a proxy class contain a method with 
  156.  * the same name and parameter signature, the order of the proxy class's 
  157.  * interfaces becomes significant.  When such a <i>duplicate method</i> 
  158.  * is invoked on a proxy instance, the <code>Method</code> object passed 
  159.  * to the invocation handler will not necessarily be the one whose 
  160.  * declaring class is assignable from the reference type of the interface 
  161.  * that the proxy's method was invoked through.  This limitation exists 
  162.  * because the corresponding method implementation in the generated proxy 
  163.  * class cannot determine which interface it was invoked through. 
  164.  * Therefore, when a duplicate method is invoked on a proxy instance, 
  165.  * the <code>Method</code> object for the method in the foremost interface 
  166.  * that contains the method (either directly or inherited through a 
  167.  * superinterface) in the proxy class's list of interfaces is passed to 
  168.  * the invocation handler's <code>invoke</code> method, regardless of the 
  169.  * reference type through which the method invocation occurred. 
  170.  * 
  171.  * <p>If a proxy interface contains a method with the same name and 
  172.  * parameter signature as the <code>hashCode</code>, <code>equals</code>, 
  173.  * or <code>toString</code> methods of <code>java.lang.Object</code>, 
  174.  * when such a method is invoked on a proxy instance, the 
  175.  * <code>Method</code> object passed to the invocation handler will have 
  176.  * <code>java.lang.Object</code> as its declaring class.  In other words, 
  177.  * the public, non-final methods of <code>java.lang.Object</code> 
  178.  * logically precede all of the proxy interfaces for the determination of 
  179.  * which <code>Method</code> object to pass to the invocation handler. 
  180.  * 
  181.  * <p>Note also that when a duplicate method is dispatched to an 
  182.  * invocation handler, the <code>invoke</code> method may only throw 
  183.  * checked exception types that are assignable to one of the exception 
  184.  * types in the <code>throws</code> clause of the method in <i>all</i> of 
  185.  * the proxy interfaces that it can be invoked through.  If the 
  186.  * <code>invoke</code> method throws a checked exception that is not 
  187.  * assignable to any of the exception types declared by the method in one 
  188.  * of the proxy interfaces that it can be invoked through, then an 
  189.  * unchecked <code>UndeclaredThrowableException</code> will be thrown by 
  190.  * the invocation on the proxy instance.  This restriction means that not 
  191.  * all of the exception types returned by invoking 
  192.  * <code>getExceptionTypes</code> on the <code>Method</code> object 
  193.  * passed to the <code>invoke</code> method can necessarily be thrown 
  194.  * successfully by the <code>invoke</code> method. 
  195.  * 
  196.  * @author  Peter Jones 
  197.  * @version 1.22, 05/11/17 
  198.  * @see     InvocationHandler 
  199.  * @since   1.3 
  200.  */  
  201. public class Proxy implements java.io.Serializable {  
  202.   
  203.     private static final long serialVersionUID = -2222568056686623797L;  
  204.   
  205.     /** prefix for all proxy class names */  
  206.     private final static String proxyClassNamePrefix = "$Proxy";  
  207.   
  208.     /** parameter types of a proxy class constructor */  
  209.     private final static Class[] constructorParams =  
  210.     { InvocationHandler.class };  
  211.   
  212.     /** maps a class loader to the proxy class cache for that loader */  
  213.     private static Map loaderToCache = new WeakHashMap();//弱HashMap  
  214.   
  215.     /** marks that a particular proxy class is currently being generated */  
  216.     private static Object pendingGenerationMarker = new Object();//代理正在被创建的标志!!  
  217.   
  218.     /** next number to use for generation of unique proxy class names */  
  219.     private static long nextUniqueNumber = 0;  
  220.     private static Object nextUniqueNumberLock = new Object();  
  221.   
  222.     /** set of all generated proxy classes, for isProxyClass implementation */  
  223.     private static Map proxyClasses =  
  224.     Collections.synchronizedMap(new WeakHashMap());//线程安全的弱HahsMap  
  225.   
  226.     /** 
  227.      * the invocation handler for this proxy instance. 
  228.      * @serial 
  229.      */  
  230.     protected InvocationHandler h;  
  231.   
  232.     /** 
  233.      * Prohibits instantiation. 
  234.      */  
  235.     private Proxy() {  
  236.     }  
  237.   
  238.     /** 
  239.      * Constructs a new <code>Proxy</code> instance from a subclass 
  240.      * (typically, a dynamic proxy class) with the specified value 
  241.      * for its invocation handler. 
  242.      * 
  243.      * @param   h the invocation handler for this proxy instance 
  244.      */  
  245.     protected Proxy(InvocationHandler h) {  
  246.     this.h = h;  
  247.     }  
  248.   
  249.     /** 
  250.      * Returns the <code>java.lang.Class</code> object for a proxy class 
  251.      * given a class loader and an array of interfaces.  The proxy class 
  252.      * will be defined by the specified class loader and will implement 
  253.      * all of the supplied interfaces.  If a proxy class for the same 
  254.      * permutation of interfaces has already been defined by the class 
  255.      * loader, then the existing proxy class will be returned; otherwise, 
  256.      * a proxy class for those interfaces will be generated dynamically 
  257.      * and defined by the class loader. 
  258.      * 
  259.      * <p>There are several restrictions on the parameters that may be 
  260.      * passed to <code>Proxy.getProxyClass</code>: 
  261.      * 
  262.      * <ul> 
  263.      * <li>All of the <code>Class</code> objects in the 
  264.      * <code>interfaces</code> array must represent interfaces, not 
  265.      * classes or primitive types. 
  266.      * 
  267.      * <li>No two elements in the <code>interfaces</code> array may 
  268.      * refer to identical <code>Class</code> objects. 
  269.      * 
  270.      * <li>All of the interface types must be visible by name through the 
  271.      * specified class loader.  In other words, for class loader 
  272.      * <code>cl</code> and every interface <code>i</code>, the following 
  273.      * expression must be true: 
  274.      * <pre> 
  275.      *     Class.forName(i.getName(), false, cl) == i 
  276.      * </pre> 
  277.      * 
  278.      * <li>All non-public interfaces must be in the same package; 
  279.      * otherwise, it would not be possible for the proxy class to 
  280.      * implement all of the interfaces, regardless of what package it is 
  281.      * defined in. 
  282.      * 
  283.      * <li>For any set of member methods of the specified interfaces 
  284.      * that have the same signature: 
  285.      * <ul> 
  286.      * <li>If the return type of any of the methods is a primitive 
  287.      * type or void, then all of the methods must have that same 
  288.      * return type. 
  289.      * <li>Otherwise, one of the methods must have a return type that 
  290.      * is assignable to all of the return types of the rest of the 
  291.      * methods. 
  292.      * </ul> 
  293.      * 
  294.      * <li>The resulting proxy class must not exceed any limits imposed 
  295.      * on classes by the virtual machine.  For example, the VM may limit 
  296.      * the number of interfaces that a class may implement to 65535; in 
  297.      * that case, the size of the <code>interfaces</code> array must not 
  298.      * exceed 65535. 
  299.      * </ul> 
  300.      * 
  301.      * <p>If any of these restrictions are violated, 
  302.      * <code>Proxy.getProxyClass</code> will throw an 
  303.      * <code>IllegalArgumentException</code>.  If the <code>interfaces</code> 
  304.      * array argument or any of its elements are <code>null</code>, a 
  305.      * <code>NullPointerException</code> will be thrown. 
  306.      * 
  307.      * <p>Note that the order of the specified proxy interfaces is 
  308.      * significant: two requests for a proxy class with the same combination 
  309.      * of interfaces but in a different order will result in two distinct 
  310.      * proxy classes. 
  311.      * 
  312.      * @param   loader the class loader to define the proxy class 
  313.      * @param   interfaces the list of interfaces for the proxy class 
  314.      *      to implement 
  315.      * @return  a proxy class that is defined in the specified class loader 
  316.      *      and that implements the specified interfaces 
  317.      * @throws  IllegalArgumentException if any of the restrictions on the 
  318.      *      parameters that may be passed to <code>getProxyClass</code> 
  319.      *      are violated 
  320.      * @throws  NullPointerException if the <code>interfaces</code> array 
  321.      *      argument or any of its elements are <code>null</code> 
  322.      */  
  323.     public static Class<?> getProxyClass(ClassLoader loader,   
  324.                                          Class<?>... interfaces)  
  325.     throws IllegalArgumentException  
  326.     {//大于65535个接口抛异常  
  327.     if (interfaces.length > 65535) {  
  328.         throw new IllegalArgumentException("interface limit exceeded");  
  329.     }  
  330.   
  331.     Class proxyClass = null;  
  332.   
  333.     /* collect interface names to use as key for proxy class cache */  
  334.     String[] interfaceNames = new String[interfaces.length];//存放接口名  
  335.   
  336.     Set interfaceSet = new HashSet();   // for detecting duplicates//去重复接口的集合  
  337.   
  338.     for (int i = 0; i < interfaces.length; i++) {  
  339.         /* 
  340.          * Verify that the class loader resolves the name of this 
  341.          * interface to the same Class object. 
  342.          * 通过类加载器去加载,验证类实现是否实现接口 
  343.          */  
  344.         String interfaceName = interfaces[i].getName();  
  345.         Class interfaceClass = null;  
  346.         try {  
  347.         //参数false表示类加载器加载时候不解释improt  
  348.         interfaceClass = Class.forName(interfaceName, false, loader);  
  349.         } catch (ClassNotFoundException e) {  
  350.         }  
  351.         if (interfaceClass != interfaces[i]) {  
  352.         throw new IllegalArgumentException(  
  353.             interfaces[i] + " is not visible from class loader");  
  354.         }  
  355.   
  356.         /* 
  357.          * Verify that the Class object actually represents an 
  358.          * interface. 
  359.          * 验证是不是接口 
  360.          */  
  361.         if (!interfaceClass.isInterface()) {  
  362.         throw new IllegalArgumentException(  
  363.             interfaceClass.getName() + " is not an interface");  
  364.         }  
  365.   
  366.         /* 
  367.          * Verify that this interface is not a duplicate. 
  368.          * 去重复 
  369.          */  
  370.         if (interfaceSet.contains(interfaceClass)) {  
  371.         throw new IllegalArgumentException(  
  372.             "repeated interface: " + interfaceClass.getName());  
  373.         }  
  374.         interfaceSet.add(interfaceClass);  
  375.   
  376.         //保存接口名  
  377.         interfaceNames[i] = interfaceName;  
  378.     }  
  379.   
  380.     /* 
  381.      * Using string representations of the proxy interfaces as 
  382.      * keys in the proxy class cache (instead of their Class 
  383.      * objects) is sufficient because we require the proxy 
  384.      * interfaces to be resolvable by name through the supplied 
  385.      * class loader, and it has the advantage that using a string 
  386.      * representation of a class makes for an implicit weak 
  387.      * reference to the class. 
  388.      * 用代理接口的字符串形式表示key存在缓存里尔不是Class对象足够了,因为我们需要 
  389.      * 代理接口去通过类加载器用名字渲染。并且这样带来的好处是使用字符串形式表述class能不明显的依赖class 
  390.      */  
  391.     Object key = Arrays.asList(interfaceNames);  
  392.   
  393.     /* 
  394.      * Find or create the proxy class cache for the class loader. 
  395.      * 从弱HahsMap中取得类加载器,如果不存在,放入弱HashMap 
  396.      */  
  397.     Map cache;  
  398.     synchronized (loaderToCache) {  
  399.         cache = (Map) loaderToCache.get(loader);  
  400.         if (cache == null) {  
  401.         cache = new HashMap();  
  402.         loaderToCache.put(loader, cache);  
  403.         }  
  404.         /* 
  405.          * This mapping will remain valid for the duration of this 
  406.          * method, without further synchronization, because the mapping 
  407.          * will only be removed if the class loader becomes unreachable. 
  408.          */  
  409.     }  
  410.   
  411.     /* 
  412.      * Look up the list of interfaces in the proxy class cache using 
  413.      * the key.  This lookup will result in one of three possible 
  414.      * kinds of values: 
  415.      *     null, if there is currently no proxy class for the list of 
  416.      *         interfaces in the class loader, 
  417.      *     the pendingGenerationMarker object, if a proxy class for the 
  418.      *         list of interfaces is currently being generated, 
  419.      *     or a weak reference to a Class object, if a proxy class for 
  420.      *         the list of interfaces has already been generated. 
  421.      */  
  422.     synchronized (cache) {  
  423.         /* 
  424.          * Note that we need not worry about reaping the cache for 
  425.          * entries with cleared weak references because if a proxy class 
  426.          * has been garbage collected, its class loader will have been 
  427.          * garbage collected as well, so the entire cache will be reaped 
  428.          * from the loaderToCache map. 
  429.          * 注意我们不用担心从缓存中得到已经被清楚的弱引用对应的Class实例(这里弱引用是key,实体是value) 
  430.          * 因为一个代理class会被垃圾回收, 
  431.          * 它的类加载器也会被垃圾回收,所以实体缓存会从loaderToCache map中获得 
  432.          *  
  433.          * 三种情况: 
  434.          * 1如果当前缓存总没有此Proxy类则返回null 
  435.          * 2如果Proxy类正在创建则返回pendingGenerationMarker对象 
  436.          * 3如果此Proxy类已经被创建,则返回WeakReference对象 
  437.          *  
  438.          */  
  439.         do {  
  440.         Object value = cache.get(key);  
  441.         if (value instanceof Reference) {  
  442.             proxyClass = (Class) ((Reference) value).get();  
  443.         }  
  444.         if (proxyClass != null) {  
  445.             // proxy class already generated: return it  
  446.             return proxyClass;  
  447.         } else if (value == pendingGenerationMarker) {  
  448.             // proxy class being generated: wait for it  
  449.             try {  
  450.             cache.wait();  
  451.             } catch (InterruptedException e) {  
  452.             /* 
  453.              * The class generation that we are waiting for should 
  454.              * take a small, bounded time, so we can safely ignore 
  455.              * thread interrupts here. 
  456.              */  
  457.             }  
  458.             continue;  
  459.         } else {  
  460.             /* 
  461.              * No proxy class for this list of interfaces has been 
  462.              * generated or is being generated, so we will go and 
  463.              * generate it now.  Mark it as pending generation. 
  464.              * 没有这堆接口的代理类生成或者正在被创建,我们创建it now!~标记为正在创建,跳出循环 
  465.              */  
  466.             cache.put(key, pendingGenerationMarker);  
  467.             break;  
  468.         }  
  469.         } while (true);  
  470.     }  
  471.   
  472.     try {  
  473.         String proxyPkg = null; // package to define proxy class in  
  474.   
  475.         /* 
  476.          * 记录包可见的代理接口,for循环中是校验非公有接口是否在同一包下的算法 
  477.          * Record the package of a non-public proxy interface so that the 
  478.          * proxy class will be defined in the same package.  Verify that 
  479.          * all non-public proxy interfaces are in the same package. 
  480.          */  
  481.         for (int i = 0; i < interfaces.length; i++) {  
  482.         int flags = interfaces[i].getModifiers();  
  483.         if (!Modifier.isPublic(flags)) {  
  484.             String name = interfaces[i].getName();  
  485.             int n = name.lastIndexOf('.');  
  486.             String pkg = ((n == -1) ? "" : name.substring(0, n + 1));  
  487.             if (proxyPkg == null) {  
  488.             proxyPkg = pkg;  
  489.             } else if (!pkg.equals(proxyPkg)) {  
  490.             throw new IllegalArgumentException(  
  491.                 "non-public interfaces from different packages");  
  492.             }  
  493.         }  
  494.         }  
  495.   
  496.         if (proxyPkg == null) { // if no non-public proxy interfaces,  
  497.         proxyPkg = "";      // use the unnamed package  
  498.         }  
  499.   
  500.         {  
  501.         /* 
  502.          * Choose a name for the proxy class to generate. 
  503.          */  
  504.         long num;  
  505.         synchronized (nextUniqueNumberLock) {  
  506.              //这里使用静态属性作为锁,保护了同步区域内的数据  
  507.                //因为num是long型的,无法对原始对象加锁(只能对类加锁)  
  508.                //而如果对整个当前对象加锁会浪费性能  
  509.                //使用一个锁对象,还可达到同时保护多个数据(对象,原始类型)的效果  
  510.             num = nextUniqueNumber++;  
  511.         }  
  512.         String proxyName = proxyPkg + proxyClassNamePrefix + num;//$Proxy+num  
  513.         /* 
  514.          * Verify that the class loader hasn't already 
  515.          * defined a class with the chosen name. 
  516.          */  
  517.   
  518.         /* 
  519.          * Generate the specified proxy class. 
  520.          * //生成Class类的字节码 
  521.          */  
  522.         byte[] proxyClassFile = ProxyGenerator.generateProxyClass(  
  523.             proxyName, interfaces);  
  524.         try {  
  525.             //加载代理类  
  526.             proxyClass = defineClass0(loader, proxyName,  
  527.             proxyClassFile, 0, proxyClassFile.length);  
  528.         } catch (ClassFormatError e) {  
  529.             /* 
  530.              * A ClassFormatError here means that (barring bugs in the 
  531.              * proxy class generation code) there was some other 
  532.              * invalid aspect of the arguments supplied to the proxy 
  533.              * class creation (such as virtual machine limitations 
  534.              * exceeded). 
  535.              */  
  536.             throw new IllegalArgumentException(e.toString());  
  537.         }  
  538.         }  
  539.         // add to set of all generated proxy classes, for isProxyClass  
  540.         proxyClasses.put(proxyClass, null);  
  541.   
  542.     } finally {  
  543.         /* 
  544.          * We must clean up the "pending generation" state of the proxy 
  545.          * class cache entry somehow.  If a proxy class was successfully 
  546.          * generated, store it in the cache (with a weak reference); 
  547.          * otherwise, remove the reserved entry.  In all cases, notify 
  548.          * all waiters on reserved entries in this cache. 
  549.          */  
  550.         synchronized (cache) {  
  551.         if (proxyClass != null) {  
  552.             cache.put(key, new WeakReference(proxyClass));//key是一堆接口的集合,并除去标记正在生成代理的pending generation对象  
  553.         } else {  
  554.             cache.remove(key);  
  555.         }  
  556.         cache.notifyAll();  
  557.         }  
  558.     }  
  559.     return proxyClass;  
  560.     }  
  561.   
  562.     /** 
  563.      * Returns an instance of a proxy class for the specified interfaces 
  564.      * that dispatches method invocations to the specified invocation 
  565.      * handler.  This method is equivalent to: 
  566.      * <pre> 
  567.      *     Proxy.getProxyClass(loader, interfaces). 
  568.      *         getConstructor(new Class[] { InvocationHandler.class }). 
  569.      *         newInstance(new Object[] { handler }); 
  570.      * </pre> 
  571.      * 
  572.      * <p><code>Proxy.newProxyInstance</code> throws 
  573.      * <code>IllegalArgumentException</code> for the same reasons that 
  574.      * <code>Proxy.getProxyClass</code> does. 
  575.      * 
  576.      * @param   loader the class loader to define the proxy class 
  577.      * @param   interfaces the list of interfaces for the proxy class 
  578.      *      to implement 
  579.      * @param   h the invocation handler to dispatch method invocations to 
  580.      * @return  a proxy instance with the specified invocation handler of a 
  581.      *      proxy class that is defined by the specified class loader 
  582.      *      and that implements the specified interfaces 
  583.      * @throws  IllegalArgumentException if any of the restrictions on the 
  584.      *      parameters that may be passed to <code>getProxyClass</code> 
  585.      *      are violated 
  586.      * @throws  NullPointerException if the <code>interfaces</code> array 
  587.      *      argument or any of its elements are <code>null</code>, or 
  588.      *      if the invocation handler, <code>h</code>, is 
  589.      *      <code>null</code> 
  590.      */  
  591.     //类加载器,接口的Class数组,类加载器,通常是APPClassLoader  
  592.     public static Object newProxyInstance(ClassLoader loader,  
  593.                       Class<?>[] interfaces,  
  594.                       InvocationHandler h)  
  595.     throws IllegalArgumentException  
  596.     {  
  597.     if (h == null) {  
  598.         throw new NullPointerException();  
  599.     }  
  600.   
  601.     /* 
  602.      * Look up or generate the designated proxy class. 
  603.      */  
  604.     //生成代理类的Class对象  
  605.     Class cl = getProxyClass(loader, interfaces);  
  606.   
  607.     /* 
  608.      * Invoke its constructor with the designated invocation handler. 
  609.      */  
  610.     try {  
  611.         //获得有一个InvocationHandler对象参数的构造函数  
  612.         Constructor cons = cl.getConstructor(constructorParams);  
  613.         //创建并返回实例  
  614.         return (Object) cons.newInstance(new Object[] { h });  
  615.     } catch (NoSuchMethodException e) {  
  616.         throw new InternalError(e.toString());  
  617.     } catch (IllegalAccessException e) {  
  618.         throw new InternalError(e.toString());  
  619.     } catch (InstantiationException e) {  
  620.         throw new InternalError(e.toString());  
  621.     } catch (InvocationTargetException e) {  
  622.         throw new InternalError(e.toString());  
  623.     }  
  624.     }  
  625.   
  626.     /** 
  627.      * Returns true if and only if the specified class was dynamically 
  628.      * generated to be a proxy class using the <code>getProxyClass</code> 
  629.      * method or the <code>newProxyInstance</code> method. 
  630.      * 
  631.      * <p>The reliability of this method is important for the ability 
  632.      * to use it to make security decisions, so its implementation should 
  633.      * not just test if the class in question extends <code>Proxy</code>. 
  634.      * 
  635.      * @param   cl the class to test 
  636.      * @return  <code>true</code> if the class is a proxy class and 
  637.      *      <code>false</code> otherwise 
  638.      * @throws  NullPointerException if <code>cl</code> is <code>null</code> 
  639.      */  
  640.     public static boolean isProxyClass(Class<?> cl) {  
  641.     if (cl == null) {  
  642.         throw new NullPointerException();  
  643.     }  
  644.   
  645.     return proxyClasses.containsKey(cl);  
  646.     }  
  647.   
  648.     /** 
  649.      * Returns the invocation handler for the specified proxy instance. 
  650.      * 
  651.      * @param   proxy the proxy instance to return the invocation handler for 
  652.      * @return  the invocation handler for the proxy instance 
  653.      * @throws  IllegalArgumentException if the argument is not a 
  654.      *      proxy instance 
  655.      */  
  656.     public static InvocationHandler getInvocationHandler(Object proxy)  
  657.     throws IllegalArgumentException  
  658.     {  
  659.     /* 
  660.      * Verify that the object is actually a proxy instance. 
  661.      */  
  662.     if (!isProxyClass(proxy.getClass())) {  
  663.         throw new IllegalArgumentException("not a proxy instance");  
  664.     }  
  665.   
  666.     Proxy p = (Proxy) proxy;  
  667.     return p.h;  
  668.     }  
  669.   
  670.     private static native Class defineClass0(ClassLoader loader, String name,  
  671.                          byte[] b, int off, int len);  
  672. }  

nginx stream proxy 模块的ssl连接源码分析 本为对 nginx的ngx_stream_proxy_module与上游服务器建立ssl连接的过程进行了详细分析。 阅读详情

相关推荐

Proxy源代码分析

linux 网络编程 Proxy源代码分析 经典代码

一文看懂Java Proxy类创建代理类实现原理源码深度剖析

一文看懂Java Proxy类创建代理类实现原理源码深度剖析,为什么要传入类加载器,代理类是如何创建出来的

大数据开发、JAVA开发、人工智能AI 2998

STM32F103 RTC闹钟唤醒Stop模式的EXTI17中断实现

本文详细介绍了STM32F103如何通过RTC闹钟触发EXTI17中断实现从Stop模式的高效唤醒。针对低功耗应用场景,提供了完整的硬件配置、CubeMX设置及代码实现方案,包括时间格式转换、中断处理和功耗优化技巧,帮助开发者可靠实现定时唤醒功能。

ol78901234的博客 230

常见的Proxy源码分析

文章目录一 描述二 源码三 dubbo的Proxy 一 描述 dubbo的源码中,还有两个关于javassist技术和jdk proxy的扩展, javassist:动态编程,通过jdk中的JavaCompiler接口,能够直接对一个已经存在java class文件进行编译,也可以在内存中动态生成java代码,动态编译执行 jdk proxy:jdk动态代理,通过Proxy类动态的根据指定的接口...

zcswl7961的博客 3736

手把手教你用STM32H743+FreeRTOS+LWIP搭建物联网网关(附完整工程)

本文详细介绍了如何使用STM32H743微控制器结合FreeRTOS实时操作系统和LWIP协议栈构建高性能物联网网关。内容涵盖硬件配置、FreeRTOS任务设计、LWIP协议栈优化及物联网协议集成,提供完整工程示例,助力开发者快速实现稳定可靠的网络通信枢纽。

weixin_42623010的博客 502

从零开始:用摩尔线程S4000运行开源AI项目的完整流程

本文详细介绍了如何使用摩尔线程S4000 GPU从零开始运行开源AI项目的完整流程,包括硬件选择、驱动安装、容器化环境配置以及典型AI项目的实战部署。通过性能优化技巧,显著提升推理速度,适合开发者快速上手国产GPU的AI应用开发。

weixin_29231725的博客 581

Proxy动态代理源码分析

ProxyGenerator#generateProxyClass()方法创建生成对象的字节码.然后调用native()方法Proxy#defineClass0()根据字节码创建Class对象.所有方法m1,m2都去调用自己写的代理对象的InvocationHandler.invoke()方法,参数为自己,调用方法Method,参数.1.在Proxy.newProxyInstance()中创建生成对象,生成对象需要实现目标接口的所有方法。(二).创建生成对象的代理方法字节码.

研究源码的最底层,只持有正确的仓位 477

【音视频处理】MP4、FLV、HLS适用范围,在线视频播放哪个更好

本期我们讨论在线点播的视频格式,对比这些视频格式的优劣以及原因 1、封装格式的作用 2、MP4 3、FLV 4、HLS

池鱼 - YiiGaa 2万+

Proxy源码解析。

/** * Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。 * * 创建某一接口 Foo 的代理: * * InvocationHandler handler = new MyInvocationHandler(...); * Class proxyClass = Proxy.getProxyClass( * ...

孤芳不自赏 1418

OCS2 移动机械臂深度解析:ocs2_mobile_manipulator 与 ocs2_mobile_manipulator_ros 源码全拆解

摘要:本文深入解析OCS2移动机械臂MPC控制框架的两个核心工具包。ocs2_mobile_manipulator负责算法建模,通过MobileManipulatorInterface统一构建最优控制问题,支持4种机械臂模型并实现自动维度推导;ocs2_mobile_manipulator_ros负责ROS集成,包含MPC求解、虚拟跟踪等4个核心节点。文章详细剖析了工具包分工、最优控制建模架构(含动力学、代价约束设计)、ROS运行管线、参数配置映射,并提供了高效的源码阅读顺序建议,帮助开发者快速掌握移动机械

m0_73309445的博客 654

NLP高频面试题(一)——Transformer的基本结构、作用和代码实现

本文详细介绍了Transformer模型的基本结构和PyTorch代码实现过程。首先解析了Transformer的核心组成部分,包括嵌入层、多头自注意力机制、位置编码、前馈神经网络、编码器和解码器等模块,并通过清晰的代码示例逐步展示了如何在PyTorch中构建完整的Transformer模型。文末提供了一个可运行的简单示例,帮助读者快速理解并实践Transformer的核心原理与实现方法。

WeLearnNLP 1026

JDK中的动态代理之二

JDK中的动态代理之二public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)throws IllegalArgumentException{                   if (h == null) {    throw new Null

Jason Hm 1098

从原理到落地:Java+TensorRT打造YOLO模型GPU极致推理方案

Java+TensorRT的YOLO模型GPU加速方案,核心是通过JNI桥接实现Java与TensorRT的高效交互,结合TensorRT的底层优化能力,最大化GPU算力。该方案既保留了Java后端的工程化优势(如易维护、生态完善),又解决了AI模型推理的性能瓶颈,可落地于实时视频分析、智能监控、工业质检等场景。基于TensorRT Dynamic Shape实现多尺寸输入的自适应优化;结合Java的协程(Virtual Thread)提升异步推理的并发效率;

2601_94871597的博客 766

kube-proxy源码分析

本文主要是对kube-proxy的源码分析,了解其代码结构和实现原理。这里是根据版本来进行分析的。在下面贴上的代码会一定裁剪,主要用于理解主流程。首先是各种对象套娃式的初始化,Options->ProxyServier->proxier->syncRunner然后是向informer中注册service和endpoint事件,当发生改动时,会给bfr.run发送信号syncRunner收到信号会去执行proxier.syncProxyRules()方法,刷新主机的iptables规则。

Crazy博客 1162

R语言中如何获取前向选择(forward selection)选出的变量

前向选择是一种常用的特征选择方法,可以在给定一个预测模型的情况下,逐步添加变量来确定最佳的预测模型。在R语言中,可以使用适当的函数和库来执行前向选择,并获取选出的变量。以下是一个详细的步骤,展示了如何使用R语言执行前向选择并获得选出的变量。通过按照上述步骤,你可以使用R语言执行前向选择,并获取选出的变量。记住,前向选择是一种特征选择方法,可以根据不同的评估指标选择最佳的预测模型。接下来,准备用于前向选择的数据。使用"summary"函数查看前向选择的摘要,并使用"which"函数获取被选中的变量。

WangWEel的博客 924

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Kube-Proxy IPVS模式源码分析

女主宣言kube-proxy当前支持三种方式实现负载均衡,分别是: userspace, iptables, IPVS. 但前两者随着Service的数量增长,存在性能的...

HULK一线技术杂谈 358

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

nginx proxy_pass和upstream源码分析

proxy_pass nginx中有两个模块都有proxy_pass指令,用于反向代理配置项。 ngx_http_proxy_module的proxy_pass: 句法: proxy_pass URL; 上下文: location, if in location, limit_except 说明: 设置后端代理服务器的协议(protocol)和地址(address),以及location中可以匹配的一个可选的URI。协议可以是"http"或"https"。地址可以..

focus on security 1439

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

k8s kube-proxy源码分析

service是为了给一组pod提供负载均衡功能的服务。

fengcai_ke的博客 442

k8s源码分析1--kube-proxy

k8s源码分析1--kube-proxykube-proxy什么鬼? kube-proxy什么鬼? 看过很多文章和自己日常应用分析作出如下解释: kube-proxy 部署在节点上,是为了: 和k8s-apiserver交互,维持service相关的ip状态。 调用系统层的工具创建service相关的链路和规则,主要是iptables,包含 使用iptables维持的负载均衡。 解释很简单,到达是不是?我们打开源码看看。 ...

qq_35117900的博客 569

mysql proxy 源码分析_Mariadb · 源码分析 · proxy protocol

前言MariaDB MaxScale 是一款数据库中间件,可以按照语义分发语句到多个数据库服务器上。它对应用程序透明,可以提供读写分离、负载均衡和高可用服务。proxy protocol 是 MaxScale 引入,为了解决使用proxy作为中间件连接mysql时,mysql获取client ip用client通过proxy中间价连接mysql时,mysql server接收到认证报文中,包含的是...

weixin_30325929的博客 690

JAVA设计模式-动态代理(Proxy)源码分析

在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现。 一,Proxy.newProxyInstance方法 1 @CallerSensitive 2 public static Object newProxyInstance(ClassLoader loader, 3 ...

ddv61232的博客 235

spp proxy 源码分析

spp proxy demo

wwhhff11 738

Vue 源码分析之proxy代理

二、Vue 源码分析之proxy代理 当我们在使用Vue进行数据设置时,通常初始化格式为: let data = { age: 12, name: 'yang' } // 实例化Vue对象 let vm = new Vue({ data }) // 输出 vm.age // 12 vm.name // 'yang' vm.data.age // throw error...

优快云前端知识共享 2162

milvus proxy启动源码分析

分析变量rootCoordClient、dataCoordClient、queryCoordClient是何时赋予的值。proxy是一个接口,实现proxyapi功能。components.NewProxy是一个函数。NewProxy()用来创建Proxy结构体。rc.NewServer()产生的是本结构体Server。proxy.NewProxy()产生结构体,是types.ProxyComponent接口的实现。代码位于。

shulu的专栏 811
上一篇: Java反射中Method类invoke方法的用法
下一篇: java 动态代理深度学习(Proxy,InvocationHandler),含$Proxy0源码
GetStudyMessages
博客等级 码龄17年 9粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值