1
25
26 package java.lang.invoke;
27
28 import sun.invoke.util.BytecodeDescriptor;
29 import sun.invoke.util.VerifyAccess;
30
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.Field;
33 import java.lang.reflect.Member;
34 import java.lang.reflect.Method;
35 import java.lang.reflect.Modifier;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Objects;
41
42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
43 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
44 import static java.lang.invoke.MethodHandleStatics.newInternalError;
45
46
73 final class ResolvedMethodName {
74
75
76 };
77
78 final class MemberName implements Member, Cloneable {
79 private Class<?> clazz;
80 private String name;
81 private Object type;
82 private int flags;
83 private ResolvedMethodName method;
84
85 Object resolution;
86
87
90 public Class<?> getDeclaringClass() {
91 return clazz;
92 }
93
94
95 public ClassLoader getClassLoader() {
96 return clazz.getClassLoader();
97 }
98
99
104 public String getName() {
105 if (name == null) {
106 expandFromVM();
107 if (name == null) {
108 return null;
109 }
110 }
111 return name;
112 }
113
114 public MethodType getMethodOrFieldType() {
115 if (isInvocable())
116 return getMethodType();
117 if (isGetter())
118 return MethodType.methodType(getFieldType());
119 if (isSetter())
120 return MethodType.methodType(void.class, getFieldType());
121 throw new InternalError("not a method or field: "+this);
122 }
123
124
127 public MethodType getMethodType() {
128 if (type == null) {
129 expandFromVM();
130 if (type == null) {
131 return null;
132 }
133 }
134 if (!isInvocable()) {
135 throw newIllegalArgumentException("not invocable, no method type");
136 }
137
138 {
139
140 final Object type = this.type;
141 if (type instanceof MethodType) {
142 return (MethodType) type;
143 }
144 }
145
146
147 synchronized (this) {
148 if (type instanceof String) {
149 String sig = (String) type;
150 MethodType res = MethodType.fromDescriptor(sig, getClassLoader());
151 type = res;
152 } else if (type instanceof Object[]) {
153 Object[] typeInfo = (Object[]) type;
154 Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
155 Class<?> rtype = (Class<?>) typeInfo[0];
156 MethodType res = MethodType.makeImpl(rtype, ptypes, true);
157 type = res;
158 }
159
160 assert type instanceof MethodType : "bad method type " + type;
161 }
162 return (MethodType) type;
163 }
164
165
168 String getMethodDescriptor() {
169 if (type == null) {
170 expandFromVM();
171 if (type == null) {
172 return null;
173 }
174 }
175 if (!isInvocable()) {
176 throw newIllegalArgumentException("not invocable, no method type");
177 }
178
179
180 final Object type = this.type;
181 if (type instanceof String) {
182 return (String) type;
183 } else {
184 return getMethodType().toMethodDescriptorString();
185 }
186 }
187
188
192 public MethodType getInvocationType() {
193 MethodType itype = getMethodOrFieldType();
194 if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
195 return itype.changeReturnType(clazz);
196 if (!isStatic())
197 return itype.insertParameterTypes(0, clazz);
198 return itype;
199 }
200
201
202 public Class<?>[] getParameterTypes() {
203 return getMethodType().parameterArray();
204 }
205
206
207 public Class<?> getReturnType() {
208 return getMethodType().returnType();
209 }
210
211
215 public Class<?> getFieldType() {
216 if (type == null) {
217 expandFromVM();
218 if (type == null) {
219 return null;
220 }
221 }
222 if (isInvocable()) {
223 throw newIllegalArgumentException("not a field or nested class, no simple type");
224 }
225
226 {
227
228 final Object type = this.type;
229 if (type instanceof Class<?>) {
230 return (Class<?>) type;
231 }
232 }
233
234
235 synchronized (this) {
236 if (type instanceof String) {
237 String sig = (String) type;
238 MethodType mtype = MethodType.fromDescriptor("()"+sig, getClassLoader());
239 Class<?> res = mtype.returnType();
240 type = res;
241 }
242
243 assert type instanceof Class<?> : "bad field type " + type;
244 }
245 return (Class<?>) type;
246 }
247
248
249 public Object getType() {
250 return (isInvocable() ? getMethodType() : getFieldType());
251 }
252
253
256 public String getSignature() {
257 if (type == null) {
258 expandFromVM();
259 if (type == null) {
260 return null;
261 }
262 }
263 if (isInvocable())
264 return BytecodeDescriptor.unparse(getMethodType());
265 else
266 return BytecodeDescriptor.unparse(getFieldType());
267 }
268
269
272 public int getModifiers() {
273 return (flags & RECOGNIZED_MODIFIERS);
274 }
275
276
278 public byte getReferenceKind() {
279 return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
280 }
281 private boolean referenceKindIsConsistent() {
282 byte refKind = getReferenceKind();
283 if (refKind == REF_NONE) return isType();
284 if (isField()) {
285 assert(staticIsConsistent());
286 assert(MethodHandleNatives.refKindIsField(refKind));
287 } else if (isConstructor()) {
288 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
289 } else if (isMethod()) {
290 assert(staticIsConsistent());
291 assert(MethodHandleNatives.refKindIsMethod(refKind));
292 if (clazz.isInterface())
293 assert(refKind == REF_invokeInterface ||
294 refKind == REF_invokeStatic ||
295 refKind == REF_invokeSpecial ||
296 refKind == REF_invokeVirtual && isObjectPublicMethod());
297 } else {
298 assert(false);
299 }
300 return true;
301 }
302 private boolean isObjectPublicMethod() {
303 if (clazz == Object.class) return true;
304 MethodType mtype = getMethodType();
305 if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
306 return true;
307 if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)
308 return true;
309 if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class)
310 return true;
311 return false;
312 }
313 boolean referenceKindIsConsistentWith(int originalRefKind) {
314 int refKind = getReferenceKind();
315 if (refKind == originalRefKind) return true;
316 switch (originalRefKind) {
317 case REF_invokeInterface:
318
319 assert(refKind == REF_invokeVirtual ||
320 refKind == REF_invokeSpecial) : this;
321 return true;
322 case REF_invokeVirtual:
323 case REF_newInvokeSpecial:
324
325 assert(refKind == REF_invokeSpecial) : this;
326 return true;
327 }
328 assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind);
329 return true;
330 }
331 private boolean staticIsConsistent() {
332 byte refKind = getReferenceKind();
333 return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0;
334 }
335 private boolean vminfoIsConsistent() {
336 byte refKind = getReferenceKind();
337 assert(isResolved());
338 Object vminfo = MethodHandleNatives.getMemberVMInfo(this);
339 assert(vminfo instanceof Object[]);
340 long vmindex = (Long) ((Object[])vminfo)[0];
341 Object vmtarget = ((Object[])vminfo)[1];
342 if (MethodHandleNatives.refKindIsField(refKind)) {
343 assert(vmindex >= 0) : vmindex + ":" + this;
344 assert(vmtarget instanceof Class);
345 } else {
346 if (MethodHandleNatives.refKindDoesDispatch(refKind))
347 assert(vmindex >= 0) : vmindex + ":" + this;
348 else
349 assert(vmindex < 0) : vmindex;
350 assert(vmtarget instanceof MemberName) : vmtarget + " in " + this;
351 }
352 return true;
353 }
354
355 private MemberName changeReferenceKind(byte refKind, byte oldKind) {
356 assert(getReferenceKind() == oldKind);
357 assert(MethodHandleNatives.refKindIsValid(refKind));
358 flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT);
359 return this;
360 }
361
362 private boolean testFlags(int mask, int value) {
363 return (flags & mask) == value;
364 }
365 private boolean testAllFlags(int mask) {
366 return testFlags(mask, mask);
367 }
368 private boolean testAnyFlags(int mask) {
369 return !testFlags(mask, 0);
370 }
371
372
374 public boolean isMethodHandleInvoke() {
375 final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
376 final int negs = Modifier.STATIC;
377 if (testFlags(bits | negs, bits) &&
378 clazz == MethodHandle.class) {
379 return isMethodHandleInvokeName(name);
380 }
381 return false;
382 }
383 public static boolean isMethodHandleInvokeName(String name) {
384 switch (name) {
385 case "invoke":
386 case "invokeExact":
387 return true;
388 default:
389 return false;
390 }
391 }
392 public boolean isVarHandleMethodInvoke() {
393 final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
394 final int negs = Modifier.STATIC;
395 if (testFlags(bits | negs, bits) &&
396 clazz == VarHandle.class) {
397 return isVarHandleMethodInvokeName(name);
398 }
399 return false;
400 }
401 public static boolean isVarHandleMethodInvokeName(String name) {
402 try {
403 VarHandle.AccessMode.valueFromMethodName(name);
404 return true;
405 } catch (IllegalArgumentException e) {
406 return false;
407 }
408 }
409 private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
410
411
412 public boolean isStatic() {
413 return Modifier.isStatic(flags);
414 }
415
416 public boolean isPublic() {
417 return Modifier.isPublic(flags);
418 }
419
420 public boolean isPrivate() {
421 return Modifier.isPrivate(flags);
422 }
423
424 public boolean isProtected() {
425 return Modifier.isProtected(flags);
426 }
427
428 public boolean isFinal() {
429 return Modifier.isFinal(flags);
430 }
431
432 public boolean canBeStaticallyBound() {
433 return Modifier.isFinal(flags | clazz.getModifiers());
434 }
435
436 public boolean isVolatile() {
437 return Modifier.isVolatile(flags);
438 }
439
440 public boolean isAbstract() {
441 return Modifier.isAbstract(flags);
442 }
443
444 public boolean isNative() {
445 return Modifier.isNative(flags);
446 }
447
448
449
450 static final int BRIDGE = 0x00000040;
451 static final int VARARGS = 0x00000080;
452 static final int SYNTHETIC = 0x00001000;
453 static final int ANNOTATION= 0x00002000;
454 static final int ENUM = 0x00004000;
455
456 public boolean isBridge() {
457 return testAllFlags(IS_METHOD | BRIDGE);
458 }
459
460 public boolean isVarargs() {
461 return testAllFlags(VARARGS) && isInvocable();
462 }
463
464 public boolean isSynthetic() {
465 return testAllFlags(SYNTHETIC);
466 }
467
468 static final String CONSTRUCTOR_NAME = "<init>";
469
470
471 static final int RECOGNIZED_MODIFIERS = 0xFFFF;
472
473
474 static final int
475 IS_METHOD = MN_IS_METHOD,
476 IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR,
477 IS_FIELD = MN_IS_FIELD,
478 IS_TYPE = MN_IS_TYPE,
479 CALLER_SENSITIVE = MN_CALLER_SENSITIVE;
480
481 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
482 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
483 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
484 static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
485 static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
486
487
488 public boolean isInvocable() {
489 return testAnyFlags(IS_INVOCABLE);
490 }
491
492 public boolean isFieldOrMethod() {
493 return testAnyFlags(IS_FIELD_OR_METHOD);
494 }
495
496 public boolean isMethod() {
497 return testAllFlags(IS_METHOD);
498 }
499
500 public boolean isConstructor() {
501 return testAllFlags(IS_CONSTRUCTOR);
502 }
503
504 public boolean isField() {
505 return testAllFlags(IS_FIELD);
506 }
507
508 public boolean isType() {
509 return testAllFlags(IS_TYPE);
510 }
511
512 public boolean isPackage() {
513 return !testAnyFlags(ALL_ACCESS);
514 }
515
516 public boolean isCallerSensitive() {
517 return testAllFlags(CALLER_SENSITIVE);
518 }
519
520
521 public boolean isAccessibleFrom(Class<?> lookupClass) {
522 int mode = (ALL_ACCESS|MethodHandles.Lookup.PACKAGE|MethodHandles.Lookup.MODULE);
523 return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
524 lookupClass, mode);
525 }
526
527
530 public boolean refersTo(Class<?> declc, String n) {
531 return clazz == declc && getName().equals(n);
532 }
533
534
535 private void init(Class<?> defClass, String name, Object type, int flags) {
536
537
538
539
540 this.clazz = defClass;
541 this.name = name;
542 this.type = type;
543 this.flags = flags;
544 assert(testAnyFlags(ALL_KINDS));
545 assert(this.resolution == null);
546
547 }
548
549
553 private void expandFromVM() {
554 if (type != null) {
555 return;
556 }
557 if (!isResolved()) {
558 return;
559 }
560 MethodHandleNatives.expand(this);
561 }
562
563
564 private static int flagsMods(int flags, int mods, byte refKind) {
565 assert((flags & RECOGNIZED_MODIFIERS) == 0);
566 assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
567 assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
568 return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
569 }
570
571 public MemberName(Method m) {
572 this(m, false);
573 }
574 @SuppressWarnings("LeakingThisInConstructor")
575 public MemberName(Method m, boolean wantSpecial) {
576 Objects.requireNonNull(m);
577
578 MethodHandleNatives.init(this, m);
579 if (clazz == null) {
580 if (m.getDeclaringClass() == MethodHandle.class &&
581 isMethodHandleInvokeName(m.getName())) {
582
583
584
585 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
586 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
587 init(MethodHandle.class, m.getName(), type, flags);
588 if (isMethodHandleInvoke())
589 return;
590 }
591 if (m.getDeclaringClass() == VarHandle.class &&
592 isVarHandleMethodInvokeName(m.getName())) {
593
594
595
596 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
597 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
598 init(VarHandle.class, m.getName(), type, flags);
599 if (isVarHandleMethodInvoke())
600 return;
601 }
602 throw new LinkageError(m.toString());
603 }
604 assert(isResolved() && this.clazz != null);
605 this.name = m.getName();
606 if (this.type == null)
607 this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
608 if (wantSpecial) {
609 if (isAbstract())
610 throw new AbstractMethodError(this.toString());
611 if (getReferenceKind() == REF_invokeVirtual)
612 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
613 else if (getReferenceKind() == REF_invokeInterface)
614
615 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
616 }
617 }
618 public MemberName asSpecial() {
619 switch (getReferenceKind()) {
620 case REF_invokeSpecial: return this;
621 case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
622 case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
623 case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
624 }
625 throw new IllegalArgumentException(this.toString());
626 }
627
630 public MemberName asConstructor() {
631 switch (getReferenceKind()) {
632 case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
633 case REF_newInvokeSpecial: return this;
634 }
635 throw new IllegalArgumentException(this.toString());
636 }
637
645 public MemberName asNormalOriginal() {
646 byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
647 byte refKind = getReferenceKind();
648 byte newRefKind = refKind;
649 MemberName result = this;
650 switch (refKind) {
651 case REF_invokeInterface:
652 case REF_invokeVirtual:
653 case REF_invokeSpecial:
654 newRefKind = normalVirtual;
655 break;
656 }
657 if (newRefKind == refKind)
658 return this;
659 result = clone().changeReferenceKind(newRefKind, refKind);
660 assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
661 return result;
662 }
663
664 @SuppressWarnings("LeakingThisInConstructor")
665 public MemberName(Constructor<?> ctor) {
666 Objects.requireNonNull(ctor);
667
668 MethodHandleNatives.init(this, ctor);
669 assert(isResolved() && this.clazz != null);
670 this.name = CONSTRUCTOR_NAME;
671 if (this.type == null)
672 this.type = new Object[] { void.class, ctor.getParameterTypes() };
673 }
674
676 public MemberName(Field fld) {
677 this(fld, false);
678 }
679 @SuppressWarnings("LeakingThisInConstructor")
680 public MemberName(Field fld, boolean makeSetter) {
681 Objects.requireNonNull(fld);
682
683 MethodHandleNatives.init(this, fld);
684 assert(isResolved() && this.clazz != null);
685 this.name = fld.getName();
686 this.type = fld.getType();
687 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
688 byte refKind = this.getReferenceKind();
689 assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
690 if (makeSetter) {
691 changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
692 }
693 }
694 public boolean isGetter() {
695 return MethodHandleNatives.refKindIsGetter(getReferenceKind());
696 }
697 public boolean isSetter() {
698 return MethodHandleNatives.refKindIsSetter(getReferenceKind());
699 }
700 public MemberName asSetter() {
701 byte refKind = getReferenceKind();
702 assert(MethodHandleNatives.refKindIsGetter(refKind));
703 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
704 byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
705 return clone().changeReferenceKind(setterRefKind, refKind);
706 }
707
708 public MemberName(Class<?> type) {
709 init(type.getDeclaringClass(), type.getSimpleName(), type,
710 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
711 initResolved(true);
712 }
713
714
720 static MemberName makeMethodHandleInvoke(String name, MethodType type) {
721 return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
722 }
723 static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
724 MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
725 mem.flags |= mods;
726 assert(mem.isMethodHandleInvoke()) : mem;
727 return mem;
728 }
729
730 static MemberName makeVarHandleMethodInvoke(String name, MethodType type) {
731 return makeVarHandleMethodInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
732 }
733 static MemberName makeVarHandleMethodInvoke(String name, MethodType type, int mods) {
734 MemberName mem = new MemberName(VarHandle.class, name, type, REF_invokeVirtual);
735 mem.flags |= mods;
736 assert(mem.isVarHandleMethodInvoke()) : mem;
737 return mem;
738 }
739
740
741 MemberName() { }
742
743
744 @Override protected MemberName clone() {
745 try {
746 return (MemberName) super.clone();
747 } catch (CloneNotSupportedException ex) {
748 throw newInternalError(ex);
749 }
750 }
751
752
755 public MemberName getDefinition() {
756 if (!isResolved()) throw new IllegalStateException("must be resolved: "+this);
757 if (isType()) return this;
758 MemberName res = this.clone();
759 res.clazz = null;
760 res.type = null;
761 res.name = null;
762 res.resolution = res;
763 res.expandFromVM();
764 assert(res.getName().equals(this.getName()));
765 return res;
766 }
767
768 @Override
769 @SuppressWarnings("deprecation")
770 public int hashCode() {
771
772
773 return Objects.hash(clazz, new Byte(getReferenceKind()), name, getType());
774 }
775
776 @Override
777 public boolean equals(Object that) {
778 return (that instanceof MemberName && this.equals((MemberName)that));
779 }
780
781
786 public boolean equals(MemberName that) {
787 if (this == that) return true;
788 if (that == null) return false;
789 return this.clazz == that.clazz
790 && this.getReferenceKind() == that.getReferenceKind()
791 && Objects.equals(this.name, that.name)
792 && Objects.equals(this.getType(), that.getType());
793 }
794
795
796
801 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
802 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
803 initResolved(false);
804 }
805
812 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
813 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
814 init(defClass, name, type, flagsMods(initFlags, 0, refKind));
815 initResolved(false);
816 }
817
820 public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
821 int kindFlags;
822 if (MethodHandleNatives.refKindIsField(refKind)) {
823 kindFlags = IS_FIELD;
824 if (!(type instanceof Class))
825 throw newIllegalArgumentException("not a field type");
826 } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
827 kindFlags = IS_METHOD;
828 if (!(type instanceof MethodType))
829 throw newIllegalArgumentException("not a method type");
830 } else if (refKind == REF_newInvokeSpecial) {
831 kindFlags = IS_CONSTRUCTOR;
832 if (!(type instanceof MethodType) ||
833 !CONSTRUCTOR_NAME.equals(name))
834 throw newIllegalArgumentException("not a constructor type or name");
835 } else {
836 throw newIllegalArgumentException("bad reference kind "+refKind);
837 }
838 init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
839 initResolved(false);
840 }
841
843 public boolean hasReceiverTypeDispatch() {
844 return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
845 }
846
847
852 public boolean isResolved() {
853 return resolution == null;
854 }
855
856 void initResolved(boolean isResolved) {
857 assert(this.resolution == null);
858 if (!isResolved)
859 this.resolution = this;
860 assert(isResolved() == isResolved);
861 }
862
863 void checkForTypeAlias(Class<?> refc) {
864 if (isInvocable()) {
865 MethodType type;
866 if (this.type instanceof MethodType)
867 type = (MethodType) this.type;
868 else
869 this.type = type = getMethodType();
870 if (type.erase() == type) return;
871 if (VerifyAccess.isTypeVisible(type, refc)) return;
872 throw new LinkageError("bad method type alias: "+type+" not visible from "+refc);
873 } else {
874 Class<?> type;
875 if (this.type instanceof Class<?>)
876 type = (Class<?>) this.type;
877 else
878 this.type = type = getFieldType();
879 if (VerifyAccess.isTypeVisible(type, refc)) return;
880 throw new LinkageError("bad field type alias: "+type+" not visible from "+refc);
881 }
882 }
883
884
885
892 @SuppressWarnings("LocalVariableHidesMemberVariable")
893 @Override
894 public String toString() {
895 if (isType())
896 return type.toString();
897
898 StringBuilder buf = new StringBuilder();
899 if (getDeclaringClass() != null) {
900 buf.append(getName(clazz));
901 buf.append('.');
902 }
903 String name = this.name;
904 buf.append(name == null ? "*" : name);
905 Object type = this.type;
906 if (!isInvocable()) {
907 buf.append('/');
908 buf.append(type == null ? "*" : getName(type));
909 } else {
910 buf.append(type == null ? "(*)*" : getName(type));
911 }
912 byte refKind = getReferenceKind();
913 if (refKind != REF_NONE) {
914 buf.append('/');
915 buf.append(MethodHandleNatives.refKindName(refKind));
916 }
917
918 return buf.toString();
919 }
920 private static String getName(Object obj) {
921 if (obj instanceof Class<?>)
922 return ((Class<?>)obj).getName();
923 return String.valueOf(obj);
924 }
925
926 public IllegalAccessException makeAccessException(String message, Object from) {
927 message = message + ": "+ toString();
928 if (from != null) {
929 if (from == MethodHandles.publicLookup()) {
930 message += ", from public Lookup";
931 } else {
932 Module m;
933 if (from instanceof MethodHandles.Lookup) {
934 MethodHandles.Lookup lookup = (MethodHandles.Lookup)from;
935 m = lookup.lookupClass().getModule();
936 } else {
937 m = from.getClass().getModule();
938 }
939 message += ", from " + from + " (" + m + ")";
940 }
941 }
942 return new IllegalAccessException(message);
943 }
944 private String message() {
945 if (isResolved())
946 return "no access";
947 else if (isConstructor())
948 return "no such constructor";
949 else if (isMethod())
950 return "no such method";
951 else
952 return "no such field";
953 }
954 public ReflectiveOperationException makeAccessException() {
955 String message = message() + ": "+ toString();
956 ReflectiveOperationException ex;
957 if (isResolved() || !(resolution instanceof NoSuchMethodError ||
958 resolution instanceof NoSuchFieldError))
959 ex = new IllegalAccessException(message);
960 else if (isConstructor())
961 ex = new NoSuchMethodException(message);
962 else if (isMethod())
963 ex = new NoSuchMethodException(message);
964 else
965 ex = new NoSuchFieldException(message);
966 if (resolution instanceof Throwable)
967 ex.initCause((Throwable) resolution);
968 return ex;
969 }
970
971
972 static Factory getFactory() {
973 return Factory.INSTANCE;
974 }
975
978 static class Factory {
979 private Factory() { }
980 static Factory INSTANCE = new Factory();
981
982 private static int ALLOWED_FLAGS = ALL_KINDS;
983
984
985 List<MemberName> getMembers(Class<?> defc,
986 String matchName, Object matchType,
987 int matchFlags, Class<?> lookupClass) {
988 matchFlags &= ALLOWED_FLAGS;
989 String matchSig = null;
990 if (matchType != null) {
991 matchSig = BytecodeDescriptor.unparse(matchType);
992 if (matchSig.startsWith("("))
993 matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
994 else
995 matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
996 }
997 final int BUF_MAX = 0x2000;
998 int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
999 MemberName[] buf = newMemberBuffer(len1);
1000 int totalCount = 0;
1001 ArrayList<MemberName[]> bufs = null;
1002 int bufCount = 0;
1003 for (;;) {
1004 bufCount = MethodHandleNatives.getMembers(defc,
1005 matchName, matchSig, matchFlags,
1006 lookupClass,
1007 totalCount, buf);
1008 if (bufCount <= buf.length) {
1009 if (bufCount < 0) bufCount = 0;
1010 totalCount += bufCount;
1011 break;
1012 }
1013
1014 totalCount += buf.length;
1015 int excess = bufCount - buf.length;
1016 if (bufs == null) bufs = new ArrayList<>(1);
1017 bufs.add(buf);
1018 int len2 = buf.length;
1019 len2 = Math.max(len2, excess);
1020 len2 = Math.max(len2, totalCount / 4);
1021 buf = newMemberBuffer(Math.min(BUF_MAX, len2));
1022 }
1023 ArrayList<MemberName> result = new ArrayList<>(totalCount);
1024 if (bufs != null) {
1025 for (MemberName[] buf0 : bufs) {
1026 Collections.addAll(result, buf0);
1027 }
1028 }
1029 for (int i = 0; i < bufCount; i++) {
1030 result.add(buf[i]);
1031 }
1032
1033
1034
1035 if (matchType != null && matchType != matchSig) {
1036 for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
1037 MemberName m = it.next();
1038 if (!matchType.equals(m.getType()))
1039 it.remove();
1040 }
1041 }
1042 return result;
1043 }
1044
1050 private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass,
1051 boolean speculativeResolve) {
1052 MemberName m = ref.clone();
1053 assert(refKind == m.getReferenceKind());
1054 try {
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070 m = MethodHandleNatives.resolve(m, lookupClass, speculativeResolve);
1071 if (m == null && speculativeResolve) {
1072 return null;
1073 }
1074 m.checkForTypeAlias(m.getDeclaringClass());
1075 m.resolution = null;
1076 } catch (ClassNotFoundException | LinkageError ex) {
1077
1078 assert(!m.isResolved());
1079 m.resolution = ex;
1080 return m;
1081 }
1082 assert(m.referenceKindIsConsistent());
1083 m.initResolved(true);
1084 assert(m.vminfoIsConsistent());
1085 return m;
1086 }
1087
1093 public
1094 <NoSuchMemberException extends ReflectiveOperationException>
1095 MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
1096 Class<NoSuchMemberException> nsmClass)
1097 throws IllegalAccessException, NoSuchMemberException {
1098 MemberName result = resolve(refKind, m, lookupClass, false);
1099 if (result.isResolved())
1100 return result;
1101 ReflectiveOperationException ex = result.makeAccessException();
1102 if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
1103 throw nsmClass.cast(ex);
1104 }
1105
1111 public
1112 MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
1113 MemberName result = resolve(refKind, m, lookupClass, true);
1114 if (result != null && result.isResolved())
1115 return result;
1116 return null;
1117 }
1118
1123 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1124 Class<?> lookupClass) {
1125 return getMethods(defc, searchSupers, null, null, lookupClass);
1126 }
1127
1133 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1134 String name, MethodType type, Class<?> lookupClass) {
1135 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1136 return getMembers(defc, name, type, matchFlags, lookupClass);
1137 }
1138
1142 public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
1143 return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
1144 }
1145
1150 public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1151 Class<?> lookupClass) {
1152 return getFields(defc, searchSupers, null, null, lookupClass);
1153 }
1154
1160 public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1161 String name, Class<?> type, Class<?> lookupClass) {
1162 int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1163 return getMembers(defc, name, type, matchFlags, lookupClass);
1164 }
1165
1170 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
1171 Class<?> lookupClass) {
1172 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1173 return getMembers(defc, null, null, matchFlags, lookupClass);
1174 }
1175 private static MemberName[] newMemberBuffer(int length) {
1176 MemberName[] buf = new MemberName[length];
1177
1178 for (int i = 0; i < length; i++)
1179 buf[i] = new MemberName();
1180 return buf;
1181 }
1182 }
1183 }
1184