- 1 package java.lang.reflect;
- 2 3 import java.lang.ref.Reference;
- 4 import java.lang.ref.WeakReference;
- 5 import java.security.AccessController;
- 6 import java.security.Permission;
- 7 import java.security.PrivilegedAction;
- 8 import java.util.Arrays;
- 9 import java.util.Collections;
- 10 import java.util.HashMap;
- 11 import java.util.HashSet;
- 12 import java.util.Map;
- 13 import java.util.Set;
- 14 import java.util.List;
- 15 import java.util.WeakHashMap;
- 16 import sun.misc.ProxyGenerator;
- 17 import sun.reflect.CallerSensitive;
- 18 import sun.reflect.Reflection;
- 19 import sun.reflect.misc.ReflectUtil;
- 20 import sun.security.util.SecurityConstants;
- 21 22
- /**
- 23 * Proxy类提供了用于创建代理对象和实例的静态方法,
- 24 并且它也是所有通过这些静态方法创建出的代理类的父类。
- 25 *
- 26 * 从某个接口创建代理对象的方法如下:
- 27 *
- 28 * InvocationHandler handler = new MyInvocationHandler(...);
- 29 * Class proxyClass = Proxy.getProxyClass(
- 30 * Foo.class.getClassLoader(), new Class[] { Foo.class });
- 31 * Foo f = (Foo) proxyClass.
- 32 * getConstructor(new Class[] { InvocationHandler.class }).
- 33 * newInstance(new Object[] { handler });
- 34 * 或者有更简单的方法
- 35 * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- 36 * new Class[] { Foo.class }, handler);
- 37 *
- 38 * 一个动态代理类(以下简称为代理类)是该类被创建时在运行时动态
- 39 * 实现一系列接口的类,有如下的特性。
- 40 *
- 41 * 动态代理接口是被动态类实现的接口。
- 42 * 代理实例是代理类一个一个实例。
- 43 *
- 44 * 每个代理实例都和一个实现了InvocationHandler接口的invocation handler对象关联。
- 45 * 通过代理接口进行的代理类实例的方法调用将会被分发给invocation handler实例,同时传递的
- 46 * 参数有代理实例,确定被调用方法的Method对象和Object数组类型的参数。
- 47 *
- 48 *
- 49 * containing the arguments. The invocation handler processes the
- 50 * encoded method invocation as appropriate and the result that it
- 51 * returns will be returned as the result of the method invocation on
- 52 * the proxy instance.
- 53 *
- 54 * A proxy class has the following properties: 55 *
- 56 *
- 57 * Proxy classes are public, final, and not abstract.
- 58 *
- 59 * The unqualified name of a proxy class is unspecified. The space
- 60 * of class names that begin with the string "$Proxy"}
- 61 * should be, however, reserved for proxy classes.
- 62 *
- 63 * A proxy class extends java.lang.reflect.Proxy}.
- 64 *
- 65 * A proxy class implements exactly the interfaces specified at its
- 66 * creation, in the same order.
- 67 *
- 68 * If a proxy class implements a non-public interface, then it will
- 69 * be defined in the same package as that interface. Otherwise, the
- 70 * package of a proxy class is also unspecified. Note that package
- 71 * sealing will not prevent a proxy class from being successfully defined
- 72 * in a particular package at runtime, and neither will classes already
- 73 * defined by the same class loader and the same package with particular
- 74 * signers.
- 75 *
- 76 * Since a proxy class implements all of the interfaces specified at
- 77 * its creation, invoking getInterfaces} on its
- 78 * Class} object will return an array containing the same
- 79 * list of interfaces (in the order specified at its creation), invoking
- 80 * getMethods} on its Class} object will return
- 81 * an array of Method} objects that include all of the
- 82 * methods in those interfaces, and invoking getMethod} will
- 83 * find methods in the proxy interfaces as would be expected.
- 84 *
- 85 * The Proxy#isProxyClass Proxy.isProxyClass} method will
- 86 * return true if it is passed a proxy class-- a class returned by
- 87 * Proxy.getProxyClass} or the class of an object returned by
- 88 * Proxy.newProxyInstance}-- and false otherwise.
- 89 *
- 90 * The java.security.ProtectionDomain} of a proxy class
- 91 * is the same as that of system classes loaded by the bootstrap class
- 92 * loader, such as java.lang.Object}, because the code for a
- 93 * proxy class is generated by trusted system code. This protection
- 94 * domain will typically be granted
- 95 * java.security.AllPermission}.
- 96 *
- 97 * Each proxy class has one public constructor that takes one argument,
- 98 * an implementation of the interface InvocationHandler}, to set
- 99 * the invocation handler for a proxy instance. Rather than having to use
- 100 * the reflection API to access the public constructor, a proxy instance
- 101 * can be also be created by calling the Proxy#newProxyInstance
- 102 * Proxy.newProxyInstance} method, which combines the actions of calling
- 103 * Proxy#getProxyClass Proxy.getProxyClass} with invoking the
- 104 * constructor with an invocation handler.
- 105 *
- 106 *
- 107 * A proxy instance has the following properties:108 *
- 109 *
- 110 * Given a proxy instance proxy} and one of the
- 111 * interfaces implemented by its proxy class Foo}, the
- 112 * following expression will return true:
- 113 * 114 * proxy instanceof Foo}
- 115 *
- 116 * and the following cast operation will succeed (rather than throwing
- 117 * a ClassCastException}):
- 118 * 119 * (Foo) proxy}
- 120 *
- 121 *
- 122 * Each proxy instance has an associated invocation handler, the one
- 123 * that was passed to its constructor. The static
- 124 * Proxy#getInvocationHandler Proxy.getInvocationHandler} method
- 125 * will return the invocation handler associated with the proxy instance
- 126 * passed as its argument.
- 127 *
- 128 * An interface method invocation on a proxy instance will be
- 129 * encoded and dispatched to the invocation handler's
- 130 * InvocationHandler#invoke invoke} method as described in the
- 131 * documentation for that method.
- 132 *
- 133 * An invocation of the hashCode},
- 134 * equals}, or toString} methods declared in
- 135 * java.lang.Object} on a proxy instance will be encoded and
- 136 * dispatched to the invocation handler's invoke} method in
- 137 * the same manner as interface method invocations are encoded and
- 138 * dispatched, as described above. The declaring class of the
- 139 * Method} object passed to invoke} will be
- 140 * java.lang.Object}. Other public methods of a proxy
- 141 * instance inherited from java.lang.Object} are not
- 142 * overridden by a proxy class, so invocations of those methods behave
- 143 * like they do for instances of java.lang.Object}.
- 144 *
- 145 *
- 146 * Methods Duplicated in Multiple Proxy Interfaces
- 147 *
- 148 * When two or more interfaces of a proxy class contain a method with149 * the same name and parameter signature, the order of the proxy class's
- 150 * interfaces becomes significant. When such a duplicate method
- 151 * is invoked on a proxy instance, the Method} object passed
- 152 * to the invocation handler will not necessarily be the one whose
- 153 * declaring class is assignable from the reference type of the interface
- 154 * that the proxy's method was invoked through. This limitation exists
- 155 * because the corresponding method implementation in the generated proxy
- 156 * class cannot determine which interface it was invoked through.
- 157 * Therefore, when a duplicate method is invoked on a proxy instance,
- 158 * the Method} object for the method in the foremost interface
- 159 * that contains the method (either directly or inherited through a
- 160 * superinterface) in the proxy class's list of interfaces is passed to
- 161 * the invocation handler's invoke} method, regardless of the
- 162 * reference type through which the method invocation occurred.
- 163 *
- 164 * If a proxy interface contains a method with the same name and165 * parameter signature as the hashCode}, equals},
- 166 * or toString} methods of java.lang.Object},
- 167 * when such a method is invoked on a proxy instance, the
- 168 * Method} object passed to the invocation handler will have
- 169 * java.lang.Object} as its declaring class. In other words,
- 170 * the public, non-final methods of java.lang.Object}
- 171 * logically precede all of the proxy interfaces for the determination of
- 172 * which Method} object to pass to the invocation handler.
- 173 *
- 174 * Note also that when a duplicate method is dispatched to an175 * invocation handler, the invoke} method may only throw
- 176 * checked exception types that are assignable to one of the exception
- 177 * types in the throws} clause of the method in all of
- 178 * the proxy interfaces that it can be invoked through. If the
- 179 * invoke} method throws a checked exception that is not
- 180 * assignable to any of the exception types declared by the method in one
- 181 * of the proxy interfaces that it can be invoked through, then an
- 182 * unchecked UndeclaredThrowableException} will be thrown by
- 183 * the invocation on the proxy instance. This restriction means that not
- 184 * all of the exception types returned by invoking
- 185 * getExceptionTypes} on the Method} object
- 186 * passed to the invoke} method can necessarily be thrown
- 187 * successfully by the invoke} method.
- 188 *
- 189 * @author Peter Jones
- 190 * @see InvocationHandler
- 191 * @since 1.3
- 192 */
- 193 194 // 代理对象是可以序列化的
- 195 public class Proxy implements java.io.Serializable {
- 196 197 private static final long serialVersionUID = -2222568056686623797L;
- 198 199
- /** 为所有代理类的类名添加前缀,难怪hibernate中很多类都有$Proxy */
- 200 private final static String proxyClassNamePrefix = "$Proxy";
- 201 202
- /** 代理类构造方法的参数类型 */
- 203 private final static Class[] constructorParams = 204 {
- InvocationHandler.class
- };
- 205 206
- /** 将代理类的类加载器放在Proxy的maps结构中缓存起来 */
- 207
- /** 为啥这里用了WeakHashMap() */
- 208 private static Map,
- Object >> loaderToCache 209 = new WeakHashMap < >();
- 210 211
- /** 用于标记正在生成的代理类 */
- 212 private static Object pendingGenerationMarker = new Object();
- 213 214
- /** 下一个用于生成唯一代理类名字的数字 */
- 215 private static long nextUniqueNumber = 0;
- 216 private static Object nextUniqueNumberLock = new Object();
- 217 218
- /** 所有代理类的集合,用于isProxyClass方法的实现 */
- 219 private static Map,
- Void > proxyClasses = 220 Collections.synchronizedMap(new WeakHashMap, Void > ());
- 221 222
- /**
- 223 * 代理实例的invocationHandler对象,原来放在这儿啊.
- 224 * @serial
- 225 */
- 226 protected InvocationHandler h;
- 227 228
- /**
- 229 * 禁止实例化
- 230 */
- 231 private Proxy() {
- 232
- }
- 233 234
- /**
- 235 * 从一个子类中创建代理类的实例(最典型的是一个动态代理类)
- 236 * 构造方法的参数是用来指定invocation handler
- 237 * 这个方法还是受保护的呢
- 238 */
- 239 protected Proxy(InvocationHandler h) {
- 240 doNewInstanceCheck();
- 241 this.h = h;
- 242
- }
- 243 244
- /**
- 245 * 为什么不注释这个方法?
- 246 * 类名大致意思是代理访问助手?
- 247 * 这还是个静态的内部类
- 248 */
- 249 private static class ProxyAccessHelper {
- 250 // The permission is implementation specific.
- 251 // 权限是指定实现的。
- 252 static final Permission PROXY_PERMISSION = 253 new ReflectPermission("proxyConstructorNewInstance");
- 254 // These system properties are defined to provide a short-term
- 255 // workaround if customers need to disable the new security checks.
- 256 // 这些系统配置被定义用来提供短期的配置,如果用户需要禁止新的安全检查。
- 257 static final boolean allowNewInstance;
- 258 static final boolean allowNullLoader;
- 259 static {
- 260 allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance");
- 261 allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader");
- 262
- }
- 263 264 // 方法参数还可以这样修饰final?
- 265 private static boolean getBooleanProperty(final String key) {
- 266 String s = AccessController.doPrivileged(new PrivilegedAction() {
- 267 public String run() {
- 268
- return System.getProperty(key);
- 269
- }
- 270
- });
- 271
- return Boolean.valueOf(s);
- 272
- }
- 273 274 // 需要进行创建新实例的检查么
- 275 static boolean needsNewInstanceCheck(Class proxyClass) {
- 276
- if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) {
- 277
- return false;
- 278
- }
- 279 280
- if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
- 281
- for (Class intf: proxyClass.getInterfaces()) {
- 282
- if (!Modifier.isPublic(intf.getModifiers())) {
- 283
- return true;
- 284
- }
- 285
- }
- 286
- }
- 287
- return false;
- 288
- }
- 289
- }
- 290 291
- /*
- 292 * Access check on a proxy class that implements any non-public interface.
- 293 *
- 294 * @throws SecurityException if a security manager exists, and
- 295 * the caller does not have the permission.
- 296 */
- 297 private void doNewInstanceCheck() {
- 298 SecurityManager sm = System.getSecurityManager();
- 299 Class proxyClass = this.getClass();
- 300
- if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) {
- 301
- try {
- 302 sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION);
- 303
- } catch(SecurityException e) {
- 304
- throw new SecurityException("Not allowed to construct a Proxy "305 + "instance that implements a non-public interface", e);
- 306
- }
- 307
- }
- 308
- }
- 309 310
- /**
- 311 * 这个方法是重头了
- 312 * 从给定的类加载器和接口数组返回动态代理类的Class对象。
- 313 * Returns the java.lang.Class} object for a proxy class
- 314 * given a class loader and an array of interfaces.
- 315 * 代理将会通过指定的类加载器所定义而且将会实现所提供的所有的接口。
- 316 *
- 317 * 如果已经有实现了相同接口的代理类存在,那么将会直接放回已经存在的代理类;
- 318 * 否则,将会动态地创建和由类加载器定义的代理类被返回。
- 319
- 320 * 对于传递给Proxy.getProxyClass方法的参数有若干限制。
- 321 *
- 322 * 在数组中所有的类类型必须是接口,不是其他的类类型或者原始类型。
- 323 * 接口数组中的接口必须两两不同
- 324 * 所有的接口类型都可以通过指定的类加载器按名字进行加载。
- 325 * 也就是对于数组中的每个接口i如下判断必须为true
- 326 * Class.forName(i.getName(), false, cl) == i
- 327 *
- 328 * 所有非公开的接口都必须在相同的包里面;不然的话,代理类不可能实现所有的接口,
- 329 * 不论它是在哪个包里面定义的。
- 330 *
- 331 * 对于指定接口的成员方法的集合的中的方法必须有相同的签名。
- 332 *
- 333 * 如果任何方法的返回类型是原始类型或者为空,那么所有的的方法都必须有相同的返回类型。
- 334 *
- 335 * 不然,其中一个方法必须可以对其他方法的返回类型是可赋值的。
- 336 *
- 337 * 生成的代理类不能超过虚拟机对其中的类的限制。例如,虚拟机会限制一个类的接口个数不超过65535;
- 338 * 因此传进去的接口的数组的长度不能超过65535
- 339 *
- 340 * 如果以上约束有违反的话,将会抛出IllegalArgumentException异常。
- 341 * 如果有接口是null的话,就会报NullPointerException异常。
- 342 *
- 343 * 注意到特定的代理接口的顺序是有意义的:对于创建具有相同代理接口的不同顺序的请求生成的代理类是不同的两个
- 344 * 代理类。(卧槽,这个也有影响,不读下源码一脸懵逼)
- 345 */
- 346@CallerSensitive 347 public static Class getProxyClass(ClassLoader loader, 348 Class...interfaces) 349 throws IllegalArgumentException 350 {
- 351 // 安全管理
- 352 SecurityManager sm = System.getSecurityManager();
- 353
- if (sm != null) {
- 354 checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
- 355
- }
- 356 357 // 返回代理对象
- 358
- return getProxyClass0(loader, interfaces);
- 359
- }
- 360 361
- /*
- 362 * Check permissions required to create a Proxy class.
- 363 *
- 364 * To define a proxy class, it performs the access checks as in
- 365 * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
- 366 * 1. "getClassLoader" permission check if loader == null
- 367 * 2. checkPackageAccess on the interfaces it implements
- 368 *
- 369 * To get a constructor and new instance of a proxy class, it performs
- 370 * the package access check on the interfaces it implements
- 371 * as in Class.getConstructor.
- 372 *
- 373 * If an interface is non-public, the proxy class must be defined by
- 374 * the defining loader of the interface. If the caller's class loader
- 375 * is not the same as the defining loader of the interface, the VM
- 376 * will throw IllegalAccessError when the generated proxy class is
- 377 * being defined via the defineClass0 method.
- 378 */
- 379 private static void checkProxyAccess(Class caller, 380 ClassLoader loader, 381 Class...interfaces) 382 {
- 383 SecurityManager sm = System.getSecurityManager();
- 384
- if (sm != null) {
- 385 ClassLoader ccl = caller.getClassLoader();
- 386
- if (loader == null && ccl != null) {
- 387
- if (!ProxyAccessHelper.allowNullLoader) {
- 388 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
- 389
- }
- 390
- }
- 391 ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
- 392
- }
- 393
- }
- 394 395
- /**
- 396 * Generate a proxy class. Must call the checkProxyAccess method
- 397 * to perform permission checks before calling this.
- 398 */
- 399 private static Class getProxyClass0(ClassLoader loader, 400 Class...interfaces) {
- 401 402 // 判断接口的个数
- 403
- if (interfaces.length > 65535) {
- 404
- throw new IllegalArgumentException("interface limit exceeded");
- 405
- }
- 406 407 // 代理类
- 408 Class proxyClass = null;
- 409 410
- /* 接口名称的集合用来作为代理类的缓存 */
- 411 String[] interfaceNames = new String[interfaces.length];
- 412 413 // 检查接口是否有重复的
- 414 Set > interfaceSet = new HashSet < >();
- 415 416
- for (int i = 0; i < interfaces.length; i++) {
- 417
- /*
- 418 * 验证类加载器对接口名称的解析是同一个对象
- 419 * 因为不同类加载加载的类是不同的
- 420 */
- 421 422 // 获取接口的名字
- 423 String interfaceName = interfaces[i].getName();
- 424 Class interfaceClass = null;
- 425
- try {
- 426 // 拿到接口的类类型
- 427 interfaceClass = Class.forName(interfaceName, false, loader);
- 428
- } catch(ClassNotFoundException e) {
- 429
- }
- 430 431 // 两个类类型之间的比较
- 432
- if (interfaceClass != interfaces[i]) {
- 433
- throw new IllegalArgumentException(434 interfaces[i] + " is not visible from class loader");
- 435
- }
- 436 437
- /*
- 438 * Verify that the Class object actually represents an
- 439 * interface.
- 440 */
- 441
- if (!interfaceClass.isInterface()) {
- 442
- throw new IllegalArgumentException(443 interfaceClass.getName() + " is not an interface");
- 444
- }
- 445 446
- /*
- 447 * Verify that this interface is not a duplicate.
- 448 */
- 449
- if (interfaceSet.contains(interfaceClass)) {
- 450
- throw new IllegalArgumentException(451 "repeated interface: " + interfaceClass.getName());
- 452
- }
- 453 454 // 将接口加入到集合中
- 455 interfaceSet.add(interfaceClass);
- 456 457 interfaceNames[i] = interfaceName;
- 458
- }
- 459 460
- /*
- 461 * 使用字符串代表代理接口作为代理类缓存的主键(而不是它们的类对象)
- 462 * 已经足够了因为我们要求代理接口必须能根据给定的类加载器通过名字被解析,
- 463 * 而且还有一个好处是,使用字符串代表类弥补了对类的隐式弱引用。
- 464 */
- 465 466 // 将数组转为字符串
- 467 List key = Arrays.asList(interfaceNames);
- 468 469
- /*
- 470 * 根据类加载器找到或者创建代理类的缓存.
- 471 */
- 472 Map,
- Object > cache;
- 473 synchronized(loaderToCache) {
- 474 cache = loaderToCache.get(loader);
- 475
- if (cache == null) {
- 476 cache = new HashMap < >();
- 477 loaderToCache.put(loader, cache);
- 478
- }
- 479
- /*
- 480 * 这个映射在这个方法执行时一直有效,不用过多的同步,
- 481 * 因为仅仅会在类加载器不可达的时候被移除。
- 482 */
- 483
- }
- 484 485
- /*
- 486 * Look up the list of interfaces in the proxy class cache using
- 487 * the key. This lookup will result in one of three possible
- 488 * kinds of values:
- 489 * null, if there is currently no proxy class for the list of
- 490 * interfaces in the class loader,
- 491 * the pendingGenerationMarker object, if a proxy class for the
- 492 * list of interfaces is currently being generated,
- 493 * or a weak reference to a Class object, if a proxy class for
- 494 * the list of interfaces has already been generated.
- 495 */
- 496 synchronized(cache) {
- 497
- /*
- 498 * Note that we need not worry about reaping the cache for
- 499 * entries with cleared weak references because if a proxy class
- 500 * has been garbage collected, its class loader will have been
- 501 * garbage collected as well, so the entire cache will be reaped
- 502 * from the loaderToCache map.
- 503 */
- 504 do {
- 505 Object value = cache.get(key);
- 506
- if (value instanceof Reference) {
- 507 proxyClass = (Class)((Reference) value).get();
- 508
- }
- 509
- if (proxyClass != null) {
- 510 // proxy class already generated: return it
- 511
- return proxyClass;
- 512
- } else if (value == pendingGenerationMarker) {
- 513 // proxy class being generated: wait for it
- 514
- try {
- 515 cache.wait();
- 516
- } catch(InterruptedException e) {
- 517
- /*
- 518 * The class generation that we are waiting for should
- 519 * take a small, bounded time, so we can safely ignore
- 520 * thread interrupts here.
- 521 */
- 522
- }
- 523
- continue;
- 524
- } else {
- 525
- /*
- 526 * No proxy class for this list of interfaces has been
- 527 * generated or is being generated, so we will go and
- 528 * generate it now. Mark it as pending generation.
- 529 */
- 530 cache.put(key, pendingGenerationMarker);
- 531
- break;
- 532
- }
- 533
- } while ( true );
- 534
- }
- 535 536
- try {
- 537 String proxyPkg = null; // package to define proxy class in
- 538 539
- /*
- 540 * Record the package of a non-public proxy interface so that the
- 541 * proxy class will be defined in the same package. Verify that
- 542 * all non-public proxy interfaces are in the same package.
- 543 */
- 544
- for (int i = 0; i < interfaces.length; i++) {
- 545 int flags = interfaces[i].getModifiers();
- 546
- if (!Modifier.isPublic(flags)) {
- 547 String name = interfaces[i].getName();
- 548 int n = name.lastIndexOf('.');
- 549 String pkg = ((n == -1) ? "": name.substring(0, n + 1));
- 550
- if (proxyPkg == null) {
- 551 proxyPkg = pkg;
- 552
- } else if (!pkg.equals(proxyPkg)) {
- 553
- throw new IllegalArgumentException(554 "non-public interfaces from different packages");
- 555
- }
- 556
- }
- 557
- }
- 558 559
- if (proxyPkg == null) {
- 560 // if no non-public proxy interfaces, use com.sun.proxy package
- 561 proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
- 562
- }
- 563 564 {
- 565
- /*
- 566 * Choose a name for the proxy class to generate.
- 567 */
- 568 long num;
- 569 synchronized(nextUniqueNumberLock) {
- 570 num = nextUniqueNumber++;
- 571
- }
- 572 String proxyName = proxyPkg + proxyClassNamePrefix + num;
- 573
- /*
- 574 * Verify that the class loader hasn't already
- 575 * defined a class with the chosen name.
- 576 */
- 577 578
- /*
- 579 * 生成指定的代理类,可以看出这里的是二进制类型
- 580 * ProxyGenerator的源码看不到了
- 581 */
- 582 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(583 proxyName, interfaces);
- 584
- try {
- 585 // defineClass0是一个本地方法
- 586 proxyClass = defineClass0(loader, proxyName, 587 proxyClassFile, 0, proxyClassFile.length);
- 588
- } catch(ClassFormatError e) {
- 589
- /*
- 590 * A ClassFormatError here means that (barring bugs in the
- 591 * proxy class generation code) there was some other
- 592 * invalid aspect of the arguments supplied to the proxy
- 593 * class creation (such as virtual machine limitations
- 594 * exceeded).
- 595 */
- 596
- throw new IllegalArgumentException(e.toString());
- 597
- }
- 598
- }
- 599 // 将其加入到所有生成的代理类的集合中,用于判断是否是代理类.
- 600 proxyClasses.put(proxyClass, null);
- 601 602
- } finally {
- 603
- /*
- 604 * We must clean up the "pending generation" state of the proxy
- 605 * class cache entry somehow. If a proxy class was successfully
- 606 * generated, store it in the cache (with a weak reference);
- 607 * otherwise, remove the reserved entry. In all cases, notify
- 608 * all waiters on reserved entries in this cache.
- 609 */
- 610 synchronized(cache) {
- 611
- if (proxyClass != null) {
- 612 cache.put(key, new WeakReference > (proxyClass));
- 613
- } else {
- 614 cache.remove(key);
- 615
- }
- 616 cache.notifyAll();
- 617
- }
- 618
- }
- 619 620 // 返回代理类
- 621
- return proxyClass;
- 622
- }
- 623 624@CallerSensitive 625 public static Object newProxyInstance(ClassLoader loader, 626 Class[] interfaces, 627 InvocationHandler h) 628 throws IllegalArgumentException 629 {
- 630
- if (h == null) {
- 631
- throw new NullPointerException();
- 632
- }
- 633 634 // 安全检查
- 635 final SecurityManager sm = System.getSecurityManager();
- 636
- if (sm != null) {
- 637 checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
- 638
- }
- 639 640
- /*
- 641 * 查找或者生成指定的代理类
- 642 */
- 643 Class cl = getProxyClass0(loader, interfaces);
- 644 645
- /*
- 646 * 调用指定了invocation handler的构造方法。
- 647 */
- 648
- try {
- 649 final Constructor cons = cl.getConstructor(constructorParams);
- 650 final InvocationHandler ih = h;
- 651
- if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
- 652 // create proxy instance with doPrivilege as the proxy class may
- 653 // implement non-public interfaces that requires a special permission
- 654
- return AccessController.doPrivileged(new PrivilegedAction() {
- 655 public Object run() {
- 656
- return newInstance(cons, ih);
- 657
- }
- 658
- });
- 659
- } else {
- 660 // 直接返回了代理对象
- 661
- return newInstance(cons, ih);
- 662
- }
- 663
- } catch(NoSuchMethodException e) {
- 664
- throw new InternalError(e.toString());
- 665
- }
- 666
- }
- 667 668 private static Object newInstance(Constructor cons, InvocationHandler h) {
- 669
- try {
- 670
- return cons.newInstance(new Object[] {
- h
- });
- 671
- } catch(IllegalAccessException | InstantiationException e) {
- 672
- throw new InternalError(e.toString());
- 673
- } catch(InvocationTargetException e) {
- 674 Throwable t = e.getCause();
- 675
- if (t instanceof RuntimeException) {
- 676
- throw (RuntimeException) t;
- 677
- } else {
- 678
- throw new InternalError(t.toString());
- 679
- }
- 680
- }
- 681
- }
- 682 683
- /**
- 684 * Returns true if and only if the specified class was dynamically
- 685 * generated to be a proxy class using the getProxyClass}
- 686 * method or the newProxyInstance} method.
- 687 *
- 688 * The reliability of this method is important for the ability689 * to use it to make security decisions, so its implementation should
- 690 * not just test if the class in question extends Proxy}.
- 691 *
- 692 * @param cl the class to test
- 693 * @return true} if the class is a proxy class and
- 694 * false} otherwise
- 695 * @throws NullPointerException if cl} is null}
- 696 */
- 697 public static boolean isProxyClass(Class cl) {
- 698
- if (cl == null) {
- 699
- throw new NullPointerException();
- 700
- }
- 701 702
- return proxyClasses.containsKey(cl);
- 703
- }
- 704 705
- /**
- 706 * Returns the invocation handler for the specified proxy instance.
- 707 *
- 708 * @param proxy the proxy instance to return the invocation handler for
- 709 * @return the invocation handler for the proxy instance
- 710 * @throws IllegalArgumentException if the argument is not a
- 711 * proxy instance
- 712 */
- 713@CallerSensitive 714 public static InvocationHandler getInvocationHandler(Object proxy) 715 throws IllegalArgumentException 716 {
- 717
- /*
- 718 * Verify that the object is actually a proxy instance.
- 719 */
- 720
- if (!isProxyClass(proxy.getClass())) {
- 721
- throw new IllegalArgumentException("not a proxy instance");
- 722
- }
- 723 724 final Proxy p = (Proxy) proxy;
- 725 final InvocationHandler ih = p.h;
- 726
- if (System.getSecurityManager() != null) {
- 727 Class ihClass = ih.getClass();
- 728 Class caller = Reflection.getCallerClass();
- 729
- if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), 730 ihClass.getClassLoader())) 731 {
- 732 ReflectUtil.checkPackageAccess(ihClass);
- 733
- }
- 734
- }
- 735 736
- return ih;
- 737
- }
- 738 739 private static native Class defineClass0(ClassLoader loader, String name, 740 byte[] b, int off, int len);
- 741
- }
来源: http://www.bubuko.com/infodetail-1991897.html