38 import java.util.Iterator; |
38 import java.util.Iterator; |
39 import java.util.List; |
39 import java.util.List; |
40 import static sun.dyn.MethodHandleNatives.Constants.*; |
40 import static sun.dyn.MethodHandleNatives.Constants.*; |
41 |
41 |
42 /** |
42 /** |
43 * Compact information which fully characterizes a method or field reference. |
43 * A {@code MemberName} is a compact symbolic datum which fully characterizes |
44 * When resolved, it includes a direct pointer to JVM metadata. |
44 * a method or field reference. |
|
45 * A member name refers to a field, method, constructor, or member type. |
|
46 * Every member name has a simple name (a string) and a type (either a Class or MethodType). |
|
47 * A member name may also have a non-null declaring class, or it may be simply |
|
48 * a naked name/type pair. |
|
49 * A member name may also have non-zero modifier flags. |
|
50 * Finally, a member name may be either resolved or unresolved. |
|
51 * If it is resolved, the existence of the named |
|
52 * <p> |
|
53 * Whether resolved or not, a member name provides no access rights or |
|
54 * invocation capability to its possessor. It is merely a compact |
|
55 * representation of all symbolic information necessary to link to |
|
56 * and properly use the named member. |
|
57 * <p> |
|
58 * When resolved, a member name's internal implementation may include references to JVM metadata. |
45 * This representation is stateless and only decriptive. |
59 * This representation is stateless and only decriptive. |
46 * It provides no private information and no capability to use the member. |
60 * It provides no private information and no capability to use the member. |
47 * <p> |
61 * <p> |
48 * By contrast, a java.lang.reflect.Method contains fuller information |
62 * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information |
49 * about the internals of a method (except its bytecodes) and also |
63 * about the internals of a method (except its bytecodes) and also |
50 * allows invocation. A MemberName is much lighter than a reflect.Method, |
64 * allows invocation. A MemberName is much lighter than a Method, |
51 * since it contains about 7 fields to Method's 16 (plus its sub-arrays), |
65 * since it contains about 7 fields to the 16 of Method (plus its sub-arrays), |
52 * and those seven fields omit much of the information in Method. |
66 * and those seven fields omit much of the information in Method. |
53 * @author jrose |
67 * @author jrose |
54 */ |
68 */ |
55 public final class MemberName implements Member, Cloneable { |
69 public final class MemberName implements Member, Cloneable { |
56 private Class<?> clazz; // class in which the method is defined |
70 private Class<?> clazz; // class in which the method is defined |
178 } |
221 } |
179 private boolean testAnyFlags(int mask) { |
222 private boolean testAnyFlags(int mask) { |
180 return !testFlags(mask, 0); |
223 return !testFlags(mask, 0); |
181 } |
224 } |
182 |
225 |
|
226 /** Utility method to query the modifier flags of this member. */ |
183 public boolean isStatic() { |
227 public boolean isStatic() { |
184 return Modifier.isStatic(flags); |
228 return Modifier.isStatic(flags); |
185 } |
229 } |
|
230 /** Utility method to query the modifier flags of this member. */ |
186 public boolean isPublic() { |
231 public boolean isPublic() { |
187 return Modifier.isPublic(flags); |
232 return Modifier.isPublic(flags); |
188 } |
233 } |
|
234 /** Utility method to query the modifier flags of this member. */ |
189 public boolean isPrivate() { |
235 public boolean isPrivate() { |
190 return Modifier.isPrivate(flags); |
236 return Modifier.isPrivate(flags); |
191 } |
237 } |
|
238 /** Utility method to query the modifier flags of this member. */ |
192 public boolean isProtected() { |
239 public boolean isProtected() { |
193 return Modifier.isProtected(flags); |
240 return Modifier.isProtected(flags); |
194 } |
241 } |
|
242 /** Utility method to query the modifier flags of this member. */ |
195 public boolean isFinal() { |
243 public boolean isFinal() { |
196 return Modifier.isFinal(flags); |
244 return Modifier.isFinal(flags); |
197 } |
245 } |
|
246 /** Utility method to query the modifier flags of this member. */ |
198 public boolean isAbstract() { |
247 public boolean isAbstract() { |
199 return Modifier.isAbstract(flags); |
248 return Modifier.isAbstract(flags); |
200 } |
249 } |
201 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo |
250 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo |
202 |
251 |
235 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; |
287 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; |
236 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR; |
288 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR; |
237 static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD; |
289 static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD; |
238 static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES; |
290 static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES; |
239 |
291 |
|
292 /** Utility method to query whether this member is a method or constructor. */ |
240 public boolean isInvocable() { |
293 public boolean isInvocable() { |
241 return testAnyFlags(IS_INVOCABLE); |
294 return testAnyFlags(IS_INVOCABLE); |
242 } |
295 } |
|
296 /** Utility method to query whether this member is a method, constructor, or field. */ |
243 public boolean isFieldOrMethod() { |
297 public boolean isFieldOrMethod() { |
244 return testAnyFlags(IS_FIELD_OR_METHOD); |
298 return testAnyFlags(IS_FIELD_OR_METHOD); |
245 } |
299 } |
|
300 /** Query whether this member is a method. */ |
246 public boolean isMethod() { |
301 public boolean isMethod() { |
247 return testAllFlags(IS_METHOD); |
302 return testAllFlags(IS_METHOD); |
248 } |
303 } |
|
304 /** Query whether this member is a constructor. */ |
249 public boolean isConstructor() { |
305 public boolean isConstructor() { |
250 return testAllFlags(IS_CONSTRUCTOR); |
306 return testAllFlags(IS_CONSTRUCTOR); |
251 } |
307 } |
|
308 /** Query whether this member is a field. */ |
252 public boolean isField() { |
309 public boolean isField() { |
253 return testAllFlags(IS_FIELD); |
310 return testAllFlags(IS_FIELD); |
254 } |
311 } |
|
312 /** Query whether this member is a type. */ |
255 public boolean isType() { |
313 public boolean isType() { |
256 return testAllFlags(IS_TYPE); |
314 return testAllFlags(IS_TYPE); |
257 } |
315 } |
|
316 /** Utility method to query whether this member is neither public, private, nor protected. */ |
258 public boolean isPackage() { |
317 public boolean isPackage() { |
259 return !testAnyFlags(ALL_ACCESS); |
318 return !testAnyFlags(ALL_ACCESS); |
260 } |
319 } |
261 |
320 |
262 /** Initialize a query. It is not resolved. */ |
321 /** Initialize a query. It is not resolved. */ |
263 private void init(Class<?> defClass, String name, Object type, int flags) { |
322 private void init(Class<?> defClass, String name, Object type, int flags) { |
264 // defining class is allowed to be null (for a naked name/type pair) |
323 // defining class is allowed to be null (for a naked name/type pair) |
265 name.toString(); // null check |
324 //name.toString(); // null check |
266 type.equals(type); // null check |
325 //type.equals(type); // null check |
267 // fill in fields: |
326 // fill in fields: |
268 this.clazz = defClass; |
327 this.clazz = defClass; |
269 this.name = name; |
328 this.name = name; |
270 this.type = type; |
329 this.type = type; |
271 setFlags(flags); |
330 setFlags(flags); |
283 private static int flagsMods(int flags, int mods) { |
342 private static int flagsMods(int flags, int mods) { |
284 assert((flags & RECOGNIZED_MODIFIERS) == 0); |
343 assert((flags & RECOGNIZED_MODIFIERS) == 0); |
285 assert((mods & ~RECOGNIZED_MODIFIERS) == 0); |
344 assert((mods & ~RECOGNIZED_MODIFIERS) == 0); |
286 return flags | mods; |
345 return flags | mods; |
287 } |
346 } |
|
347 /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ |
288 public MemberName(Method m) { |
348 public MemberName(Method m) { |
289 Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() }; |
349 Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() }; |
290 init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers())); |
350 init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers())); |
291 // fill in vmtarget, vmindex while we have m in hand: |
351 // fill in vmtarget, vmindex while we have m in hand: |
292 MethodHandleNatives.init(this, m); |
352 MethodHandleNatives.init(this, m); |
293 assert(isResolved()); |
353 assert(isResolved()); |
294 } |
354 } |
|
355 /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */ |
295 public MemberName(Constructor ctor) { |
356 public MemberName(Constructor ctor) { |
296 Object[] typeInfo = { void.class, ctor.getParameterTypes() }; |
357 Object[] typeInfo = { void.class, ctor.getParameterTypes() }; |
297 init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers())); |
358 init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers())); |
298 // fill in vmtarget, vmindex while we have ctor in hand: |
359 // fill in vmtarget, vmindex while we have ctor in hand: |
299 MethodHandleNatives.init(this, ctor); |
360 MethodHandleNatives.init(this, ctor); |
300 assert(isResolved()); |
361 assert(isResolved()); |
301 } |
362 } |
|
363 /** Create a name for the given reflected field. The resulting name will be in a resolved state. */ |
302 public MemberName(Field fld) { |
364 public MemberName(Field fld) { |
303 init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers())); |
365 init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers())); |
304 // fill in vmtarget, vmindex while we have fld in hand: |
366 // fill in vmtarget, vmindex while we have fld in hand: |
305 MethodHandleNatives.init(this, fld); |
367 MethodHandleNatives.init(this, fld); |
306 assert(isResolved()); |
368 assert(isResolved()); |
307 } |
369 } |
|
370 /** Create a name for the given class. The resulting name will be in a resolved state. */ |
308 public MemberName(Class<?> type) { |
371 public MemberName(Class<?> type) { |
309 init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers())); |
372 init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers())); |
310 vmindex = 0; // isResolved |
373 vmindex = 0; // isResolved |
311 assert(isResolved()); |
374 assert(isResolved()); |
312 } |
375 } |
324 } |
387 } |
325 |
388 |
326 // %%% define equals/hashcode? |
389 // %%% define equals/hashcode? |
327 |
390 |
328 // Construction from symbolic parts, for queries: |
391 // Construction from symbolic parts, for queries: |
|
392 /** Create a field or type name from the given components: Declaring class, name, type, modifiers. |
|
393 * The declaring class may be supplied as null if this is to be a bare name and type. |
|
394 * The resulting name will in an unresolved state. |
|
395 */ |
329 public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) { |
396 public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) { |
330 init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS)); |
397 init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS)); |
331 } |
398 } |
|
399 /** Create a field or type name from the given components: Declaring class, name, type. |
|
400 * The declaring class may be supplied as null if this is to be a bare name and type. |
|
401 * The modifier flags default to zero. |
|
402 * The resulting name will in an unresolved state. |
|
403 */ |
332 public MemberName(Class<?> defClass, String name, Class<?> type) { |
404 public MemberName(Class<?> defClass, String name, Class<?> type) { |
333 this(defClass, name, type, 0); |
405 this(defClass, name, type, 0); |
334 } |
406 } |
|
407 /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. |
|
408 * It will be a constructor if and only if the name is {@code "<init>"}. |
|
409 * The declaring class may be supplied as null if this is to be a bare name and type. |
|
410 * The resulting name will in an unresolved state. |
|
411 */ |
335 public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) { |
412 public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) { |
336 int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); |
413 int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); |
337 init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS)); |
414 init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS)); |
338 } |
415 } |
|
416 /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. |
|
417 * It will be a constructor if and only if the name is {@code "<init>"}. |
|
418 * The declaring class may be supplied as null if this is to be a bare name and type. |
|
419 * The modifier flags default to zero. |
|
420 * The resulting name will in an unresolved state. |
|
421 */ |
339 public MemberName(Class<?> defClass, String name, MethodType type) { |
422 public MemberName(Class<?> defClass, String name, MethodType type) { |
340 this(defClass, name, type, 0); |
423 this(defClass, name, type, 0); |
341 } |
424 } |
342 |
425 |
343 boolean isResolved() { |
426 /** Query whether this member name is resolved. |
|
427 * A resolved member name is one for which the JVM has found |
|
428 * a method, constructor, field, or type binding corresponding exactly to the name. |
|
429 * (Document?) |
|
430 */ |
|
431 public boolean isResolved() { |
344 return (vmindex != VM_INDEX_UNINITIALIZED); |
432 return (vmindex != VM_INDEX_UNINITIALIZED); |
345 } |
433 } |
346 |
434 |
|
435 /** Query whether this member name is resolved to a non-static, non-final method. |
|
436 */ |
347 public boolean hasReceiverTypeDispatch() { |
437 public boolean hasReceiverTypeDispatch() { |
348 return (isMethod() && getVMIndex(Access.TOKEN) >= 0); |
438 return (isMethod() && getVMIndex(Access.TOKEN) >= 0); |
349 } |
439 } |
350 |
440 |
|
441 /** Produce a string form of this member name. |
|
442 * For types, it is simply the type's own string (as reported by {@code toString}). |
|
443 * For fields, it is {@code "DeclaringClass.name/type"}. |
|
444 * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}. |
|
445 * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted. |
|
446 * If the member is unresolved, a prefix {@code "*."} is prepended. |
|
447 */ |
351 @Override |
448 @Override |
352 public String toString() { |
449 public String toString() { |
353 if (isType()) |
450 if (isType()) |
354 return type.toString(); // class java.lang.String |
451 return type.toString(); // class java.lang.String |
355 // else it is a field, method, or constructor |
452 // else it is a field, method, or constructor |
492 } |
596 } |
493 } |
597 } |
494 return result; |
598 return result; |
495 } |
599 } |
496 boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) { |
600 boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) { |
|
601 if (m.name == null || m.type == null) { // find unique non-overloaded name |
|
602 Class<?> defc = m.getDeclaringClass(); |
|
603 List<MemberName> choices = null; |
|
604 if (m.isMethod()) |
|
605 choices = getMethods(defc, searchSupers, m.name, (MethodType) m.type, lookupClass); |
|
606 else if (m.isConstructor()) |
|
607 choices = getConstructors(defc, lookupClass); |
|
608 else if (m.isField()) |
|
609 choices = getFields(defc, searchSupers, m.name, (Class<?>) m.type, lookupClass); |
|
610 //System.out.println("resolving "+m+" to "+choices); |
|
611 if (choices == null || choices.size() != 1) |
|
612 return false; |
|
613 if (m.name == null) m.name = choices.get(0).name; |
|
614 if (m.type == null) m.type = choices.get(0).type; |
|
615 } |
497 MethodHandleNatives.resolve(m, lookupClass); |
616 MethodHandleNatives.resolve(m, lookupClass); |
498 if (m.isResolved()) return true; |
617 if (m.isResolved()) return true; |
499 int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0); |
618 int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0); |
500 String matchSig = m.getSignature(); |
619 String matchSig = m.getSignature(); |
501 MemberName[] buf = { m }; |
620 MemberName[] buf = { m }; |
502 int n = MethodHandleNatives.getMembers(m.getDeclaringClass(), |
621 int n = MethodHandleNatives.getMembers(m.getDeclaringClass(), |
503 m.getName(), matchSig, matchFlags, lookupClass, 0, buf); |
622 m.getName(), matchSig, matchFlags, lookupClass, 0, buf); |
504 if (n != 1) return false; |
623 if (n != 1) return false; |
505 return m.isResolved(); |
624 return m.isResolved(); |
506 } |
625 } |
|
626 /** Produce a resolved version of the given member. |
|
627 * Super types are searched (for inherited members) if {@code searchSupers} is true. |
|
628 * Access checking is performed on behalf of the given {@code lookupClass}. |
|
629 * If lookup fails or access is not permitted, null is returned. |
|
630 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. |
|
631 */ |
507 public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) { |
632 public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) { |
508 MemberName result = m.clone(); |
633 MemberName result = m.clone(); |
509 if (resolveInPlace(result, searchSupers, lookupClass)) |
634 if (resolveInPlace(result, searchSupers, lookupClass)) |
510 return result; |
635 return result; |
511 return null; |
636 return null; |
512 } |
637 } |
|
638 /** Produce a resolved version of the given member. |
|
639 * Super types are searched (for inherited members) if {@code searchSupers} is true. |
|
640 * Access checking is performed on behalf of the given {@code lookupClass}. |
|
641 * If lookup fails or access is not permitted, a {@linkplain NoAccessException} is thrown. |
|
642 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. |
|
643 */ |
513 public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) { |
644 public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) { |
514 MemberName result = resolveOrNull(m, searchSupers, lookupClass); |
645 MemberName result = resolveOrNull(m, searchSupers, lookupClass); |
515 if (result != null) |
646 if (result != null) |
516 return result; |
647 return result; |
517 throw newNoAccessException(m, lookupClass); |
648 throw newNoAccessException(m, lookupClass); |
518 } |
649 } |
|
650 /** Return a list of all methods defined by the given class. |
|
651 * Super types are searched (for inherited members) if {@code searchSupers} is true. |
|
652 * Access checking is performed on behalf of the given {@code lookupClass}. |
|
653 * Inaccessible members are not added to the last. |
|
654 */ |
519 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, |
655 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, |
520 Class<?> lookupClass) { |
656 Class<?> lookupClass) { |
521 return getMethods(defc, searchSupers, null, null, lookupClass); |
657 return getMethods(defc, searchSupers, null, null, lookupClass); |
522 } |
658 } |
|
659 /** Return a list of matching methods defined by the given class. |
|
660 * Super types are searched (for inherited members) if {@code searchSupers} is true. |
|
661 * Returned methods will match the name (if not null) and the type (if not null). |
|
662 * Access checking is performed on behalf of the given {@code lookupClass}. |
|
663 * Inaccessible members are not added to the last. |
|
664 */ |
523 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, |
665 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, |
524 String name, MethodType type, Class<?> lookupClass) { |
666 String name, MethodType type, Class<?> lookupClass) { |
525 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0); |
667 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0); |
526 return getMembers(defc, name, type, matchFlags, lookupClass); |
668 return getMembers(defc, name, type, matchFlags, lookupClass); |
527 } |
669 } |
|
670 /** Return a list of all constructors defined by the given class. |
|
671 * Access checking is performed on behalf of the given {@code lookupClass}. |
|
672 * Inaccessible members are not added to the last. |
|
673 */ |
528 public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) { |
674 public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) { |
529 return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass); |
675 return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass); |
530 } |
676 } |
|
677 /** Return a list of all fields defined by the given class. |
|
678 * Super types are searched (for inherited members) if {@code searchSupers} is true. |
|
679 * Access checking is performed on behalf of the given {@code lookupClass}. |
|
680 * Inaccessible members are not added to the last. |
|
681 */ |
531 public List<MemberName> getFields(Class<?> defc, boolean searchSupers, |
682 public List<MemberName> getFields(Class<?> defc, boolean searchSupers, |
532 Class<?> lookupClass) { |
683 Class<?> lookupClass) { |
533 return getFields(defc, searchSupers, null, null, lookupClass); |
684 return getFields(defc, searchSupers, null, null, lookupClass); |
534 } |
685 } |
|
686 /** Return a list of all fields defined by the given class. |
|
687 * Super types are searched (for inherited members) if {@code searchSupers} is true. |
|
688 * Returned fields will match the name (if not null) and the type (if not null). |
|
689 * Access checking is performed on behalf of the given {@code lookupClass}. |
|
690 * Inaccessible members are not added to the last. |
|
691 */ |
535 public List<MemberName> getFields(Class<?> defc, boolean searchSupers, |
692 public List<MemberName> getFields(Class<?> defc, boolean searchSupers, |
536 String name, Class<?> type, Class<?> lookupClass) { |
693 String name, Class<?> type, Class<?> lookupClass) { |
537 int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0); |
694 int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0); |
538 return getMembers(defc, name, type, matchFlags, lookupClass); |
695 return getMembers(defc, name, type, matchFlags, lookupClass); |
539 } |
696 } |
|
697 /** Return a list of all nested types defined by the given class. |
|
698 * Super types are searched (for inherited members) if {@code searchSupers} is true. |
|
699 * Access checking is performed on behalf of the given {@code lookupClass}. |
|
700 * Inaccessible members are not added to the last. |
|
701 */ |
540 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers, |
702 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers, |
541 Class<?> lookupClass) { |
703 Class<?> lookupClass) { |
542 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0); |
704 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0); |
543 return getMembers(defc, null, null, matchFlags, lookupClass); |
705 return getMembers(defc, null, null, matchFlags, lookupClass); |
544 } |
706 } |