1 7 8 package java.lang.reflect; 9 10 import java.lang.ref.Reference ; 11 import java.lang.ref.WeakReference ; 12 import java.util.Arrays ; 13 import java.util.Collections ; 14 import java.util.HashMap ; 15 import java.util.HashSet ; 16 import java.util.Map ; 17 import java.util.Set ; 18 import java.util.WeakHashMap ; 19 import sun.misc.ProxyGenerator; 20 21 204 public class Proxy implements java.io.Serializable { 205 206 private static final long serialVersionUID = -2222568056686623797L; 207 208 209 private final static String proxyClassNamePrefix = "$Proxy"; 210 211 212 private final static Class [] constructorParams = 213 { InvocationHandler .class }; 214 215 216 private static Map loaderToCache = new WeakHashMap (); 217 218 219 private static Object pendingGenerationMarker = new Object (); 220 221 222 private static long nextUniqueNumber = 0; 223 private static Object nextUniqueNumberLock = new Object (); 224 225 226 private static Map proxyClasses = 227 Collections.synchronizedMap(new WeakHashMap ()); 228 229 233 protected InvocationHandler h; 234 235 238 private Proxy() { 239 } 240 241 248 protected Proxy(InvocationHandler h) { 249 this.h = h; 250 } 251 252 326 public static Class <?> getProxyClass(ClassLoader loader, 327 Class <?>... interfaces) 328 throws IllegalArgumentException 329 { 330 if (interfaces.length > 65535) { 331 throw new IllegalArgumentException ("interface limit exceeded"); 332 } 333 334 Class proxyClass = null; 335 336 337 String [] interfaceNames = new String [interfaces.length]; 338 339 Set interfaceSet = new HashSet (); 341 for (int i = 0; i < interfaces.length; i++) { 342 346 String interfaceName = interfaces[i].getName(); 347 Class interfaceClass = null; 348 try { 349 interfaceClass = Class.forName(interfaceName, false, loader); 350 } catch (ClassNotFoundException e) { 351 } 352 if (interfaceClass != interfaces[i]) { 353 throw new IllegalArgumentException ( 354 interfaces[i] + " is not visible from class loader"); 355 } 356 357 361 if (!interfaceClass.isInterface()) { 362 throw new IllegalArgumentException ( 363 interfaceClass.getName() + " is not an interface"); 364 } 365 366 369 if (interfaceSet.contains(interfaceClass)) { 370 throw new IllegalArgumentException ( 371 "repeated interface: " + interfaceClass.getName()); 372 } 373 interfaceSet.add(interfaceClass); 374 375 interfaceNames[i] = interfaceName; 376 } 377 378 387 Object key = Arrays.asList(interfaceNames); 388 389 392 Map cache; 393 synchronized (loaderToCache) { 394 cache = (Map ) loaderToCache.get(loader); 395 if (cache == null) { 396 cache = new HashMap (); 397 loaderToCache.put(loader, cache); 398 } 399 404 } 405 406 417 synchronized (cache) { 418 425 do { 426 Object value = cache.get(key); 427 if (value instanceof Reference ) { 428 proxyClass = (Class ) ((Reference ) value).get(); 429 } 430 if (proxyClass != null) { 431 return proxyClass; 433 } else if (value == pendingGenerationMarker) { 434 try { 436 cache.wait(); 437 } catch (InterruptedException e) { 438 443 } 444 continue; 445 } else { 446 451 cache.put(key, pendingGenerationMarker); 452 break; 453 } 454 } while (true); 455 } 456 457 try { 458 String proxyPkg = null; 460 465 for (int i = 0; i < interfaces.length; i++) { 466 int flags = interfaces[i].getModifiers(); 467 if (!Modifier.isPublic(flags)) { 468 String name = interfaces[i].getName(); 469 int n = name.lastIndexOf('.'); 470 String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); 471 if (proxyPkg == null) { 472 proxyPkg = pkg; 473 } else if (!pkg.equals(proxyPkg)) { 474 throw new IllegalArgumentException ( 475 "non-public interfaces from different packages"); 476 } 477 } 478 } 479 480 if (proxyPkg == null) { proxyPkg = ""; } 483 484 { 485 488 long num; 489 synchronized (nextUniqueNumberLock) { 490 num = nextUniqueNumber++; 491 } 492 String proxyName = proxyPkg + proxyClassNamePrefix + num; 493 497 498 501 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( 502 proxyName, interfaces); 503 try { 504 proxyClass = defineClass0(loader, proxyName, 505 proxyClassFile, 0, proxyClassFile.length); 506 } catch (ClassFormatError e) { 507 514 throw new IllegalArgumentException (e.toString()); 515 } 516 } 517 proxyClasses.put(proxyClass, null); 519 520 } finally { 521 528 synchronized (cache) { 529 if (proxyClass != null) { 530 cache.put(key, new WeakReference (proxyClass)); 531 } else { 532 cache.remove(key); 533 } 534 cache.notifyAll(); 535 } 536 } 537 return proxyClass; 538 } 539 540 569 public static Object newProxyInstance(ClassLoader loader, 570 Class <?>[] interfaces, 571 InvocationHandler h) 572 throws IllegalArgumentException 573 { 574 if (h == null) { 575 throw new NullPointerException (); 576 } 577 578 581 Class cl = getProxyClass(loader, interfaces); 582 583 586 try { 587 Constructor cons = cl.getConstructor(constructorParams); 588 return (Object ) cons.newInstance(new Object [] { h }); 589 } catch (NoSuchMethodException e) { 590 throw new InternalError (e.toString()); 591 } catch (IllegalAccessException e) { 592 throw new InternalError (e.toString()); 593 } catch (InstantiationException e) { 594 throw new InternalError (e.toString()); 595 } catch (InvocationTargetException e) { 596 throw new InternalError (e.toString()); 597 } 598 } 599 600 614 public static boolean isProxyClass(Class <?> cl) { 615 if (cl == null) { 616 throw new NullPointerException (); 617 } 618 619 return proxyClasses.containsKey(cl); 620 } 621 622 630 public static InvocationHandler getInvocationHandler(Object proxy) 631 throws IllegalArgumentException 632 { 633 636 if (!isProxyClass(proxy.getClass())) { 637 throw new IllegalArgumentException ("not a proxy instance"); 638 } 639 640 Proxy p = (Proxy ) proxy; 641 return p.h; 642 } 643 644 private static native Class defineClass0(ClassLoader loader, String name, 645 byte[] b, int off, int len); 646 } 647 | Popular Tags |