码迷,mamicode.com
首页 > 编程语言 > 详细

java动态代理【二】:JDK动态代理的内部原理

时间:2017-05-10 18:53:30      阅读:281      评论:0      收藏:0      [点我收藏+]

标签:访问   expected   min   tar   different   assertion   exist   boolean   help   

上一章我们简单的讲解了什么是动态代理和如何使用动态代理。
这章讲解一下jdk的动态代理的内部实现:
首先查看测试代码:
            
  1. //创建一个静态方法,生成代理类,
  2. public static Object newProxyInstance(Object speak){
  3. System.out.println(JDKDynamicProxy.class.getClassLoader().toString());
  4. return Proxy.newProxyInstance(JDKDynamicProxy.class.getClassLoader(),new Class[]{Speak.class,Eat.class}, new JDKDynamicProxy(speak));
  5. }

从代码可以看出是调用了Proxy.newProxyInstance,进入该方法,查看源代码:
            
  1. @CallerSensitive
  2. public static Object newProxyInstance(ClassLoader loader,
  3. Class<?>[] interfaces,
  4. InvocationHandler h)
  5. throws IllegalArgumentException
  6. {
  7. if (h == null) {
  8. throw new NullPointerException();
  9. }
  10. final Class<?>[] intfs = interfaces.clone();//拷贝一份接口类数组,我们的例子是传入{Speak.class,Eat.class}
  11. final SecurityManager sm = System.getSecurityManager();//获取安全管理器组件
  12. if (sm != null) {//判断是否有权限去访问
  13. checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
  14. }
  15. /*
  16. * Look up or generate the designated proxy class.
  17. */
  18. //根据classloader和接口类数组动态创建Proxy.cass
  19. Class<?> cl = getProxyClass0(loader, intfs);
  20. /*
  21. * Invoke its constructor with the designated invocation handler.
  22. */
  23. try {
  24. //Proxy.class存在一个以InvocationHandler.class为类型的参数,获取该构造器
  25. //看起来是我们常用的代理模式
  26. final Constructor<?> cons = cl.getConstructor(constructorParams);
  27. final InvocationHandler ih = h;
  28. if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {//判断是Proxy.class是否包含不是public类型的接口
  29. // create proxy instance with doPrivilege as the proxy class may
  30. // implement non-public interfaces that requires a special permission
  31. return AccessController.doPrivileged(new PrivilegedAction<Object>() {
  32. public Object run() {
  33. return newInstance(cons, ih);
  34. }
  35. });
  36. } else {
  37. //返回Proxy.class实例
  38. return newInstance(cons, ih);
  39. }
  40. } catch (NoSuchMethodException e) {
  41. throw new InternalError(e.toString());
  42. }
  43. }
    从代码可以看出,核心方法是:
           Class<?> cl = getProxyClass0(loader, intfs);
    这个方法根据我们传入的接口类和类加载器(若没有自定义加载器,默认是AppClassLoader),此方法是动态生成实现了我们传入的接口的Proxy.class,还有一个Proxy(InvocationHandler h)构造器,传入我们之前实现了InvocationHandler 接口的实现类JDKDynamicProxy.class,之后的newInstance就是反射创建实例并返回。
    先不管那些权限判断的代码,主要看getProxyClass0方法:
     
  1. private static Class<?> getProxyClass0(ClassLoader loader,
  2. Class<?>... interfaces) {
  3. if (interfaces.length > 65535) {//接口数量不能超过65535,刚好是一个int类型的最大值
  4. throw new IllegalArgumentException("interface limit exceeded");
  5. }
  6. // If the proxy class defined by the given loader implementing
  7. // the given interfaces exists, this will simply return the cached copy;
  8. // otherwise, it will create the proxy class via the ProxyClassFactory
  9. return proxyClassCache.get(loader, interfaces);
  10. }
        我们看一下proxyClassCache的定义:
            
  1. /**
  2. * a cache of proxy classes
  3. */
  4. private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
  5. proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
          proxyClassCache是静态变量,从注解可以看出是缓存动态生成的ProxyClass,以便下次再调用的时候可以跳过动态生成java字节码这一步,我们再看一下WeakCache类(题外话:我本地的jdk是1.7版本,在jdk的rt.jar包里是没有java.lang.reflect.WeakCache这个类的,但运行又没有报错,于是看了一下虚拟机的运行环境里的rt.jar,发现是存在这个类的,而且BiFunction伪函数指针是java8才有的):
        技术分享
 

        WeakCache主要的内部类有:CacheKey,CacheValue,Factory,Supplier,Value。
        其中CacheValue实现Supplier的接口中get方法由WeakReference的get方法来实现。
        
        查看WeakCache的成员:
            
  1. private final ReferenceQueue<K> refQueue = new ReferenceQueue();//弱引用队列
  2. //(ClassLoader key ,(<CLassloader,Class<?>[]> key ,Factory value) value)
  3. private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap();
  4. private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap();
  5. private final BiFunction<K, P, ?> subKeyFactory;//Key的创建工厂
  6. private final BiFunction<K, P, V> valueFactory;//value的创建工厂

        主要的有map和reverseMap,其中map的key是ClassLoader类型,Value是concurrentMap类型,而concurrentMap里的key是由subKeyFactory组合ClassLoader和接口类数组组合而成,value有两种可能,一种是Factory对象,一种是CacheValue,Factory对象是生产我们需要的ProxyClass的,而CacheValue是存储已经生产过的ProxyClass。
        看主要方法:
                
  1. //调用这个方法获取动态生成的class
  2. public V get(K paramK, P paramP)
  3. {
  4. Objects.requireNonNull(paramP);//检测传入的接口数组是否为空
  5. expungeStaleEntries();//删除因为只有弱引用没有强引用指向的被gc回收后遗留下来的WeakReference对象,
  6. Object localObject1 = CacheKey.valueOf(paramK, this.refQueue); //创建一个CacheKey,paramK是ClassLoader对象,CacheKey是继承WeakReference类,
  7. Object localObject2 = (ConcurrentMap)this.map.get(localObject1);//判断map中是否存在相同的key
  8. if (localObject2 == null)//不存在
  9. {
  10. localObject3 = (ConcurrentMap)this.map.putIfAbsent(localObject1, localObject2 = new ConcurrentHashMap());//不存在则存入<ClassLoader:localObject1,ConcurrentHashMap:localObject2>,若存在则map.get(localObject1)得到localObject3
  11. if (localObject3 != null)
  12. localObject2 = localObject3;
  13. }
  14. Object localObject3 = Objects.requireNonNull(this.subKeyFactory.apply(paramK, paramP));//创建二元键<classloader,Class<?>[]>
  15. Object localObject4 = (Supplier)((ConcurrentMap)localObject2).get(localObject3);//从localObject2根据我们给的<classloader,Class<?>[]>获取Value,有可能是Factory对象,也有可能是CacheValue对象,Factory则调用动态创建ProxyClass,创建完ProxyClass后封装成CacheValue,然后用CacheValue替换掉Factory。
  16. Factory localFactory = null;
  17. while (true)
  18. {
  19. if (localObject4 != null)
  20. {
  21.        //核心代码
  22. Object localObject5 = ((Supplier)localObject4).get();//调用的有可能是Factory的get方法,也有可能是CacheValue的get方法
  23. if (localObject5 != null)
  24. return localObject5;
  25. }
  26. if (localFactory == null)//为该键值<classloader,intfaces>创建一个工厂
  27. localFactory = new Factory(paramK, paramP, localObject3, (ConcurrentMap)localObject2);
  28. if (localObject4 == null)//把创建的工厂放入localObject2中
  29. {
  30. localObject4 = (Supplier)((ConcurrentMap)localObject2).putIfAbsent(localObject3, localFactory);
  31. if (localObject4 != null)
  32. continue;
  33. localObject4 = localFactory;
  34. continue;
  35. }
  36. //当localObject4存在,但Facotry的get方法并返回null时,就替换掉replace(K key, V oldValue, V newValue)
  37. if (((ConcurrentMap)localObject2).replace(localObject3, localObject4, localFactory))
  38. {
  39. localObject4 = localFactory;
  40. continue;
  41. }
  42. localObject4 = (Supplier)((ConcurrentMap)localObject2).get(localObject3);
  43. }
  44. }
               CacheValue的get方法是返回已生成的Class文件,故不再关注,重点关注Factory的get方法
  1. public synchronized V get()
  2. {
  3. //factory获取
  4. WeakCache.Supplier localSupplier = (WeakCache.Supplier)this.valuesMap.get(this.subKey);
  5. if (localSupplier != this)
  6. return null;
  7. Object localObject1 = null;
  8. try
  9. {
  10. //调用ProxyClassFactory的apply,返回Class类型为localObject1
  11. localObject1 = Objects.requireNonNull(WeakCache.this.valueFactory.apply(this.key, this.parameter));
  12. }
  13. finally
  14. {
  15. if (localObject1 == null)
  16. this.valuesMap.remove(this.subKey, this);
  17. }
  18. assert (localObject1 != null);
  19. WeakCache.CacheValue localCacheValue = new WeakCache.CacheValue(localObject1);
  20. //因为Factory和CacheValue都继承Supplier,故可以将原本指向Factory对象替换成指向CacheValue
  21. if (this.valuesMap.replace(this.subKey, this, localCacheValue))
  22. //缓存Class
  23. WeakCache.this.reverseMap.put(localCacheValue, Boolean.TRUE);
  24. else
  25. throw new AssertionError("Should not reach here");
  26. return localObject1;
  27. }
