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