24 */ |
24 */ |
25 |
25 |
26 package java.lang.invoke; |
26 package java.lang.invoke; |
27 |
27 |
28 import java.lang.reflect.*; |
28 import java.lang.reflect.*; |
29 import java.util.*; |
29 import java.util.ArrayList; |
|
30 import java.util.BitSet; |
|
31 import java.util.List; |
|
32 import java.util.Arrays; |
|
33 import java.util.Objects; |
|
34 import java.security.AccessController; |
|
35 import java.security.PrivilegedAction; |
30 |
36 |
31 import sun.invoke.util.ValueConversions; |
37 import sun.invoke.util.ValueConversions; |
32 import sun.invoke.util.VerifyAccess; |
38 import sun.invoke.util.VerifyAccess; |
33 import sun.invoke.util.Wrapper; |
39 import sun.invoke.util.Wrapper; |
34 import sun.reflect.CallerSensitive; |
40 import sun.reflect.CallerSensitive; |
41 import static java.lang.invoke.MethodHandleImpl.Intrinsic; |
47 import static java.lang.invoke.MethodHandleImpl.Intrinsic; |
42 import static java.lang.invoke.MethodHandleNatives.Constants.*; |
48 import static java.lang.invoke.MethodHandleNatives.Constants.*; |
43 import java.util.concurrent.ConcurrentHashMap; |
49 import java.util.concurrent.ConcurrentHashMap; |
44 import java.util.stream.Collectors; |
50 import java.util.stream.Collectors; |
45 import java.util.stream.Stream; |
51 import java.util.stream.Stream; |
|
52 |
|
53 import jdk.internal.org.objectweb.asm.ClassWriter; |
|
54 import jdk.internal.org.objectweb.asm.Opcodes; |
46 |
55 |
47 /** |
56 /** |
48 * This class consists exclusively of static methods that operate on or return |
57 * This class consists exclusively of static methods that operate on or return |
49 * method handles. They fall into several categories: |
58 * method handles. They fall into several categories: |
50 * <ul> |
59 * <ul> |
92 return new Lookup(Reflection.getCallerClass()); |
101 return new Lookup(Reflection.getCallerClass()); |
93 } |
102 } |
94 |
103 |
95 /** |
104 /** |
96 * Returns a {@link Lookup lookup object} which is trusted minimally. |
105 * Returns a {@link Lookup lookup object} which is trusted minimally. |
97 * It can only be used to create method handles to |
106 * It can only be used to create method handles to public members in |
98 * publicly accessible fields and methods. |
107 * public classes in packages that are exported unconditionally. |
99 * <p> |
108 * <p> |
100 * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} |
109 * For now, the {@linkplain Lookup#lookupClass lookup class} of this lookup |
101 * of this lookup object will be {@link java.lang.Object}. |
110 * object is in an unnamed module. |
102 * |
111 * |
103 * <p style="font-size:smaller;"> |
112 * <p style="font-size:smaller;"> |
104 * <em>Discussion:</em> |
113 * <em>Discussion:</em> |
105 * The lookup class can be changed to any other class {@code C} using an expression of the form |
114 * The lookup class can be changed to any other class {@code C} using an expression of the form |
106 * {@link Lookup#in publicLookup().in(C.class)}. |
115 * {@link Lookup#in publicLookup().in(C.class)}. |
107 * Since all classes have equal access to public names, |
|
108 * such a change would confer no new access rights. |
|
109 * A public lookup object is always subject to |
116 * A public lookup object is always subject to |
110 * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. |
117 * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. |
111 * Also, it cannot access |
118 * Also, it cannot access |
112 * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>. |
119 * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>. |
113 * @return a lookup object which is trusted minimally |
120 * @return a lookup object which is trusted minimally |
114 */ |
121 */ |
115 public static Lookup publicLookup() { |
122 public static Lookup publicLookup() { |
116 return Lookup.PUBLIC_LOOKUP; |
123 // During VM startup then only classes in the java.base module can be |
|
124 // loaded and linked. This is because java.base exports aren't setup until |
|
125 // the module system is initialized, hence types in the unnamed module |
|
126 // (or any named module) can't link to java/lang/Object. |
|
127 if (!jdk.internal.misc.VM.isModuleSystemInited()) { |
|
128 return new Lookup(Object.class, Lookup.PUBLIC); |
|
129 } else { |
|
130 return LookupHelper.PUBLIC_LOOKUP; |
|
131 } |
117 } |
132 } |
118 |
133 |
119 /** |
134 /** |
120 * Performs an unchecked "crack" of a |
135 * Performs an unchecked "crack" of a |
121 * <a href="MethodHandleInfo.html#directmh">direct method handle</a>. |
136 * <a href="MethodHandleInfo.html#directmh">direct method handle</a>. |
384 * The accesses permitted to a given lookup object may be limited, |
399 * The accesses permitted to a given lookup object may be limited, |
385 * according to its set of {@link #lookupModes lookupModes}, |
400 * according to its set of {@link #lookupModes lookupModes}, |
386 * to a subset of members normally accessible to the lookup class. |
401 * to a subset of members normally accessible to the lookup class. |
387 * For example, the {@link MethodHandles#publicLookup publicLookup} |
402 * For example, the {@link MethodHandles#publicLookup publicLookup} |
388 * method produces a lookup object which is only allowed to access |
403 * method produces a lookup object which is only allowed to access |
389 * public members in public classes. |
404 * public members in public classes of exported packages. |
390 * The caller sensitive method {@link MethodHandles#lookup lookup} |
405 * The caller sensitive method {@link MethodHandles#lookup lookup} |
391 * produces a lookup object with full capabilities relative to |
406 * produces a lookup object with full capabilities relative to |
392 * its caller class, to emulate all supported bytecode behaviors. |
407 * its caller class, to emulate all supported bytecode behaviors. |
393 * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object |
408 * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object |
394 * with fewer access modes than the original lookup object. |
409 * with fewer access modes than the original lookup object. |
556 * The value is {@code 0x08}, which does not correspond meaningfully to |
571 * The value is {@code 0x08}, which does not correspond meaningfully to |
557 * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. |
572 * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. |
558 */ |
573 */ |
559 public static final int PACKAGE = Modifier.STATIC; |
574 public static final int PACKAGE = Modifier.STATIC; |
560 |
575 |
561 private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE); |
576 /** A single-bit mask representing {@code module} access (default access), |
|
577 * which may contribute to the result of {@link #lookupModes lookupModes}. |
|
578 * The value is {@code 0x10}, which does not correspond meaningfully to |
|
579 * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. |
|
580 * In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup} |
|
581 * with this lookup mode can access all public types in the module of the |
|
582 * lookup class and public types in packages exported by other modules |
|
583 * to the module of the lookup class. |
|
584 * @since 9 |
|
585 */ |
|
586 public static final int MODULE = PACKAGE << 1; |
|
587 |
|
588 private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE); |
562 private static final int TRUSTED = -1; |
589 private static final int TRUSTED = -1; |
563 |
590 |
564 private static int fixmods(int mods) { |
591 private static int fixmods(int mods) { |
565 mods &= (ALL_MODES - PACKAGE); |
592 mods &= (ALL_MODES - PACKAGE - MODULE); |
566 return (mods != 0) ? mods : PACKAGE; |
593 return (mods != 0) ? mods : (PACKAGE | MODULE); |
567 } |
594 } |
568 |
595 |
569 /** Tells which class is performing the lookup. It is this class against |
596 /** Tells which class is performing the lookup. It is this class against |
570 * which checks are performed for visibility and access permissions. |
597 * which checks are performed for visibility and access permissions. |
571 * <p> |
598 * <p> |
587 /** Tells which access-protection classes of members this lookup object can produce. |
614 /** Tells which access-protection classes of members this lookup object can produce. |
588 * The result is a bit-mask of the bits |
615 * The result is a bit-mask of the bits |
589 * {@linkplain #PUBLIC PUBLIC (0x01)}, |
616 * {@linkplain #PUBLIC PUBLIC (0x01)}, |
590 * {@linkplain #PRIVATE PRIVATE (0x02)}, |
617 * {@linkplain #PRIVATE PRIVATE (0x02)}, |
591 * {@linkplain #PROTECTED PROTECTED (0x04)}, |
618 * {@linkplain #PROTECTED PROTECTED (0x04)}, |
592 * and {@linkplain #PACKAGE PACKAGE (0x08)}. |
619 * {@linkplain #PACKAGE PACKAGE (0x08)}, |
|
620 * and {@linkplain #MODULE MODULE (0x10)}. |
593 * <p> |
621 * <p> |
594 * A freshly-created lookup object |
622 * A freshly-created lookup object |
595 * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} |
623 * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} |
596 * has all possible bits set, since the caller class can access all its own members. |
624 * has all possible bits set, since the caller class can access all its own members, |
|
625 * all public types in the caller's module, and all public types in packages exported |
|
626 * by other modules to the caller's module. |
597 * A lookup object on a new lookup class |
627 * A lookup object on a new lookup class |
598 * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} |
628 * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} |
599 * may have some mode bits set to zero. |
629 * may have some mode bits set to zero. |
600 * The purpose of this is to restrict access via the new lookup object, |
630 * The purpose of this is to restrict access via the new lookup object, |
601 * so that it can access only names which can be reached by the original |
631 * so that it can access only names which can be reached by the original |
628 * class as its own {@link #lookupClass lookupClass}. |
658 * class as its own {@link #lookupClass lookupClass}. |
629 * <p> |
659 * <p> |
630 * However, the resulting {@code Lookup} object is guaranteed |
660 * However, the resulting {@code Lookup} object is guaranteed |
631 * to have no more access capabilities than the original. |
661 * to have no more access capabilities than the original. |
632 * In particular, access capabilities can be lost as follows:<ul> |
662 * In particular, access capabilities can be lost as follows:<ul> |
|
663 * <li>If the lookup class for this {@code Lookup} is not in a named module, |
|
664 * and the new lookup class is in a named module {@code M}, then no members in |
|
665 * {@code M}'s non-exported packages will be accessible. |
|
666 * <li>If the lookup for this {@code Lookup} is in a named module, and the |
|
667 * new lookup class is in a different module {@code M}, then no members, not even |
|
668 * public members in {@code M}'s exported packages, will be accessible. |
633 * <li>If the new lookup class differs from the old one, |
669 * <li>If the new lookup class differs from the old one, |
634 * protected members will not be accessible by virtue of inheritance. |
670 * protected members will not be accessible by virtue of inheritance. |
635 * (Protected members may continue to be accessible because of package sharing.) |
671 * (Protected members may continue to be accessible because of package sharing.) |
636 * <li>If the new lookup class is in a different package |
672 * <li>If the new lookup class is in a different package |
637 * than the old one, protected and default (package) members will not be accessible. |
673 * than the old one, protected and default (package) members will not be accessible. |
650 Objects.requireNonNull(requestedLookupClass); |
686 Objects.requireNonNull(requestedLookupClass); |
651 if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all |
687 if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all |
652 return new Lookup(requestedLookupClass, ALL_MODES); |
688 return new Lookup(requestedLookupClass, ALL_MODES); |
653 if (requestedLookupClass == this.lookupClass) |
689 if (requestedLookupClass == this.lookupClass) |
654 return this; // keep same capabilities |
690 return this; // keep same capabilities |
|
691 |
655 int newModes = (allowedModes & (ALL_MODES & ~PROTECTED)); |
692 int newModes = (allowedModes & (ALL_MODES & ~PROTECTED)); |
|
693 if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) { |
|
694 // Allowed to teleport from an unnamed to a named module but resulting |
|
695 // Lookup has no access to module private members |
|
696 if (this.lookupClass.getModule().isNamed()) { |
|
697 newModes = 0; |
|
698 } else { |
|
699 newModes &= ~MODULE; |
|
700 } |
|
701 } |
656 if ((newModes & PACKAGE) != 0 |
702 if ((newModes & PACKAGE) != 0 |
657 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { |
703 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { |
658 newModes &= ~(PACKAGE|PRIVATE); |
704 newModes &= ~(PACKAGE|PRIVATE); |
659 } |
705 } |
660 // Allow nestmate lookups to be created without special privilege: |
706 // Allow nestmate lookups to be created without special privilege: |
666 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { |
712 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { |
667 // The requested class it not accessible from the lookup class. |
713 // The requested class it not accessible from the lookup class. |
668 // No permissions. |
714 // No permissions. |
669 newModes = 0; |
715 newModes = 0; |
670 } |
716 } |
|
717 |
671 checkUnprivilegedlookupClass(requestedLookupClass, newModes); |
718 checkUnprivilegedlookupClass(requestedLookupClass, newModes); |
672 return new Lookup(requestedLookupClass, newModes); |
719 return new Lookup(requestedLookupClass, newModes); |
673 } |
720 } |
674 |
721 |
675 // Make sure outer class is initialized first. |
722 // Make sure outer class is initialized first. |
676 static { IMPL_NAMES.getClass(); } |
723 static { IMPL_NAMES.getClass(); } |
677 |
|
678 /** Version of lookup which is trusted minimally. |
|
679 * It can only be used to create method handles to |
|
680 * publicly accessible members. |
|
681 */ |
|
682 static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC); |
|
683 |
724 |
684 /** Package-private version of lookup which is trusted. */ |
725 /** Package-private version of lookup which is trusted. */ |
685 static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); |
726 static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); |
686 |
727 |
687 private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) { |
728 private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) { |
706 * this is indicated by adding a suffix to the class name, consisting |
747 * this is indicated by adding a suffix to the class name, consisting |
707 * of a slash and a keyword. The keyword represents the strongest |
748 * of a slash and a keyword. The keyword represents the strongest |
708 * allowed access, and is chosen as follows: |
749 * allowed access, and is chosen as follows: |
709 * <ul> |
750 * <ul> |
710 * <li>If no access is allowed, the suffix is "/noaccess". |
751 * <li>If no access is allowed, the suffix is "/noaccess". |
711 * <li>If only public access is allowed, the suffix is "/public". |
752 * <li>If only public access to types in exported packages is allowed, the suffix is "/public". |
712 * <li>If only public and package access are allowed, the suffix is "/package". |
753 * <li>If only public and module access are allowed, the suffix is "/module". |
713 * <li>If only public, package, and private access are allowed, the suffix is "/private". |
754 * <li>If only public, module and package access are allowed, the suffix is "/package". |
|
755 * <li>If only public, module, package, and private access are allowed, the suffix is "/private". |
714 * </ul> |
756 * </ul> |
715 * If none of the above cases apply, it is the case that full |
757 * If none of the above cases apply, it is the case that full |
716 * access (public, package, private, and protected) is allowed. |
758 * access (public, module, package, private, and protected) is allowed. |
717 * In this case, no suffix is added. |
759 * In this case, no suffix is added. |
718 * This is true only of an object obtained originally from |
760 * This is true only of an object obtained originally from |
719 * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}. |
761 * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}. |
720 * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in} |
762 * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in} |
721 * always have restricted access, and will display a suffix. |
763 * always have restricted access, and will display a suffix. |
733 switch (allowedModes) { |
775 switch (allowedModes) { |
734 case 0: // no privileges |
776 case 0: // no privileges |
735 return cname + "/noaccess"; |
777 return cname + "/noaccess"; |
736 case PUBLIC: |
778 case PUBLIC: |
737 return cname + "/public"; |
779 return cname + "/public"; |
738 case PUBLIC|PACKAGE: |
780 case PUBLIC|MODULE: |
|
781 return cname + "/module"; |
|
782 case PUBLIC|MODULE|PACKAGE: |
739 return cname + "/package"; |
783 return cname + "/package"; |
740 case ALL_MODES & ~PROTECTED: |
784 case ALL_MODES & ~PROTECTED: |
741 return cname + "/private"; |
785 return cname + "/private"; |
742 case ALL_MODES: |
786 case ALL_MODES: |
743 return cname; |
787 return cname; |
1453 |
1497 |
1454 void checkSymbolicClass(Class<?> refc) throws IllegalAccessException { |
1498 void checkSymbolicClass(Class<?> refc) throws IllegalAccessException { |
1455 Objects.requireNonNull(refc); |
1499 Objects.requireNonNull(refc); |
1456 Class<?> caller = lookupClassOrNull(); |
1500 Class<?> caller = lookupClassOrNull(); |
1457 if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes)) |
1501 if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes)) |
1458 throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); |
1502 throw new MemberName(refc).makeAccessException("symbolic reference class is not accessible", this); |
1459 } |
1503 } |
1460 |
1504 |
1461 /** Check name for an illegal leading "<" character. */ |
1505 /** Check name for an illegal leading "<" character. */ |
1462 void checkMethodName(byte refKind, String name) throws NoSuchMethodException { |
1506 void checkMethodName(byte refKind, String name) throws NoSuchMethodException { |
1463 if (name.startsWith("<") && refKind != REF_newInvokeSpecial) |
1507 if (name.startsWith("<") && refKind != REF_newInvokeSpecial) |
1582 mods ^= Modifier.PROTECTED; |
1626 mods ^= Modifier.PROTECTED; |
1583 } |
1627 } |
1584 if (Modifier.isFinal(mods) && |
1628 if (Modifier.isFinal(mods) && |
1585 MethodHandleNatives.refKindIsSetter(refKind)) |
1629 MethodHandleNatives.refKindIsSetter(refKind)) |
1586 throw m.makeAccessException("unexpected set of a final field", this); |
1630 throw m.makeAccessException("unexpected set of a final field", this); |
1587 if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0) |
|
1588 return; // common case |
|
1589 int requestedModes = fixmods(mods); // adjust 0 => PACKAGE |
1631 int requestedModes = fixmods(mods); // adjust 0 => PACKAGE |
1590 if ((requestedModes & allowedModes) != 0) { |
1632 if ((requestedModes & allowedModes) != 0) { |
1591 if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(), |
1633 if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(), |
1592 mods, lookupClass(), allowedModes)) |
1634 mods, lookupClass(), allowedModes)) |
1593 return; |
1635 return; |
1613 VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES))); |
1655 VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES))); |
1614 } |
1656 } |
1615 if (!classOK) |
1657 if (!classOK) |
1616 return "class is not public"; |
1658 return "class is not public"; |
1617 if (Modifier.isPublic(mods)) |
1659 if (Modifier.isPublic(mods)) |
1618 return "access to public member failed"; // (how?) |
1660 return "access to public member failed"; // (how?, module not readable?) |
1619 if (Modifier.isPrivate(mods)) |
1661 if (Modifier.isPrivate(mods)) |
1620 return "member is private"; |
1662 return "member is private"; |
1621 if (Modifier.isProtected(mods)) |
1663 if (Modifier.isProtected(mods)) |
1622 return "member is protected"; |
1664 return "member is protected"; |
1623 return "member is private to package"; |
1665 return "member is private to package"; |
1872 // oops |
1914 // oops |
1873 throw newIllegalArgumentException("bad MethodHandle constant #"+member); |
1915 throw newIllegalArgumentException("bad MethodHandle constant #"+member); |
1874 } |
1916 } |
1875 |
1917 |
1876 static ConcurrentHashMap<MemberName, DirectMethodHandle> LOOKASIDE_TABLE = new ConcurrentHashMap<>(); |
1918 static ConcurrentHashMap<MemberName, DirectMethodHandle> LOOKASIDE_TABLE = new ConcurrentHashMap<>(); |
|
1919 } |
|
1920 |
|
1921 /** |
|
1922 * Helper class used to lazily create PUBLIC_LOOKUP with a lookup class |
|
1923 * in an <em>unnamed module</em>. |
|
1924 * |
|
1925 * @see Lookup#publicLookup |
|
1926 */ |
|
1927 private static class LookupHelper { |
|
1928 private static final String UNNAMED = "Unnamed"; |
|
1929 private static final String OBJECT = "java/lang/Object"; |
|
1930 |
|
1931 private static Class<?> createClass() { |
|
1932 try { |
|
1933 ClassWriter cw = new ClassWriter(0); |
|
1934 cw.visit(Opcodes.V1_8, |
|
1935 Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, |
|
1936 UNNAMED, |
|
1937 null, |
|
1938 OBJECT, |
|
1939 null); |
|
1940 cw.visitSource(UNNAMED, null); |
|
1941 cw.visitEnd(); |
|
1942 byte[] bytes = cw.toByteArray(); |
|
1943 ClassLoader loader = new ClassLoader(null) { |
|
1944 @Override |
|
1945 protected Class<?> findClass(String cn) throws ClassNotFoundException { |
|
1946 if (cn.equals(UNNAMED)) |
|
1947 return super.defineClass(UNNAMED, bytes, 0, bytes.length); |
|
1948 throw new ClassNotFoundException(cn); |
|
1949 } |
|
1950 }; |
|
1951 return loader.loadClass(UNNAMED); |
|
1952 } catch (Exception e) { |
|
1953 throw new InternalError(e); |
|
1954 } |
|
1955 } |
|
1956 |
|
1957 private static final Class<?> PUBLIC_LOOKUP_CLASS; |
|
1958 static { |
|
1959 PrivilegedAction<Class<?>> pa = new PrivilegedAction<Class<?>>() { |
|
1960 public Class<?> run() { |
|
1961 return createClass(); |
|
1962 } |
|
1963 }; |
|
1964 PUBLIC_LOOKUP_CLASS = AccessController.doPrivileged(pa); |
|
1965 } |
|
1966 |
|
1967 /** |
|
1968 * Lookup that is trusted minimally. It can only be used to create |
|
1969 * method handles to publicly accessible members in exported packages. |
|
1970 * |
|
1971 * @see MethodHandles#publicLookup |
|
1972 */ |
|
1973 static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_LOOKUP_CLASS, Lookup.PUBLIC); |
1877 } |
1974 } |
1878 |
1975 |
1879 /** |
1976 /** |
1880 * Produces a method handle giving read access to elements of an array. |
1977 * Produces a method handle giving read access to elements of an array. |
1881 * The type of the method handle will have a return type of the array's |
1978 * The type of the method handle will have a return type of the array's |