其中WeakCache.this.valueFactory.apply(this.key, this.parameter) 是调用之前
  1. private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
  2. proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
Proxy类的newProxyClassFactory类的apply方法:
            
  1. /**
  2. * A factory function that generates, defines and returns the proxy class given
  3. * the ClassLoader and array of interfaces.
  4. */
  5. private static final class ProxyClassFactory
  6. implements BiFunction<ClassLoader, Class<?>[], Class<?>>
  7. {
  8. // prefix for all proxy class names
  9. //定义类名前缀
  10. private static final String proxyClassNamePrefix = "$Proxy";
  11. // next number to use for generation of unique proxy class names
  12. //生成类序列号和$Proxy组合成类名
  13. private static final AtomicLong nextUniqueNumber = new AtomicLong();
  14. @Override
  15. public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
  16. Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
  17. for (Class<?> intf : interfaces) {
  18. /*
  19. * Verify that the class loader resolves the name of this
  20. * interface to the same Class object.
  21. */
  22.                //循环获取接口类数组
  23. Class<?> interfaceClass = null;
  24. try {
  25.                    加载接口类
  26. interfaceClass = Class.forName(intf.getName(), false, loader);
  27. } catch (ClassNotFoundException e) {
  28. }
  29. if (interfaceClass != intf) {
  30. throw new IllegalArgumentException(
  31. intf + " is not visible from class loader");
  32. }
  33. /*
  34. * Verify that the Class object actually represents an
  35. * interface.
  36. */
  37.                //判断是否接口
  38. if (!interfaceClass.isInterface()) {
  39. throw new IllegalArgumentException(
  40. interfaceClass.getName() + " is not an interface");
  41. }
  42. /*
  43. * Verify that this interface is not a duplicate.
  44. */
  45.                //判断是否有重复的接口
  46. if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
  47. throw new IllegalArgumentException(
  48. "repeated interface: " + interfaceClass.getName());
  49. }
  50. }
  51. String proxyPkg = null; // package to define proxy class in
  52. /*
  53. * Record the package of a non-public proxy interface so that the
  54. * proxy class will be defined in the same package. Verify that
  55. * all non-public proxy interfaces are in the same package.
  56. */
  1.            //判断是否存在接口类不是public,存在就使用它的包路径
  2. for (Class<?> intf : interfaces) {
  3. int flags = intf.getModifiers();
  4. if (!Modifier.isPublic(flags)) {
  5. String name = intf.getName();
  6. int n = name.lastIndexOf(‘.‘);
  7. String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
  8. if (proxyPkg == null) {
  9. proxyPkg = pkg;
  10. } else if (!pkg.equals(proxyPkg)) {
  11. throw new IllegalArgumentException(
  12. "non-public interfaces from different packages");
  13. }
  14. }
  15. }
  16.            //使用默认的包路径
  17.  if (proxyPkg == null) {
  18. // if no non-public proxy interfaces, use com.sun.proxy package
  19. proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
  20. }
  21. /*
  22. * Choose a name for the proxy class to generate.
  23. */
  24.            //获取这次动态代理生成class的序列号
  25. long num = nextUniqueNumber.getAndIncrement();
  26. String proxyName = proxyPkg + proxyClassNamePrefix + num;
  27. /*
  28. * Generate the specified proxy class.
  29. */
                   //主要代码,生成ProxyClass的java字节码文件
  1. byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
  2. proxyName, interfaces);
  3. try {
  4.                //defineClass函数会校验class文件并将class文件加载并返回成Class对象
  5. return defineClass0(loader, proxyName,
  6. proxyClassFile, 0, proxyClassFile.length);
  7. } catch (ClassFormatError e) {
  8. /*
  9. * A ClassFormatError here means that (barring bugs in the
  10. * proxy class generation code) there was some other
  11. * invalid aspect of the arguments supplied to the proxy
  12. * class creation (such as virtual machine limitations
  13. * exceeded).
  14. */
  15. throw new IllegalArgumentException(e.toString());
  16. }
  17. }
  18. }
        过程是先检验我们传入的接口类数组,然后生成ProxyClass的类名proxyName,ProxyClass的包路径pkgname,再根据类名和接口生成proxyClassFile字节码文件,然后调用defineClass0函数生成Class对象并返回。
        那我们再进入这个函数看看如何生成class文件的
  1. byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
  2. proxyName, interfaces);
        
  1. public static byte[] generateProxyClass(String paramString, Class[] paramArrayOfClass)
  2. {
  3. ProxyGenerator localProxyGenerator = new ProxyGenerator(paramString, paramArrayOfClass);
  4.  //核心代码
    1. byte[] arrayOfByte = localProxyGenerator.generateClassFile();
    2. //是否保存生成的class文件到本地文件系统,其中saveGeneratedFiles是由saveGeneratedFiles = ((Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"))).booleanValue();
    3. //控制,若想看到生成的class
    4. ,只需要在测试代码中将系统配置属性Sytem.properties里的sun.misc.ProxyGenerator.saveGeneratedFiles改为true就行了,还有就是在项目下建立:com.sun.proxy,否则报fileNotFound
  5. if (saveGeneratedFiles)
  6. AccessController.doPrivileged(new PrivilegedAction(paramString, arrayOfByte)
  7. {
  8. public Void run()
  9. {
  10. try
  11. {
  12. FileOutputStream localFileOutputStream = new FileOutputStream(ProxyGenerator.access$000(this.val$name) + ".class");
  13. localFileOutputStream.write(this.val$classFile);
  14. localFileOutputStream.close();
  15. return null;
  16. }
  17. catch (IOException localIOException)
  18. {
  19. }
  20. throw new InternalError("I/O exception saving generated file: " + localIOException);
  21. }
  22. });
  23. return arrayOfByte;
  24. }

