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 jdk.internal.reflect;
27
28 import java.lang.reflect.*;
29 import java.util.Set;
30
31 /** Provides reflective access to the constant pools of classes.
32 Currently this is needed to provide reflective access to annotations
33 but may be used by other internal subsystems in the future. */
34
35 public class ConstantPool {
36 // Number of entries in this constant pool (= maximum valid constant pool index)
37 public int getSize() { return getSize0 (constantPoolOop); }
38 public Class<?> getClassAt (int index) { return getClassAt0 (constantPoolOop, index); }
39 public Class<?> getClassAtIfLoaded (int index) { return getClassAtIfLoaded0 (constantPoolOop, index); }
40 // Returns a class reference index for a method or a field.
41 public int getClassRefIndexAt(int index) {
42 return getClassRefIndexAt0(constantPoolOop, index);
43 }
44 // Returns either a Method or Constructor.
45 // Static initializers are returned as Method objects.
46 public Member getMethodAt (int index) { return getMethodAt0 (constantPoolOop, index); }
47 public Member getMethodAtIfLoaded(int index) { return getMethodAtIfLoaded0(constantPoolOop, index); }
48 public Field getFieldAt (int index) { return getFieldAt0 (constantPoolOop, index); }
49 public Field getFieldAtIfLoaded (int index) { return getFieldAtIfLoaded0 (constantPoolOop, index); }
50 // Fetches the class name, member (field, method or interface
51 // method) name, and type descriptor as an array of three Strings
52 public String[] getMemberRefInfoAt (int index) { return getMemberRefInfoAt0 (constantPoolOop, index); }
53 // Returns a name and type reference index for a method, a field or an invokedynamic.
54 public int getNameAndTypeRefIndexAt(int index) {
55 return getNameAndTypeRefIndexAt0(constantPoolOop, index);
56 }
57 // Fetches the name and type from name_and_type index as an array of two Strings
58 public String[] getNameAndTypeRefInfoAt(int index) {
59 return getNameAndTypeRefInfoAt0(constantPoolOop, index);
60 }
61 public int getIntAt (int index) { return getIntAt0 (constantPoolOop, index); }
62 public long getLongAt (int index) { return getLongAt0 (constantPoolOop, index); }
63 public float getFloatAt (int index) { return getFloatAt0 (constantPoolOop, index); }
64 public double getDoubleAt (int index) { return getDoubleAt0 (constantPoolOop, index); }
65 public String getStringAt (int index) { return getStringAt0 (constantPoolOop, index); }
66 public String getUTF8At (int index) { return getUTF8At0 (constantPoolOop, index); }
67 public Tag getTagAt(int index) {
68 return Tag.valueOf(getTagAt0(constantPoolOop, index));
69 }
70
71 public static enum Tag {
72 UTF8(1),
73 INTEGER(3),
74 FLOAT(4),
75 LONG(5),
76 DOUBLE(6),
77 CLASS(7),
78 STRING(8),
79 FIELDREF(9),
80 METHODREF(10),
81 INTERFACEMETHODREF(11),
82 NAMEANDTYPE(12),
83 METHODHANDLE(15),
84 METHODTYPE(16),
85 INVOKEDYNAMIC(18),
86 INVALID(0);
87
88 private final int tagCode;
89
90 private Tag(int tagCode) {
91 this.tagCode = tagCode;
92 }
93
94 private static Tag valueOf(byte v) {
95 for (Tag tag : Tag.values()) {
96 if (tag.tagCode == v) {
97 return tag;
98 }
99 }
100 throw new IllegalArgumentException("Unknown constant pool tag code " + v);
101 }
102 }
103 //---------------------------------------------------------------------------
104 // Internals only below this point
105 //
106
107 static {
108 Reflection.registerFieldsToFilter(ConstantPool.class, Set.of("constantPoolOop"));
109 }
110
111 // HotSpot-internal constant pool object (set by the VM, name known to the VM)
112 private Object constantPoolOop;
113
114 private native int getSize0 (Object constantPoolOop);
115 private native Class<?> getClassAt0 (Object constantPoolOop, int index);
116 private native Class<?> getClassAtIfLoaded0 (Object constantPoolOop, int index);
117 private native int getClassRefIndexAt0 (Object constantPoolOop, int index);
118 private native Member getMethodAt0 (Object constantPoolOop, int index);
119 private native Member getMethodAtIfLoaded0(Object constantPoolOop, int index);
120 private native Field getFieldAt0 (Object constantPoolOop, int index);
121 private native Field getFieldAtIfLoaded0 (Object constantPoolOop, int index);
122 private native String[] getMemberRefInfoAt0 (Object constantPoolOop, int index);
123 private native int getNameAndTypeRefIndexAt0(Object constantPoolOop, int index);
124 private native String[] getNameAndTypeRefInfoAt0(Object constantPoolOop, int index);
125 private native int getIntAt0 (Object constantPoolOop, int index);
126 private native long getLongAt0 (Object constantPoolOop, int index);
127 private native float getFloatAt0 (Object constantPoolOop, int index);
128 private native double getDoubleAt0 (Object constantPoolOop, int index);
129 private native String getStringAt0 (Object constantPoolOop, int index);
130 private native String getUTF8At0 (Object constantPoolOop, int index);
131 private native byte getTagAt0 (Object constantPoolOop, int index);
132 }
|
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 jdk.internal.reflect;
27
28 import jdk.internal.vm.annotation.Stable;
29
30 import java.lang.constant.*;
31 import java.lang.constant.DirectMethodHandleDesc.Kind;
32 import java.lang.reflect.Field;
33 import java.lang.reflect.Member;
34 import java.util.Arrays;
35
36 /** Provides reflective access to the constant pools of classes.
37 Currently this is needed to provide reflective access to annotations
38 and bootstrap methods
39 but may be used by other internal subsystems in the future.
40 <p>
41 When applying this API to internal subsystems, take special account
42 of interactions with the JVMTI class redefinition features.
43 If a class reflects on its constant pool, and then is redefined to
44 have a different constant pool, the data reported by the reflected
45 constant pool may become out of date.
46 */
47
48 public class ConstantPool {
49 // Number of entries in this constant pool (= maximum valid constant pool index)
50 public int getSize() { return getSize1(); }
51 // Class holding this CP
52 public Class<?> getHolder() { return getHolder1(); }
53 public Class<?> getClassAt (int index) { return (Class<?>) getRefAt(index, Tag.CLASS, true); }
54
55 public Class<?> getClassAtIfLoaded (int index) { return (Class<?>) getRefAt(index, Tag.CLASS, false); }
56 // Returns a class reference index for a method or a field.
57 public int getClassRefIndexAt(int index) { return getWordAt1(index, 0); }
58 // Returns either a Method or Constructor.
59 // Static initializers are returned as Method objects.
60 public Member getMethodAt (int index) { return (Member) getRefAt(index, Tag.METHODREF, true); }
61 public Member getMethodAtIfLoaded(int index) { return (Member) getRefAt(index, Tag.METHODREF, false); }
62 public Field getFieldAt (int index) { return (Field) getRefAt(index, Tag.FIELDREF, true); }
63 public Field getFieldAtIfLoaded (int index) { return (Field) getRefAt(index, Tag.FIELDREF, false); }
64 // Fetches the class name, member (field, method or interface
65 // method) name, and type descriptor as an array of three Strings
66 public String[] getMemberRefInfoAt (int index) {
67 return new String[] { getUtf8At(index, 2), getUtf8At(index, 3), getUtf8At(index, 4) };
68 }
69
70 // Returns a name and type reference index for a method, a field or an invokedynamic.
71 public int getNameAndTypeRefIndexAt(int index) { return getWordAt1(index, 1); }
72 // Fetches the name and type from name_and_type index as an array of two Strings
73 public String[] getNameAndTypeRefInfoAt(int index) {
74 return (String[]) getRefAt(index, Tag.NAMEANDTYPE, true);
75 }
76
77 public int getIntAt (int index) { return getIntAt1 (index); }
78 public long getLongAt (int index) { return getLongAt1 (index); }
79 public float getFloatAt (int index) { return getFloatAt1 (index); }
80 public double getDoubleAt (int index) { return getDoubleAt1 (index); }
81 public String getStringAt (int index) { return (String) getRefAt(index, Tag.STRING, true); }
82 public String getUTF8At (int index) { return (String) getRefAt1(index, 0, BAR_SYMREF, null); }
83 public Tag getTagAt (int index) { return Tag.valueOf(getCachedTagAt(index)); }
84
85 public static enum Tag {
86 UTF8(1),
87 INTEGER(3),
88 FLOAT(4),
89 LONG(5),
90 DOUBLE(6),
91 CLASS(7),
92 STRING(8),
93 FIELDREF(9),
94 METHODREF(10),
95 INTERFACEMETHODREF(11),
96 NAMEANDTYPE(12),
97 METHODHANDLE(15),
98 METHODTYPE(16),
99 DYNAMIC(17), // condy
100 INVOKEDYNAMIC(18), // indy
101 INVALID(0);
102
103 private final int tagCode;
104
105 private Tag(int tagCode) {
106 this.tagCode = tagCode;
107 }
108
109 private static @Stable final Tag TAG_TABLE[] = new Tag[20];
110 static {
111 for (Tag tag : values()) {
112 assert(TAG_TABLE[tag.tagCode] == null); // unique
113 TAG_TABLE[tag.tagCode] = tag;
114 }
115 }
116 private static Tag valueOf(byte v) {
117 Tag tag = (v >= 0 && v < TAG_TABLE.length) ? TAG_TABLE[v] : null;
118 if (tag != null) return tag;
119 throw new IllegalArgumentException("Unknown constant pool tag code " + v);
120 }
121 }
122
123 public Object getConstantAt(int index) {
124 return getRefAt1(index, -1, BAR_FORCE, null);
125 }
126 public Object getConstantAt(int index, Object ifNotPresent) {
127 return getRefAt1(index, -1, BAR_IFPRESENT, ifNotPresent);
128 }
129
130 private static final byte BAR_IFPRESENT = 0, BAR_FORCE = 1, BAR_SYMREF = 2;
131
132 public ConstantDesc<?> getConstantDescAt(int index) {
133 Tag tag = getTagAt(index);
134 switch (tag) {
135 case UTF8: return getUTF8At(index);
136 case INTEGER: return getIntAt(index);
137 case LONG: return getLongAt(index);
138 case FLOAT: return getFloatAt(index);
139 case DOUBLE: return getDoubleAt(index);
140 case CLASS: return classDescOf(getUTF8At(index));
141 case STRING: return getStringAt(index);
142 //case FIELDREF:
143 //case METHODREF:
144 //case INTERFACEMETHODREF:
145 //case NAMEANDTYPE:
146 case METHODHANDLE:
147 {
148 int w0 = getWordAt1(index, 0); // refKind
149 int w1 = getWordAt1(index, 1); // member
150 boolean isInterface = getTagAt(w1) == Tag.INTERFACEMETHODREF;
151 Kind kind = Kind.valueOf(w0, isInterface);
152 // Note: Even if isInterface is true Kind.valueOf may discard it.
153 ClassDesc clazz = classDescOf(getUtf8At(w1, 2));
154 return MethodHandleDesc.of(kind, clazz, getUtf8At(w1, 3), getUtf8At(w1, 4));
155 }
156 case METHODTYPE:
157 return MethodTypeDesc.ofDescriptor(getUTF8At(index));
158 //case INVOKEDYNAMIC:
159 case DYNAMIC:
160 return (DynamicConstantDesc) getBootstrappedEntryAt(index);
161 }
162 throw new IllegalArgumentException("no ConstantDesc representation for "+tag+" at CP["+index+"]");
163 }
164
165 public DynamicCallSiteDesc getDynamicCallSiteDescAt(int index) {
166 checkTag(index, Tag.INVOKEDYNAMIC);
167 return (DynamicCallSiteDesc) getBootstrappedEntryAt(index);
168 }
169
170 /**
171 * Get bootstrap arguments for the indy or condy at the given index.
172 * @param index CP index of the selected indy or condy constant
173 * @param start which bootstrap argument to start copying
174 * @param end which bootstrap argument (exclusive) to stop copying
175 * @param buf where to put the copied arguments (must be int[] for BAR_SYMREF, Object[] for other modes)
176 * @param pos where to store arguments into the buf
177 * @param resolving resolution mode: 0=BAR_IFPRESENT, 1=BAR_FORCE, 2=BAR_SYMREF
178 * @param ifNotPresent in BAR_IFPRESENT mode, sentinel to store for values not yet resolved
179 * @param ifNullConstant in BAR_IFPRESENT or BAR_FORCE mode, sentinel to store for an actual {@code null}
180 * @param skipNonNull BAR_IFPRESENT or BAR_FORCE mode, do not store over elements of buf which are non-{@code null}
181 */
182 public void copyOutBootstrapArgumentsAt(int index,
183 int start, int end,
184 Object buf, int pos,
185 byte resolving,
186 Object ifNotPresent,
187 Object ifNullConstant,
188 boolean skipNonNull) {
189 if (start < 0 || end < start) throw new IllegalArgumentException();
190 copyOutRefsAt1(index, start + BSS_HEADER_WORDS, end + BSS_HEADER_WORDS,
191 buf, pos, resolving, ifNotPresent, ifNullConstant, skipNonNull);
192 }
193
194 //---------------------------------------------------------------------------
195 // Internals only below this point
196 //
197
198 private @Stable byte[] tags;
199 private byte getCachedTagAt(int index) {
200 if (tags == null) tags = getTags1();
201 if (index >= 0 && index < tags.length) {
202 return tags[index];
203 }
204 // constant pool can grow over time
205 return getTagAt1(index);
206 }
207
208 private static final int
209 BSS_HEADER_WORDS = 6, // { attrIndex, natIndex, bsm, name, type, argc }
210 BSS_HEADER_BSM = 2, BSS_HEADER_NAME = 3, BSS_HEADER_TYPE = 4, BSS_HEADER_ARGC = 5;
211 private Object getBootstrappedEntryAt(int index) {
212 int argc = getWordAt1(index, BSS_HEADER_ARGC);
213 int[] argIndexes = copyOutWordsAt(index, BSS_HEADER_WORDS, BSS_HEADER_WORDS+argc);
214 int bsmIndex = getWordAt1(index, BSS_HEADER_BSM);
215 DirectMethodHandleDesc bsm = (DirectMethodHandleDesc) getConstantDescAt(bsmIndex);
216 String name = (String) getRefAt1(index, BSS_HEADER_NAME, BAR_FORCE, null);
217 String type = (String) getRefAt1(index, BSS_HEADER_TYPE, BAR_FORCE, null);
218 ConstantDesc<?>[] args = new ConstantDesc<?>[argc];
219 for (int i = 0; i < argc; i++) {
220 args[i] = getConstantDescAt(argIndexes[i]);
221 }
222 if (getTagAt(index) == Tag.DYNAMIC)
223 return DynamicConstantDesc.ofNamed(bsm, name, ClassDesc.ofDescriptor(type), args);
224 else
225 return DynamicCallSiteDesc.of(bsm, name, MethodTypeDesc.ofDescriptor(type), args);
226 }
227
228
229 private ClassDesc classDescOf(String name) {
230 return ClassDesc.of(name.replace('/', '.'));
231 }
232
233 private Object getRefAt(int index, Tag tag, boolean forceResolution) {
234 return getRefAt1(index, -1, forceResolution ? BAR_FORCE : BAR_IFPRESENT, null);
235 }
236
237 private int getWordAt(int index, Tag tag, int word) {
238 checkTag(index, tag);
239 return getWordAt1(index, word);
240 }
241
242 private void checkTag(int index, Tag needTag) {
243 Tag haveTag = getTagAt(index);
244 if (haveTag == needTag) return;
245 switch (needTag) {
246 case METHODREF:
247 if (haveTag == Tag.INTERFACEMETHODREF) return;
248 break;
249 }
250 throw new IllegalArgumentException("expected "+needTag+" but found "+haveTag);
251 }
252
253 private String getUtf8At(int index, int word) {
254 return (String) getRefAt1(index, word, BAR_SYMREF, null);
255 }
256
257
258 private native Class<?> getHolder1 ();
259 private native int getSize1 ();
260 private native int getWordCountAt1 (int index);
261 private native int getWordAt1 (int index, int word);
262 private native Object getRefAt1 (int index, int word, byte resolving, Object ifNotPresent);
263 private native int getIntAt1 (int index);
264 private native long getLongAt1 (int index);
265 private native float getFloatAt1 (int index);
266 private native double getDoubleAt1 (int index);
267 private native byte getTagAt1 (int index);
268 private native byte[] getTags1 ();
269
270 /**
271 * @param index which CP entry to process
272 * @param startWord which word to start copying
273 * @param endWord which word (exclusive) to stop copying
274 * @param buf where to put the copied arguments (must be int[] for BAR_SYMREF, Object[] for other modes)
275 * @param bufPos where to store arguments into the buf
276 * @param resolving resolution mode: 0=BAR_IFPRESENT, 1=BAR_FORCE, 2=BAR_SYMREF
277 * @param ifNotPresent in BAR_IFPRESENT mode, sentinel to store for values not yet resolved
278 * @param ifNullConstant in BAR_IFPRESENT or BAR_FORCE mode, sentinel to store for an actual {@code null}
279 * @param skipNonNull BAR_IFPRESENT or BAR_FORCE mode, do not store over elements of buf which are non-{@code null}
280 */
281 private native void copyOutRefsAt1(int index,
282 int startWord, int endWord,
283 Object buf, int bufPos, // destination
284 byte resolving,
285 Object ifNotPresent,
286 Object ifNullConstant,
287 boolean skipNonNull);
288
289 private int[] copyOutWordsAt(int index, int startWord, int endWord) {
290 int[] buf = new int[endWord - startWord];
291 copyOutRefsAt1(index, startWord, endWord, buf, 0, BAR_SYMREF, null, null, false);
292 return buf;
293 }
294 private Object[] copyOutRefsAt(int index, int startWord, int endWord, boolean forceResolution,
295 Object ifNotPresent, Object ifNullConstant) {
296 Object[] buf = new Object[endWord - startWord];
297 copyOutRefsAt1(index, startWord, endWord, buf, 0, forceResolution ? BAR_FORCE : BAR_IFPRESENT, ifNotPresent, ifNullConstant, false);
298 return buf;
299 }
300
301 }
|