81 // For sharing of MethodAccessors. This branching structure is |
81 // For sharing of MethodAccessors. This branching structure is |
82 // currently only two levels deep (i.e., one root Method and |
82 // currently only two levels deep (i.e., one root Method and |
83 // potentially many Method objects pointing to it.) |
83 // potentially many Method objects pointing to it.) |
84 private Method root; |
84 private Method root; |
85 |
85 |
86 // More complicated security check cache needed here than for |
|
87 // Class.newInstance() and Constructor.newInstance() |
|
88 private Class<?> securityCheckCache; |
|
89 private Class<?> securityCheckTargetClassCache; |
|
90 |
|
91 // Generics infrastructure |
86 // Generics infrastructure |
92 |
87 |
93 private String getGenericSignature() {return signature;} |
88 private String getGenericSignature() {return signature;} |
94 |
89 |
95 // Accessor for factory |
90 // Accessor for factory |
400 * {@code abstract}, {@code static}, {@code final}, |
395 * {@code abstract}, {@code static}, {@code final}, |
401 * {@code synchronized}, {@code native}, {@code strictfp}. |
396 * {@code synchronized}, {@code native}, {@code strictfp}. |
402 */ |
397 */ |
403 public String toString() { |
398 public String toString() { |
404 try { |
399 try { |
405 StringBuffer sb = new StringBuffer(); |
400 StringBuilder sb = new StringBuilder(); |
406 int mod = getModifiers() & Modifier.methodModifiers(); |
401 int mod = getModifiers() & Modifier.methodModifiers(); |
407 if (mod != 0) { |
402 if (mod != 0) { |
408 sb.append(Modifier.toString(mod) + " "); |
403 sb.append(Modifier.toString(mod)).append(' '); |
409 } |
404 } |
410 sb.append(Field.getTypeName(getReturnType()) + " "); |
405 sb.append(Field.getTypeName(getReturnType())).append(' '); |
411 sb.append(Field.getTypeName(getDeclaringClass()) + "."); |
406 sb.append(Field.getTypeName(getDeclaringClass())).append('.'); |
412 sb.append(getName() + "("); |
407 sb.append(getName()).append('('); |
413 Class<?>[] params = parameterTypes; // avoid clone |
408 Class<?>[] params = parameterTypes; // avoid clone |
414 for (int j = 0; j < params.length; j++) { |
409 for (int j = 0; j < params.length; j++) { |
415 sb.append(Field.getTypeName(params[j])); |
410 sb.append(Field.getTypeName(params[j])); |
416 if (j < (params.length - 1)) |
411 if (j < (params.length - 1)) |
417 sb.append(","); |
412 sb.append(','); |
418 } |
413 } |
419 sb.append(")"); |
414 sb.append(')'); |
420 Class<?>[] exceptions = exceptionTypes; // avoid clone |
415 Class<?>[] exceptions = exceptionTypes; // avoid clone |
421 if (exceptions.length > 0) { |
416 if (exceptions.length > 0) { |
422 sb.append(" throws "); |
417 sb.append(" throws "); |
423 for (int k = 0; k < exceptions.length; k++) { |
418 for (int k = 0; k < exceptions.length; k++) { |
424 sb.append(exceptions[k].getName()); |
419 sb.append(exceptions[k].getName()); |
425 if (k < (exceptions.length - 1)) |
420 if (k < (exceptions.length - 1)) |
426 sb.append(","); |
421 sb.append(','); |
427 } |
422 } |
428 } |
423 } |
429 return sb.toString(); |
424 return sb.toString(); |
430 } catch (Exception e) { |
425 } catch (Exception e) { |
431 return "<" + e + ">"; |
426 return "<" + e + ">"; |
473 public String toGenericString() { |
468 public String toGenericString() { |
474 try { |
469 try { |
475 StringBuilder sb = new StringBuilder(); |
470 StringBuilder sb = new StringBuilder(); |
476 int mod = getModifiers() & Modifier.methodModifiers(); |
471 int mod = getModifiers() & Modifier.methodModifiers(); |
477 if (mod != 0) { |
472 if (mod != 0) { |
478 sb.append(Modifier.toString(mod) + " "); |
473 sb.append(Modifier.toString(mod)).append(' '); |
479 } |
474 } |
480 TypeVariable<?>[] typeparms = getTypeParameters(); |
475 TypeVariable<?>[] typeparms = getTypeParameters(); |
481 if (typeparms.length > 0) { |
476 if (typeparms.length > 0) { |
482 boolean first = true; |
477 boolean first = true; |
483 sb.append("<"); |
478 sb.append('<'); |
484 for(TypeVariable<?> typeparm: typeparms) { |
479 for(TypeVariable<?> typeparm: typeparms) { |
485 if (!first) |
480 if (!first) |
486 sb.append(","); |
481 sb.append(','); |
487 // Class objects can't occur here; no need to test |
482 // Class objects can't occur here; no need to test |
488 // and call Class.getName(). |
483 // and call Class.getName(). |
489 sb.append(typeparm.toString()); |
484 sb.append(typeparm.toString()); |
490 first = false; |
485 first = false; |
491 } |
486 } |
492 sb.append("> "); |
487 sb.append("> "); |
493 } |
488 } |
494 |
489 |
495 Type genRetType = getGenericReturnType(); |
490 Type genRetType = getGenericReturnType(); |
496 sb.append( ((genRetType instanceof Class<?>)? |
491 sb.append( ((genRetType instanceof Class<?>)? |
497 Field.getTypeName((Class<?>)genRetType):genRetType.toString()) + " "); |
492 Field.getTypeName((Class<?>)genRetType):genRetType.toString())) |
498 |
493 .append(' '); |
499 sb.append(Field.getTypeName(getDeclaringClass()) + "."); |
494 |
500 sb.append(getName() + "("); |
495 sb.append(Field.getTypeName(getDeclaringClass())).append('.'); |
|
496 sb.append(getName()).append('('); |
501 Type[] params = getGenericParameterTypes(); |
497 Type[] params = getGenericParameterTypes(); |
502 for (int j = 0; j < params.length; j++) { |
498 for (int j = 0; j < params.length; j++) { |
503 String param = (params[j] instanceof Class)? |
499 String param = (params[j] instanceof Class)? |
504 Field.getTypeName((Class)params[j]): |
500 Field.getTypeName((Class)params[j]): |
505 (params[j].toString()); |
501 (params[j].toString()); |
506 if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... |
502 if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... |
507 param = param.replaceFirst("\\[\\]$", "..."); |
503 param = param.replaceFirst("\\[\\]$", "..."); |
508 sb.append(param); |
504 sb.append(param); |
509 if (j < (params.length - 1)) |
505 if (j < (params.length - 1)) |
510 sb.append(","); |
506 sb.append(','); |
511 } |
507 } |
512 sb.append(")"); |
508 sb.append(')'); |
513 Type[] exceptions = getGenericExceptionTypes(); |
509 Type[] exceptions = getGenericExceptionTypes(); |
514 if (exceptions.length > 0) { |
510 if (exceptions.length > 0) { |
515 sb.append(" throws "); |
511 sb.append(" throws "); |
516 for (int k = 0; k < exceptions.length; k++) { |
512 for (int k = 0; k < exceptions.length; k++) { |
517 sb.append((exceptions[k] instanceof Class)? |
513 sb.append((exceptions[k] instanceof Class)? |
518 ((Class)exceptions[k]).getName(): |
514 ((Class)exceptions[k]).getName(): |
519 exceptions[k].toString()); |
515 exceptions[k].toString()); |
520 if (k < (exceptions.length - 1)) |
516 if (k < (exceptions.length - 1)) |
521 sb.append(","); |
517 sb.append(','); |
522 } |
518 } |
523 } |
519 } |
524 return sb.toString(); |
520 return sb.toString(); |
525 } catch (Exception e) { |
521 } catch (Exception e) { |
526 return "<" + e + ">"; |
522 return "<" + e + ">"; |
589 InvocationTargetException |
585 InvocationTargetException |
590 { |
586 { |
591 if (!override) { |
587 if (!override) { |
592 if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { |
588 if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { |
593 Class<?> caller = Reflection.getCallerClass(1); |
589 Class<?> caller = Reflection.getCallerClass(1); |
594 Class<?> targetClass = ((obj == null || !Modifier.isProtected(modifiers)) |
590 |
595 ? clazz |
591 checkAccess(caller, clazz, obj, modifiers); |
596 : obj.getClass()); |
592 } |
597 |
593 } |
598 boolean cached; |
594 MethodAccessor ma = methodAccessor; // read volatile |
599 synchronized (this) { |
595 if (ma == null) { |
600 cached = (securityCheckCache == caller) |
596 ma = acquireMethodAccessor(); |
601 && (securityCheckTargetClassCache == targetClass); |
597 } |
602 } |
598 return ma.invoke(obj, args); |
603 if (!cached) { |
|
604 Reflection.ensureMemberAccess(caller, clazz, obj, modifiers); |
|
605 synchronized (this) { |
|
606 securityCheckCache = caller; |
|
607 securityCheckTargetClassCache = targetClass; |
|
608 } |
|
609 } |
|
610 } |
|
611 } |
|
612 if (methodAccessor == null) acquireMethodAccessor(); |
|
613 return methodAccessor.invoke(obj, args); |
|
614 } |
599 } |
615 |
600 |
616 /** |
601 /** |
617 * Returns {@code true} if this method is a bridge |
602 * Returns {@code true} if this method is a bridge |
618 * method; returns {@code false} otherwise. |
603 * method; returns {@code false} otherwise. |
652 |
637 |
653 // NOTE that there is no synchronization used here. It is correct |
638 // NOTE that there is no synchronization used here. It is correct |
654 // (though not efficient) to generate more than one MethodAccessor |
639 // (though not efficient) to generate more than one MethodAccessor |
655 // for a given Method. However, avoiding synchronization will |
640 // for a given Method. However, avoiding synchronization will |
656 // probably make the implementation more scalable. |
641 // probably make the implementation more scalable. |
657 private void acquireMethodAccessor() { |
642 private MethodAccessor acquireMethodAccessor() { |
658 // First check to see if one has been created yet, and take it |
643 // First check to see if one has been created yet, and take it |
659 // if so |
644 // if so |
660 MethodAccessor tmp = null; |
645 MethodAccessor tmp = null; |
661 if (root != null) tmp = root.getMethodAccessor(); |
646 if (root != null) tmp = root.getMethodAccessor(); |
662 if (tmp != null) { |
647 if (tmp != null) { |
663 methodAccessor = tmp; |
648 methodAccessor = tmp; |
664 return; |
649 } else { |
665 } |
650 // Otherwise fabricate one and propagate it up to the root |
666 // Otherwise fabricate one and propagate it up to the root |
651 tmp = reflectionFactory.newMethodAccessor(this); |
667 tmp = reflectionFactory.newMethodAccessor(this); |
652 setMethodAccessor(tmp); |
668 setMethodAccessor(tmp); |
653 } |
|
654 |
|
655 return tmp; |
669 } |
656 } |
670 |
657 |
671 // Returns MethodAccessor for this Method object, not looking up |
658 // Returns MethodAccessor for this Method object, not looking up |
672 // the chain to the root |
659 // the chain to the root |
673 MethodAccessor getMethodAccessor() { |
660 MethodAccessor getMethodAccessor() { |