从代码可以看出,我们可以把动态生成的ProxyClass保存到本地文件系统:
  1. //是否保存生成的class文件到本地文件系统,其中saveGeneratedFiles是由saveGeneratedFiles = ((Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"))).booleanValue();
  2. //控制,若想看到生成的class
  3. ,只需要在测试代码中将系统配置属性Sytem.properties里的sun.misc.ProxyGenerator.saveGeneratedFiles改为true就行了,还有就是在项目下建立:com.sun.proxy,否则报fileNotFound
另外一种方法就是编写一个工具方法:
        Path是输出路径,然后反编译就能看到ProxyClass的代码了
  1. public static void writeToDisk(String path) {
  2. byte[] class = ProxyGenerator.generateProxyClass("$Proxy0", Star.class.getInterfaces());
  3. FileOutputStream out = null;
  4. try {
  5. out = new FileOutputStream(path);
  6. out.write(class);
  7. out.flush();
  8. } catch (Exception e) {
  9. e.printStackTrace();
  10. } finally {
  11. try {
  12. out.close();
  13. } catch (IOException e) {
  14. e.printStackTrace();
  15. }
  16. }
  17. }



  1. private byte[] generateClassFile()
  2. {
  3.    //添加hashCode函数字节码
  4. addProxyMethod(hashCodeMethod, Object.class);
  5.    //添加equals函数字节码
  6. addProxyMethod(equalsMethod, Object.class);
  7.   //添加toString函数字节码
  8. addProxyMethod(toStringMethod, Object.class);
  9.    //循环添加接口的方法字节码,存储到名为ProxyMethods的Map中,其Key(String)是方法的字符串如
  10.    //java/io/PrintStream.println:(Ljava/lang/String;),value是List<ProxyMethod>,
  11. for (int i = 0; i < this.interfaces.length; i++)
  12. {
  13. localObject1 = this.interfaces[i].getMethods();
  14. for (int k = 0; k < localObject1.length; k++)
  15. addProxyMethod(localObject1[k], this.interfaces[i]);
  16. }
  17. Iterator localIterator1 = this.proxyMethods.values().iterator();
  18. while (localIterator1.hasNext())
  19. {
  20. localObject1 = (List)localIterator1.next();
  21.      //校验List<ProxyMethod>(有可能有函数名相同的函数,来自不同的接口,但返回类不一样),判断这些返回类中是否有共同的父类,并设置为函数最终返回类型
  22. checkReturnTypes((List)localObject1);
  23. }
  24. Object localObject2;
  25. try
  26. {
  27.      //methods存储的是最终要输出到Class的函数
  28. this.methods.add(generateConstructor());//添加构造器
  29. localIterator1 = this.proxyMethods.values().iterator();
  30. while (localIterator1.hasNext())
  31. {
  32.        
  33. localObject1 = (List)localIterator1.next();
  34. Iterator localIterator2 = ((List)localObject1).iterator();
  35. while (localIterator2.hasNext())
  36. {
  37. localObject2 = (ProxyMethod)localIterator2.next();
  38.         //ProxyClass的成员,成员的类型都是反射Method类型
  39. this.fields.add(new FieldInfo(((ProxyMethod)localObject2).methodFieldName, "Ljava/lang/reflect/Method;", 10));
  40.  //添加方法
  41. this.methods.add(((ProxyMethod)localObject2).generateMethod());
  42. }
  43. }
  44.      //添加静态的初始化模块:static{}
  45. this.methods.add(generateStaticInitializer());
  46. }
  47. catch (IOException localIOException1)
  48. {
  49. throw new InternalError("unexpected I/O Exception");
  50. }
  51. if (this.methods.size() > 65535)//
  52. throw new IllegalArgumentException("method limit exceeded");
  53. if (this.fields.size() > 65535)
  54. throw new IllegalArgumentException("field limit exceeded");
  55.    //下面是常量池的创建赋值
  56. this.cp.getClass(dotToSlash(this.className));
  57. this.cp.getClass("java/lang/reflect/Proxy");
  58. for (int j = 0; j < this.interfaces.length; j++)
  59. this.cp.getClass(dotToSlash(this.interfaces[j].getName()));
  60. this.cp.setReadOnly();
  61.    //最终输出Class文件,如果有兴趣可以去看一下java的字节码结构和含义
  62. ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
  63. Object localObject1 = new DataOutputStream(localByteArrayOutputStream);
  64. try
  65. {
  66. ((DataOutputStream)localObject1).writeInt(-889275714);
  67. ((DataOutputStream)localObject1).writeShort(0);
  68. ((DataOutputStream)localObject1).writeShort(49);
  69. this.cp.write((OutputStream)localObject1);
  70. ((DataOutputStream)localObject1).writeShort(49);
  71. ((DataOutputStream)localObject1).writeShort(this.cp.getClass(dotToSlash(this.className)));
  72. ((DataOutputStream)localObject1).writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
  73. ((DataOutputStream)localObject1).writeShort(this.interfaces.length);
  74. for (int m = 0; m < this.interfaces.length; m++)
  75. ((DataOutputStream)localObject1).writeShort(this.cp.getClass(dotToSlash(this.interfaces[m].getName())));
  76. ((DataOutputStream)localObject1).writeShort(this.fields.size());
  77. Iterator localIterator3 = this.fields.iterator();
  78. while (localIterator3.hasNext())
  79. {
  80. localObject2 = (FieldInfo)localIterator3.next();
  81. ((FieldInfo)localObject2).write((DataOutputStream)localObject1);
  82. }
  83. ((DataOutputStream)localObject1).writeShort(this.methods.size());
  84. localIterator3 = this.methods.iterator();
  85. while (localIterator3.hasNext())
  86. {
  87. localObject2 = (MethodInfo)localIterator3.next();
  88. ((MethodInfo)localObject2).write((DataOutputStream)localObject1);
  89. }
  90. ((DataOutputStream)localObject1).writeShort(0);
  91. }
  92. catch (IOException localIOException2)
  93. {
  94. throw new InternalError("unexpected I/O Exception");
  95. }
  96. return (B)(B)localByteArrayOutputStream.toByteArray();
  97. }

如果想了解java字节码结构,请跳转到下网址:
动态生成的ProxyClass反编译如下:
  1. import cglib.Eat;
  2. import cglib.Speak;
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.Method;
  5. import java.lang.reflect.Proxy;
  6. import java.lang.reflect.UndeclaredThrowableException;
  7. public final class $Proxy0 extends Proxy
  8. implements Speak, Eat
  9. {
  10.   //对应this.fields.add(new FieldInfo(((ProxyMethod)localObject2).methodFieldName, "Ljava/lang/reflect/Method;", 10));
  11. private static Method m3;
  12. private static Method m1;
  13. private static Method m4;
  14. private static Method m0;
  15. private static Method m2;
  16. // 对应this.methods.add(generateConstructor());//添加构造器
  17. public $Proxy0(InvocationHandler paramInvocationHandler)
  18. throws
  19. {
  20. super(paramInvocationHandler);
  21. }
  22.    // 对应this.methods.add(((ProxyMethod)localObject2).generateMethod());
  23. public final void say()
  24. throws
  25. {
  26. try
  27. {
  28. this.h.invoke(this, m3, null);
  29. return;
  30. }
  31. catch (RuntimeException localRuntimeException)
  32. {
  33. throw localRuntimeException;
  34. }
  35. catch (Throwable localThrowable)
  36. {
  37. }
  38. throw new UndeclaredThrowableException(localThrowable);
  39. }
  40. public final boolean equals(Object paramObject)
  41. throws
  42. {
  43. try
  44. {
  45. return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
  46. }
  47. catch (RuntimeException localRuntimeException)
  48. {
  49. throw localRuntimeException;
  50. }
  51. catch (Throwable localThrowable)
  52. {
  53. }
  54. throw new UndeclaredThrowableException(localThrowable);
  55. }
  56. public final void eat()
  57. throws
  58. {
  59. try
  60. {
  61. this.h.invoke(this, m4, null);
  62. return;
  63. }
  64. catch (RuntimeException localRuntimeException)
  65. {
  66. throw localRuntimeException;
  67. }
  68. catch (Throwable localThrowable)
  69. {
  70. }
  71. throw new UndeclaredThrowableException(localThrowable);
  72. }
  73. public final int hashCode()
  74. throws
  75. {
  76. try
  77. {
  78. return ((Integer)this.h.invoke(this, m0, null)).intValue();
  79. }
  80. catch (RuntimeException localRuntimeException)
  81. {
  82. throw localRuntimeException;
  83. }
  84. catch (Throwable localThrowable)
  85. {
  86. }
  87. throw new UndeclaredThrowableException(localThrowable);
  88. }
  89. public final String toString()
  90. throws
  91. {
  92. try
  93. {
  94. return (String)this.h.invoke(this, m2, null);
  95. }
  96. catch (RuntimeException localRuntimeException)
  97. {
  98. throw localRuntimeException;
  99. }
  100. catch (Throwable localThrowable)
  101. {
  102. }
  103. throw new UndeclaredThrowableException(localThrowable);
  104. }
  105.  //对应this.methods.add(generateStaticInitializer());
  106. static
  107. {
  108. try
  109. {
  110. m3 = Class.forName("cglib.Speak").getMethod("say", new Class[0]);
  111. m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
  112. m4 = Class.forName("cglib.Eat").getMethod("eat", new Class[0]);
  113. m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
  114. m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
  115. return;
  116. }
  117. catch (NoSuchMethodException localNoSuchMethodException)
  118. {
  119. throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
  120. }
  121. catch (ClassNotFoundException localClassNotFoundException)
  122. {
  123. }
  124. throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
  125. }
  126. }


参考资料:
        http://rejoy.iteye.com/blog/1627405?page=2
         http://blog.csdn.net/dc_726/article/details/7944154
            
            






java动态代理【二】:JDK动态代理的内部原理

标签:访问   expected   min   tar   different   assertion   exist   boolean   help   

原文地址:http://www.cnblogs.com/zhenyimo/p/6837326.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!