File: | jdk/src/hotspot/share/classfile/classFileParser.cpp |
Warning: | line 2265, column 13 Value stored to 'cp_size' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | #include "precompiled.hpp" |
25 | #include "jvm.h" |
26 | #include "classfile/classFileParser.hpp" |
27 | #include "classfile/classFileStream.hpp" |
28 | #include "classfile/classLoader.hpp" |
29 | #include "classfile/classLoaderData.inline.hpp" |
30 | #include "classfile/classLoadInfo.hpp" |
31 | #include "classfile/defaultMethods.hpp" |
32 | #include "classfile/fieldLayoutBuilder.hpp" |
33 | #include "classfile/javaClasses.inline.hpp" |
34 | #include "classfile/moduleEntry.hpp" |
35 | #include "classfile/packageEntry.hpp" |
36 | #include "classfile/symbolTable.hpp" |
37 | #include "classfile/systemDictionary.hpp" |
38 | #include "classfile/verificationType.hpp" |
39 | #include "classfile/verifier.hpp" |
40 | #include "classfile/vmClasses.hpp" |
41 | #include "classfile/vmSymbols.hpp" |
42 | #include "logging/log.hpp" |
43 | #include "logging/logStream.hpp" |
44 | #include "memory/allocation.hpp" |
45 | #include "memory/metadataFactory.hpp" |
46 | #include "memory/oopFactory.hpp" |
47 | #include "memory/resourceArea.hpp" |
48 | #include "memory/universe.hpp" |
49 | #include "oops/annotations.hpp" |
50 | #include "oops/constantPool.inline.hpp" |
51 | #include "oops/fieldStreams.inline.hpp" |
52 | #include "oops/instanceKlass.inline.hpp" |
53 | #include "oops/instanceMirrorKlass.hpp" |
54 | #include "oops/klass.inline.hpp" |
55 | #include "oops/klassVtable.hpp" |
56 | #include "oops/metadata.hpp" |
57 | #include "oops/method.inline.hpp" |
58 | #include "oops/oop.inline.hpp" |
59 | #include "oops/recordComponent.hpp" |
60 | #include "oops/symbol.hpp" |
61 | #include "prims/jvmtiExport.hpp" |
62 | #include "prims/jvmtiThreadState.hpp" |
63 | #include "runtime/arguments.hpp" |
64 | #include "runtime/fieldDescriptor.inline.hpp" |
65 | #include "runtime/handles.inline.hpp" |
66 | #include "runtime/javaCalls.hpp" |
67 | #include "runtime/os.hpp" |
68 | #include "runtime/perfData.hpp" |
69 | #include "runtime/reflection.hpp" |
70 | #include "runtime/safepointVerifiers.hpp" |
71 | #include "runtime/signature.hpp" |
72 | #include "runtime/timer.hpp" |
73 | #include "services/classLoadingService.hpp" |
74 | #include "services/threadService.hpp" |
75 | #include "utilities/align.hpp" |
76 | #include "utilities/bitMap.inline.hpp" |
77 | #include "utilities/copy.hpp" |
78 | #include "utilities/formatBuffer.hpp" |
79 | #include "utilities/exceptions.hpp" |
80 | #include "utilities/globalDefinitions.hpp" |
81 | #include "utilities/growableArray.hpp" |
82 | #include "utilities/macros.hpp" |
83 | #include "utilities/ostream.hpp" |
84 | #include "utilities/resourceHash.hpp" |
85 | #include "utilities/utf8.hpp" |
86 | |
87 | #if INCLUDE_CDS1 |
88 | #include "classfile/systemDictionaryShared.hpp" |
89 | #endif |
90 | #if INCLUDE_JFR1 |
91 | #include "jfr/support/jfrTraceIdExtension.hpp" |
92 | #endif |
93 | |
94 | // We generally try to create the oops directly when parsing, rather than |
95 | // allocating temporary data structures and copying the bytes twice. A |
96 | // temporary area is only needed when parsing utf8 entries in the constant |
97 | // pool and when parsing line number tables. |
98 | |
99 | // We add assert in debug mode when class format is not checked. |
100 | |
101 | #define JAVA_CLASSFILE_MAGIC0xCAFEBABE 0xCAFEBABE |
102 | #define JAVA_MIN_SUPPORTED_VERSION45 45 |
103 | #define JAVA_PREVIEW_MINOR_VERSION65535 65535 |
104 | |
105 | // Used for two backward compatibility reasons: |
106 | // - to check for new additions to the class file format in JDK1.5 |
107 | // - to check for bug fixes in the format checker in JDK1.5 |
108 | #define JAVA_1_5_VERSION49 49 |
109 | |
110 | // Used for backward compatibility reasons: |
111 | // - to check for javac bug fixes that happened after 1.5 |
112 | // - also used as the max version when running in jdk6 |
113 | #define JAVA_6_VERSION50 50 |
114 | |
115 | // Used for backward compatibility reasons: |
116 | // - to disallow argument and require ACC_STATIC for <clinit> methods |
117 | #define JAVA_7_VERSION51 51 |
118 | |
119 | // Extension method support. |
120 | #define JAVA_8_VERSION52 52 |
121 | |
122 | #define JAVA_9_VERSION53 53 |
123 | |
124 | #define JAVA_10_VERSION54 54 |
125 | |
126 | #define JAVA_11_VERSION55 55 |
127 | |
128 | #define JAVA_12_VERSION56 56 |
129 | |
130 | #define JAVA_13_VERSION57 57 |
131 | |
132 | #define JAVA_14_VERSION58 58 |
133 | |
134 | #define JAVA_15_VERSION59 59 |
135 | |
136 | #define JAVA_16_VERSION60 60 |
137 | |
138 | #define JAVA_17_VERSION61 61 |
139 | |
140 | #define JAVA_18_VERSION62 62 |
141 | |
142 | #define JAVA_19_VERSION63 63 |
143 | |
144 | void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { |
145 | assert((bad_constant == JVM_CONSTANT_Module ||do { if (!((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 147, "assert(" "(bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53" ") failed", "Unexpected bad constant pool entry"); ::breakpoint (); } } while (0) |
146 | bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION,do { if (!((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 147, "assert(" "(bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53" ") failed", "Unexpected bad constant pool entry"); ::breakpoint (); } } while (0) |
147 | "Unexpected bad constant pool entry")do { if (!((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 147, "assert(" "(bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53" ") failed", "Unexpected bad constant pool entry"); ::breakpoint (); } } while (0); |
148 | if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant; |
149 | } |
150 | |
151 | void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream, |
152 | ConstantPool* cp, |
153 | const int length, |
154 | TRAPSJavaThread* __the_thread__) { |
155 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 155, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
156 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 156, "assert(" "cp != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); |
157 | |
158 | // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize |
159 | // this function (_current can be allocated in a register, with scalar |
160 | // replacement of aggregates). The _current pointer is copied back to |
161 | // stream() when this function returns. DON'T call another method within |
162 | // this method that uses stream(). |
163 | const ClassFileStream cfs1 = *stream; |
164 | const ClassFileStream* const cfs = &cfs1; |
165 | |
166 | assert(cfs->allocated_on_stack_or_embedded(), "should be local")do { if (!(cfs->allocated_on_stack_or_embedded())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 166, "assert(" "cfs->allocated_on_stack_or_embedded()" ") failed" , "should be local"); ::breakpoint(); } } while (0); |
167 | debug_only(const u1* const old_current = stream->current();)const u1* const old_current = stream->current(); |
168 | |
169 | // Used for batching symbol allocations. |
170 | const char* names[SymbolTable::symbol_alloc_batch_size]; |
171 | int lengths[SymbolTable::symbol_alloc_batch_size]; |
172 | int indices[SymbolTable::symbol_alloc_batch_size]; |
173 | unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; |
174 | int names_count = 0; |
175 | |
176 | // parsing Index 0 is unused |
177 | for (int index = 1; index < length; index++) { |
178 | // Each of the following case guarantees one more byte in the stream |
179 | // for the following tag or the access_flags following constant pool, |
180 | // so we don't need bounds-check for reading tag. |
181 | const u1 tag = cfs->get_u1_fast(); |
182 | switch (tag) { |
183 | case JVM_CONSTANT_Class : { |
184 | cfs->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // name_index, tag/access_flags |
185 | const u2 name_index = cfs->get_u2_fast(); |
186 | cp->klass_index_at_put(index, name_index); |
187 | break; |
188 | } |
189 | case JVM_CONSTANT_Fieldref: { |
190 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // class_index, name_and_type_index, tag/access_flags |
191 | const u2 class_index = cfs->get_u2_fast(); |
192 | const u2 name_and_type_index = cfs->get_u2_fast(); |
193 | cp->field_at_put(index, class_index, name_and_type_index); |
194 | break; |
195 | } |
196 | case JVM_CONSTANT_Methodref: { |
197 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // class_index, name_and_type_index, tag/access_flags |
198 | const u2 class_index = cfs->get_u2_fast(); |
199 | const u2 name_and_type_index = cfs->get_u2_fast(); |
200 | cp->method_at_put(index, class_index, name_and_type_index); |
201 | break; |
202 | } |
203 | case JVM_CONSTANT_InterfaceMethodref: { |
204 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // class_index, name_and_type_index, tag/access_flags |
205 | const u2 class_index = cfs->get_u2_fast(); |
206 | const u2 name_and_type_index = cfs->get_u2_fast(); |
207 | cp->interface_method_at_put(index, class_index, name_and_type_index); |
208 | break; |
209 | } |
210 | case JVM_CONSTANT_String : { |
211 | cfs->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // string_index, tag/access_flags |
212 | const u2 string_index = cfs->get_u2_fast(); |
213 | cp->string_index_at_put(index, string_index); |
214 | break; |
215 | } |
216 | case JVM_CONSTANT_MethodHandle : |
217 | case JVM_CONSTANT_MethodType: { |
218 | if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { |
219 | classfile_parse_error( |
220 | "Class file version does not support constant tag %u in class file %s", |
221 | tag, THREAD__the_thread__); |
222 | return; |
223 | } |
224 | if (tag == JVM_CONSTANT_MethodHandle) { |
225 | cfs->guarantee_more(4, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // ref_kind, method_index, tag/access_flags |
226 | const u1 ref_kind = cfs->get_u1_fast(); |
227 | const u2 method_index = cfs->get_u2_fast(); |
228 | cp->method_handle_index_at_put(index, ref_kind, method_index); |
229 | } |
230 | else if (tag == JVM_CONSTANT_MethodType) { |
231 | cfs->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // signature_index, tag/access_flags |
232 | const u2 signature_index = cfs->get_u2_fast(); |
233 | cp->method_type_index_at_put(index, signature_index); |
234 | } |
235 | else { |
236 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 236); ::breakpoint(); } while (0); |
237 | } |
238 | break; |
239 | } |
240 | case JVM_CONSTANT_Dynamic : { |
241 | if (_major_version < Verifier::DYNAMICCONSTANT_MAJOR_VERSION) { |
242 | classfile_parse_error( |
243 | "Class file version does not support constant tag %u in class file %s", |
244 | tag, THREAD__the_thread__); |
245 | return; |
246 | } |
247 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bsm_index, nt, tag/access_flags |
248 | const u2 bootstrap_specifier_index = cfs->get_u2_fast(); |
249 | const u2 name_and_type_index = cfs->get_u2_fast(); |
250 | if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) { |
251 | _max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later |
252 | } |
253 | cp->dynamic_constant_at_put(index, bootstrap_specifier_index, name_and_type_index); |
254 | break; |
255 | } |
256 | case JVM_CONSTANT_InvokeDynamic : { |
257 | if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { |
258 | classfile_parse_error( |
259 | "Class file version does not support constant tag %u in class file %s", |
260 | tag, THREAD__the_thread__); |
261 | return; |
262 | } |
263 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bsm_index, nt, tag/access_flags |
264 | const u2 bootstrap_specifier_index = cfs->get_u2_fast(); |
265 | const u2 name_and_type_index = cfs->get_u2_fast(); |
266 | if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) { |
267 | _max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later |
268 | } |
269 | cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index); |
270 | break; |
271 | } |
272 | case JVM_CONSTANT_Integer: { |
273 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bytes, tag/access_flags |
274 | const u4 bytes = cfs->get_u4_fast(); |
275 | cp->int_at_put(index, (jint)bytes); |
276 | break; |
277 | } |
278 | case JVM_CONSTANT_Float: { |
279 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bytes, tag/access_flags |
280 | const u4 bytes = cfs->get_u4_fast(); |
281 | cp->float_at_put(index, *(jfloat*)&bytes); |
282 | break; |
283 | } |
284 | case JVM_CONSTANT_Long: { |
285 | // A mangled type might cause you to overrun allocated memory |
286 | guarantee_property(index + 1 < length, |
287 | "Invalid constant pool entry %u in class file %s", |
288 | index, |
289 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
290 | cfs->guarantee_more(9, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bytes, tag/access_flags |
291 | const u8 bytes = cfs->get_u8_fast(); |
292 | cp->long_at_put(index, bytes); |
293 | index++; // Skip entry following eigth-byte constant, see JVM book p. 98 |
294 | break; |
295 | } |
296 | case JVM_CONSTANT_Double: { |
297 | // A mangled type might cause you to overrun allocated memory |
298 | guarantee_property(index+1 < length, |
299 | "Invalid constant pool entry %u in class file %s", |
300 | index, |
301 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
302 | cfs->guarantee_more(9, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bytes, tag/access_flags |
303 | const u8 bytes = cfs->get_u8_fast(); |
304 | cp->double_at_put(index, *(jdouble*)&bytes); |
305 | index++; // Skip entry following eigth-byte constant, see JVM book p. 98 |
306 | break; |
307 | } |
308 | case JVM_CONSTANT_NameAndType: { |
309 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // name_index, signature_index, tag/access_flags |
310 | const u2 name_index = cfs->get_u2_fast(); |
311 | const u2 signature_index = cfs->get_u2_fast(); |
312 | cp->name_and_type_at_put(index, name_index, signature_index); |
313 | break; |
314 | } |
315 | case JVM_CONSTANT_Utf8 : { |
316 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // utf8_length |
317 | u2 utf8_length = cfs->get_u2_fast(); |
318 | const u1* utf8_buffer = cfs->current(); |
319 | assert(utf8_buffer != NULL, "null utf8 buffer")do { if (!(utf8_buffer != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 319, "assert(" "utf8_buffer != __null" ") failed", "null utf8 buffer" ); ::breakpoint(); } } while (0); |
320 | // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward. |
321 | cfs->guarantee_more(utf8_length+1, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // utf8 string, tag/access_flags |
322 | cfs->skip_u1_fast(utf8_length); |
323 | |
324 | // Before storing the symbol, make sure it's legal |
325 | if (_need_verify) { |
326 | verify_legal_utf8(utf8_buffer, utf8_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
327 | } |
328 | |
329 | unsigned int hash; |
330 | Symbol* const result = SymbolTable::lookup_only((const char*)utf8_buffer, |
331 | utf8_length, |
332 | hash); |
333 | if (result == NULL__null) { |
334 | names[names_count] = (const char*)utf8_buffer; |
335 | lengths[names_count] = utf8_length; |
336 | indices[names_count] = index; |
337 | hashValues[names_count++] = hash; |
338 | if (names_count == SymbolTable::symbol_alloc_batch_size) { |
339 | SymbolTable::new_symbols(_loader_data, |
340 | constantPoolHandle(THREAD__the_thread__, cp), |
341 | names_count, |
342 | names, |
343 | lengths, |
344 | indices, |
345 | hashValues); |
346 | names_count = 0; |
347 | } |
348 | } else { |
349 | cp->symbol_at_put(index, result); |
350 | } |
351 | break; |
352 | } |
353 | case JVM_CONSTANT_Module: |
354 | case JVM_CONSTANT_Package: { |
355 | // Record that an error occurred in these two cases but keep parsing so |
356 | // that ACC_Module can be checked for in the access_flags. Need to |
357 | // throw NoClassDefFoundError in that case. |
358 | if (_major_version >= JAVA_9_VERSION53) { |
359 | cfs->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
360 | cfs->get_u2_fast(); |
361 | set_class_bad_constant_seen(tag); |
362 | break; |
363 | } |
364 | } |
365 | default: { |
366 | classfile_parse_error("Unknown constant tag %u in class file %s", |
367 | tag, |
368 | THREAD__the_thread__); |
369 | return; |
370 | } |
371 | } // end of switch(tag) |
372 | } // end of for |
373 | |
374 | // Allocate the remaining symbols |
375 | if (names_count > 0) { |
376 | SymbolTable::new_symbols(_loader_data, |
377 | constantPoolHandle(THREAD__the_thread__, cp), |
378 | names_count, |
379 | names, |
380 | lengths, |
381 | indices, |
382 | hashValues); |
383 | } |
384 | |
385 | // Copy _current pointer of local copy back to stream. |
386 | assert(stream->current() == old_current, "non-exclusive use of stream")do { if (!(stream->current() == old_current)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 386, "assert(" "stream->current() == old_current" ") failed" , "non-exclusive use of stream"); ::breakpoint(); } } while ( 0); |
387 | stream->set_current(cfs1.current()); |
388 | |
389 | } |
390 | |
391 | static inline bool valid_cp_range(int index, int length) { |
392 | return (index > 0 && index < length); |
393 | } |
394 | |
395 | static inline Symbol* check_symbol_at(const ConstantPool* cp, int index) { |
396 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 396, "assert(" "cp != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); |
397 | if (valid_cp_range(index, cp->length()) && cp->tag_at(index).is_utf8()) { |
398 | return cp->symbol_at(index); |
399 | } |
400 | return NULL__null; |
401 | } |
402 | |
403 | #ifdef ASSERT1 |
404 | PRAGMA_DIAG_PUSHGCC diagnostic push |
405 | PRAGMA_FORMAT_NONLITERAL_IGNOREDGCC diagnostic ignored "-Wformat-nonliteral"
GCC diagnostic ignored "-Wformat-security" |
406 | void ClassFileParser::report_assert_property_failure(const char* msg, TRAPSJavaThread* __the_thread__) const { |
407 | ResourceMark rm(THREAD__the_thread__); |
408 | fatal(msg, _class_name->as_C_string())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 408, msg, _class_name->as_C_string()); ::breakpoint(); } while (0); |
409 | } |
410 | |
411 | void ClassFileParser::report_assert_property_failure(const char* msg, |
412 | int index, |
413 | TRAPSJavaThread* __the_thread__) const { |
414 | ResourceMark rm(THREAD__the_thread__); |
415 | fatal(msg, index, _class_name->as_C_string())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 415, msg, index, _class_name->as_C_string()); ::breakpoint (); } while (0); |
416 | } |
417 | PRAGMA_DIAG_POPGCC diagnostic pop |
418 | #endif |
419 | |
420 | void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream, |
421 | ConstantPool* const cp, |
422 | const int length, |
423 | TRAPSJavaThread* __the_thread__) { |
424 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 424, "assert(" "cp != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); |
425 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 425, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
426 | |
427 | // parsing constant pool entries |
428 | parse_constant_pool_entries(stream, cp, length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
429 | if (class_bad_constant_seen() != 0) { |
430 | // a bad CP entry has been detected previously so stop parsing and just return. |
431 | return; |
432 | } |
433 | |
434 | int index = 1; // declared outside of loops for portability |
435 | int num_klasses = 0; |
436 | |
437 | // first verification pass - validate cross references |
438 | // and fixup class and string constants |
439 | for (index = 1; index < length; index++) { // Index 0 is unused |
440 | const jbyte tag = cp->tag_at(index).value(); |
441 | switch (tag) { |
442 | case JVM_CONSTANT_Class: { |
443 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 443); ::breakpoint(); } while (0); // Only JVM_CONSTANT_ClassIndex should be present |
444 | break; |
445 | } |
446 | case JVM_CONSTANT_Fieldref: |
447 | // fall through |
448 | case JVM_CONSTANT_Methodref: |
449 | // fall through |
450 | case JVM_CONSTANT_InterfaceMethodref: { |
451 | if (!_need_verify) break; |
452 | const int klass_ref_index = cp->klass_ref_index_at(index); |
453 | const int name_and_type_ref_index = cp->name_and_type_ref_index_at(index); |
454 | check_property(valid_klass_reference_at(klass_ref_index), |
455 | "Invalid constant pool index %u in class file %s", |
456 | klass_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
457 | check_property(valid_cp_range(name_and_type_ref_index, length) && |
458 | cp->tag_at(name_and_type_ref_index).is_name_and_type(), |
459 | "Invalid constant pool index %u in class file %s", |
460 | name_and_type_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
461 | break; |
462 | } |
463 | case JVM_CONSTANT_String: { |
464 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 464); ::breakpoint(); } while (0); // Only JVM_CONSTANT_StringIndex should be present |
465 | break; |
466 | } |
467 | case JVM_CONSTANT_Integer: |
468 | break; |
469 | case JVM_CONSTANT_Float: |
470 | break; |
471 | case JVM_CONSTANT_Long: |
472 | case JVM_CONSTANT_Double: { |
473 | index++; |
474 | check_property( |
475 | (index < length && cp->tag_at(index).is_invalid()), |
476 | "Improper constant pool long/double index %u in class file %s", |
477 | index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
478 | break; |
479 | } |
480 | case JVM_CONSTANT_NameAndType: { |
481 | if (!_need_verify) break; |
482 | const int name_ref_index = cp->name_ref_index_at(index); |
483 | const int signature_ref_index = cp->signature_ref_index_at(index); |
484 | check_property(valid_symbol_at(name_ref_index), |
485 | "Invalid constant pool index %u in class file %s", |
486 | name_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
487 | check_property(valid_symbol_at(signature_ref_index), |
488 | "Invalid constant pool index %u in class file %s", |
489 | signature_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
490 | break; |
491 | } |
492 | case JVM_CONSTANT_Utf8: |
493 | break; |
494 | case JVM_CONSTANT_UnresolvedClass: // fall-through |
495 | case JVM_CONSTANT_UnresolvedClassInError: { |
496 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 496); ::breakpoint(); } while (0); // Only JVM_CONSTANT_ClassIndex should be present |
497 | break; |
498 | } |
499 | case JVM_CONSTANT_ClassIndex: { |
500 | const int class_index = cp->klass_index_at(index); |
501 | check_property(valid_symbol_at(class_index), |
502 | "Invalid constant pool index %u in class file %s", |
503 | class_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
504 | cp->unresolved_klass_at_put(index, class_index, num_klasses++); |
505 | break; |
506 | } |
507 | case JVM_CONSTANT_StringIndex: { |
508 | const int string_index = cp->string_index_at(index); |
509 | check_property(valid_symbol_at(string_index), |
510 | "Invalid constant pool index %u in class file %s", |
511 | string_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
512 | Symbol* const sym = cp->symbol_at(string_index); |
513 | cp->unresolved_string_at_put(index, sym); |
514 | break; |
515 | } |
516 | case JVM_CONSTANT_MethodHandle: { |
517 | const int ref_index = cp->method_handle_index_at(index); |
518 | check_property(valid_cp_range(ref_index, length), |
519 | "Invalid constant pool index %u in class file %s", |
520 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
521 | const constantTag tag = cp->tag_at(ref_index); |
522 | const int ref_kind = cp->method_handle_ref_kind_at(index); |
523 | |
524 | switch (ref_kind) { |
525 | case JVM_REF_getField: |
526 | case JVM_REF_getStatic: |
527 | case JVM_REF_putField: |
528 | case JVM_REF_putStatic: { |
529 | check_property( |
530 | tag.is_field(), |
531 | "Invalid constant pool index %u in class file %s (not a field)", |
532 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
533 | break; |
534 | } |
535 | case JVM_REF_invokeVirtual: |
536 | case JVM_REF_newInvokeSpecial: { |
537 | check_property( |
538 | tag.is_method(), |
539 | "Invalid constant pool index %u in class file %s (not a method)", |
540 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
541 | break; |
542 | } |
543 | case JVM_REF_invokeStatic: |
544 | case JVM_REF_invokeSpecial: { |
545 | check_property( |
546 | tag.is_method() || |
547 | ((_major_version >= JAVA_8_VERSION52) && tag.is_interface_method()), |
548 | "Invalid constant pool index %u in class file %s (not a method)", |
549 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
550 | break; |
551 | } |
552 | case JVM_REF_invokeInterface: { |
553 | check_property( |
554 | tag.is_interface_method(), |
555 | "Invalid constant pool index %u in class file %s (not an interface method)", |
556 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
557 | break; |
558 | } |
559 | default: { |
560 | classfile_parse_error( |
561 | "Bad method handle kind at constant pool index %u in class file %s", |
562 | index, THREAD__the_thread__); |
563 | return; |
564 | } |
565 | } // switch(refkind) |
566 | // Keep the ref_index unchanged. It will be indirected at link-time. |
567 | break; |
568 | } // case MethodHandle |
569 | case JVM_CONSTANT_MethodType: { |
570 | const int ref_index = cp->method_type_index_at(index); |
571 | check_property(valid_symbol_at(ref_index), |
572 | "Invalid constant pool index %u in class file %s", |
573 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
574 | break; |
575 | } |
576 | case JVM_CONSTANT_Dynamic: { |
577 | const int name_and_type_ref_index = |
578 | cp->bootstrap_name_and_type_ref_index_at(index); |
579 | |
580 | check_property(valid_cp_range(name_and_type_ref_index, length) && |
581 | cp->tag_at(name_and_type_ref_index).is_name_and_type(), |
582 | "Invalid constant pool index %u in class file %s", |
583 | name_and_type_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
584 | // bootstrap specifier index must be checked later, |
585 | // when BootstrapMethods attr is available |
586 | |
587 | // Mark the constant pool as having a CONSTANT_Dynamic_info structure |
588 | cp->set_has_dynamic_constant(); |
589 | break; |
590 | } |
591 | case JVM_CONSTANT_InvokeDynamic: { |
592 | const int name_and_type_ref_index = |
593 | cp->bootstrap_name_and_type_ref_index_at(index); |
594 | |
595 | check_property(valid_cp_range(name_and_type_ref_index, length) && |
596 | cp->tag_at(name_and_type_ref_index).is_name_and_type(), |
597 | "Invalid constant pool index %u in class file %s", |
598 | name_and_type_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
599 | // bootstrap specifier index must be checked later, |
600 | // when BootstrapMethods attr is available |
601 | break; |
602 | } |
603 | default: { |
604 | fatal("bad constant pool tag value %u", cp->tag_at(index).value())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 604, "bad constant pool tag value %u", cp->tag_at(index) .value()); ::breakpoint(); } while (0); |
605 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 605); ::breakpoint(); } while (0); |
606 | break; |
607 | } |
608 | } // switch(tag) |
609 | } // end of for |
610 | |
611 | cp->allocate_resolved_klasses(_loader_data, num_klasses, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
612 | |
613 | if (!_need_verify) { |
614 | return; |
615 | } |
616 | |
617 | // second verification pass - checks the strings are of the right format. |
618 | // but not yet to the other entries |
619 | for (index = 1; index < length; index++) { |
620 | const jbyte tag = cp->tag_at(index).value(); |
621 | switch (tag) { |
622 | case JVM_CONSTANT_UnresolvedClass: { |
623 | const Symbol* const class_name = cp->klass_name_at(index); |
624 | // check the name |
625 | verify_legal_class_name(class_name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
626 | break; |
627 | } |
628 | case JVM_CONSTANT_NameAndType: { |
629 | if (_need_verify) { |
630 | const int sig_index = cp->signature_ref_index_at(index); |
631 | const int name_index = cp->name_ref_index_at(index); |
632 | const Symbol* const name = cp->symbol_at(name_index); |
633 | const Symbol* const sig = cp->symbol_at(sig_index); |
634 | guarantee_property(sig->utf8_length() != 0, |
635 | "Illegal zero length constant pool entry at %d in class %s", |
636 | sig_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
637 | guarantee_property(name->utf8_length() != 0, |
638 | "Illegal zero length constant pool entry at %d in class %s", |
639 | name_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
640 | |
641 | if (Signature::is_method(sig)) { |
642 | // Format check method name and signature |
643 | verify_legal_method_name(name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
644 | verify_legal_method_signature(name, sig, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
645 | } else { |
646 | // Format check field name and signature |
647 | verify_legal_field_name(name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
648 | verify_legal_field_signature(name, sig, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
649 | } |
650 | } |
651 | break; |
652 | } |
653 | case JVM_CONSTANT_Dynamic: { |
654 | const int name_and_type_ref_index = |
655 | cp->name_and_type_ref_index_at(index); |
656 | // already verified to be utf8 |
657 | const int name_ref_index = |
658 | cp->name_ref_index_at(name_and_type_ref_index); |
659 | // already verified to be utf8 |
660 | const int signature_ref_index = |
661 | cp->signature_ref_index_at(name_and_type_ref_index); |
662 | const Symbol* const name = cp->symbol_at(name_ref_index); |
663 | const Symbol* const signature = cp->symbol_at(signature_ref_index); |
664 | if (_need_verify) { |
665 | // CONSTANT_Dynamic's name and signature are verified above, when iterating NameAndType_info. |
666 | // Need only to be sure signature is the right type. |
667 | if (Signature::is_method(signature)) { |
668 | throwIllegalSignature("CONSTANT_Dynamic", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
669 | } |
670 | } |
671 | break; |
672 | } |
673 | case JVM_CONSTANT_InvokeDynamic: |
674 | case JVM_CONSTANT_Fieldref: |
675 | case JVM_CONSTANT_Methodref: |
676 | case JVM_CONSTANT_InterfaceMethodref: { |
677 | const int name_and_type_ref_index = |
678 | cp->name_and_type_ref_index_at(index); |
679 | // already verified to be utf8 |
680 | const int name_ref_index = |
681 | cp->name_ref_index_at(name_and_type_ref_index); |
682 | // already verified to be utf8 |
683 | const int signature_ref_index = |
684 | cp->signature_ref_index_at(name_and_type_ref_index); |
685 | const Symbol* const name = cp->symbol_at(name_ref_index); |
686 | const Symbol* const signature = cp->symbol_at(signature_ref_index); |
687 | if (tag == JVM_CONSTANT_Fieldref) { |
688 | if (_need_verify) { |
689 | // Field name and signature are verified above, when iterating NameAndType_info. |
690 | // Need only to be sure signature is non-zero length and the right type. |
691 | if (Signature::is_method(signature)) { |
692 | throwIllegalSignature("Field", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
693 | } |
694 | } |
695 | } else { |
696 | if (_need_verify) { |
697 | // Method name and signature are individually verified above, when iterating |
698 | // NameAndType_info. Need to check here that signature is non-zero length and |
699 | // the right type. |
700 | if (!Signature::is_method(signature)) { |
701 | throwIllegalSignature("Method", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
702 | } |
703 | } |
704 | // If a class method name begins with '<', it must be "<init>" and have void signature. |
705 | const unsigned int name_len = name->utf8_length(); |
706 | if (tag == JVM_CONSTANT_Methodref && name_len != 0 && |
707 | name->char_at(0) == JVM_SIGNATURE_SPECIAL) { |
708 | if (name != vmSymbols::object_initializer_name()) { |
709 | classfile_parse_error( |
710 | "Bad method name at constant pool index %u in class file %s", |
711 | name_ref_index, THREAD__the_thread__); |
712 | return; |
713 | } else if (!Signature::is_void_method(signature)) { // must have void signature. |
714 | throwIllegalSignature("Method", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
715 | } |
716 | } |
717 | } |
718 | break; |
719 | } |
720 | case JVM_CONSTANT_MethodHandle: { |
721 | const int ref_index = cp->method_handle_index_at(index); |
722 | const int ref_kind = cp->method_handle_ref_kind_at(index); |
723 | switch (ref_kind) { |
724 | case JVM_REF_invokeVirtual: |
725 | case JVM_REF_invokeStatic: |
726 | case JVM_REF_invokeSpecial: |
727 | case JVM_REF_newInvokeSpecial: { |
728 | const int name_and_type_ref_index = |
729 | cp->name_and_type_ref_index_at(ref_index); |
730 | const int name_ref_index = |
731 | cp->name_ref_index_at(name_and_type_ref_index); |
732 | const Symbol* const name = cp->symbol_at(name_ref_index); |
733 | if (ref_kind == JVM_REF_newInvokeSpecial) { |
734 | if (name != vmSymbols::object_initializer_name()) { |
735 | classfile_parse_error( |
736 | "Bad constructor name at constant pool index %u in class file %s", |
737 | name_ref_index, THREAD__the_thread__); |
738 | return; |
739 | } |
740 | } else { |
741 | if (name == vmSymbols::object_initializer_name()) { |
742 | classfile_parse_error( |
743 | "Bad method name at constant pool index %u in class file %s", |
744 | name_ref_index, THREAD__the_thread__); |
745 | return; |
746 | } |
747 | } |
748 | break; |
749 | } |
750 | // Other ref_kinds are already fully checked in previous pass. |
751 | } // switch(ref_kind) |
752 | break; |
753 | } |
754 | case JVM_CONSTANT_MethodType: { |
755 | const Symbol* const no_name = vmSymbols::type_name(); // place holder |
756 | const Symbol* const signature = cp->method_type_signature_at(index); |
757 | verify_legal_method_signature(no_name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
758 | break; |
759 | } |
760 | case JVM_CONSTANT_Utf8: { |
761 | assert(cp->symbol_at(index)->refcount() != 0, "count corrupted")do { if (!(cp->symbol_at(index)->refcount() != 0)) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 761, "assert(" "cp->symbol_at(index)->refcount() != 0" ") failed", "count corrupted"); ::breakpoint(); } } while (0 ); |
762 | } |
763 | } // switch(tag) |
764 | } // end of for |
765 | } |
766 | |
767 | class NameSigHash: public ResourceObj { |
768 | public: |
769 | const Symbol* _name; // name |
770 | const Symbol* _sig; // signature |
771 | NameSigHash* _next; // Next entry in hash table |
772 | }; |
773 | |
774 | static const int HASH_ROW_SIZE = 256; |
775 | |
776 | static unsigned int hash(const Symbol* name, const Symbol* sig) { |
777 | unsigned int raw_hash = 0; |
778 | raw_hash += ((unsigned int)(uintptr_t)name) >> (LogHeapWordSize + 2); |
779 | raw_hash += ((unsigned int)(uintptr_t)sig) >> LogHeapWordSize; |
780 | |
781 | return (raw_hash + (unsigned int)(uintptr_t)name) % HASH_ROW_SIZE; |
782 | } |
783 | |
784 | |
785 | static void initialize_hashtable(NameSigHash** table) { |
786 | memset((void*)table, 0, sizeof(NameSigHash*) * HASH_ROW_SIZE); |
787 | } |
788 | // Return false if the name/sig combination is found in table. |
789 | // Return true if no duplicate is found. And name/sig is added as a new entry in table. |
790 | // The old format checker uses heap sort to find duplicates. |
791 | // NOTE: caller should guarantee that GC doesn't happen during the life cycle |
792 | // of table since we don't expect Symbol*'s to move. |
793 | static bool put_after_lookup(const Symbol* name, const Symbol* sig, NameSigHash** table) { |
794 | assert(name != NULL, "name in constant pool is NULL")do { if (!(name != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 794, "assert(" "name != __null" ") failed", "name in constant pool is NULL" ); ::breakpoint(); } } while (0); |
795 | |
796 | // First lookup for duplicates |
797 | int index = hash(name, sig); |
798 | NameSigHash* entry = table[index]; |
799 | while (entry != NULL__null) { |
800 | if (entry->_name == name && entry->_sig == sig) { |
801 | return false; |
802 | } |
803 | entry = entry->_next; |
804 | } |
805 | |
806 | // No duplicate is found, allocate a new entry and fill it. |
807 | entry = new NameSigHash(); |
808 | entry->_name = name; |
809 | entry->_sig = sig; |
810 | |
811 | // Insert into hash table |
812 | entry->_next = table[index]; |
813 | table[index] = entry; |
814 | |
815 | return true; |
816 | } |
817 | |
818 | // Side-effects: populates the _local_interfaces field |
819 | void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, |
820 | const int itfs_len, |
821 | ConstantPool* const cp, |
822 | bool* const has_nonstatic_concrete_methods, |
823 | TRAPSJavaThread* __the_thread__) { |
824 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 824, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
825 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 825, "assert(" "cp != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); |
826 | assert(has_nonstatic_concrete_methods != NULL, "invariant")do { if (!(has_nonstatic_concrete_methods != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 826, "assert(" "has_nonstatic_concrete_methods != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
827 | |
828 | if (itfs_len == 0) { |
829 | _local_interfaces = Universe::the_empty_instance_klass_array(); |
830 | } else { |
831 | assert(itfs_len > 0, "only called for len>0")do { if (!(itfs_len > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 831, "assert(" "itfs_len > 0" ") failed", "only called for len>0" ); ::breakpoint(); } } while (0); |
832 | _local_interfaces = MetadataFactory::new_array<InstanceKlass*>(_loader_data, itfs_len, NULL__null, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
833 | |
834 | int index; |
835 | for (index = 0; index < itfs_len; index++) { |
836 | const u2 interface_index = stream->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
837 | Klass* interf; |
838 | check_property( |
839 | valid_klass_reference_at(interface_index), |
840 | "Interface name has bad constant pool index %u in class file %s", |
841 | interface_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
842 | if (cp->tag_at(interface_index).is_klass()) { |
843 | interf = cp->resolved_klass_at(interface_index); |
844 | } else { |
845 | Symbol* const unresolved_klass = cp->klass_name_at(interface_index); |
846 | |
847 | // Don't need to check legal name because it's checked when parsing constant pool. |
848 | // But need to make sure it's not an array type. |
849 | guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY, |
850 | "Bad interface name in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
851 | |
852 | // Call resolve_super so class circularity is checked |
853 | interf = SystemDictionary::resolve_super_or_fail( |
854 | _class_name, |
855 | unresolved_klass, |
856 | Handle(THREAD__the_thread__, _loader_data->class_loader()), |
857 | _protection_domain, |
858 | false, |
859 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
860 | } |
861 | |
862 | if (!interf->is_interface()) { |
863 | THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; } |
864 | err_msg("class %s can not implement %s, because it is not an interface (%s)",{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; } |
865 | _class_name->as_klass_external_name(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; } |
866 | interf->external_name(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; } |
867 | interf->class_in_module_of_loader())){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; }; |
868 | } |
869 | |
870 | if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) { |
871 | *has_nonstatic_concrete_methods = true; |
872 | } |
873 | _local_interfaces->at_put(index, InstanceKlass::cast(interf)); |
874 | } |
875 | |
876 | if (!_need_verify || itfs_len <= 1) { |
877 | return; |
878 | } |
879 | |
880 | // Check if there's any duplicates in interfaces |
881 | ResourceMark rm(THREAD__the_thread__); |
882 | NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)) |
883 | NameSigHash*,(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)) |
884 | HASH_ROW_SIZE)(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)); |
885 | initialize_hashtable(interface_names); |
886 | bool dup = false; |
887 | const Symbol* name = NULL__null; |
888 | { |
889 | debug_only(NoSafepointVerifier nsv;)NoSafepointVerifier nsv; |
890 | for (index = 0; index < itfs_len; index++) { |
891 | const InstanceKlass* const k = _local_interfaces->at(index); |
892 | name = k->name(); |
893 | // If no duplicates, add (name, NULL) in hashtable interface_names. |
894 | if (!put_after_lookup(name, NULL__null, interface_names)) { |
895 | dup = true; |
896 | break; |
897 | } |
898 | } |
899 | } |
900 | if (dup) { |
901 | classfile_parse_error("Duplicate interface name \"%s\" in class file %s", |
902 | name->as_C_string(), THREAD__the_thread__); |
903 | } |
904 | } |
905 | } |
906 | |
907 | void ClassFileParser::verify_constantvalue(const ConstantPool* const cp, |
908 | int constantvalue_index, |
909 | int signature_index, |
910 | TRAPSJavaThread* __the_thread__) const { |
911 | // Make sure the constant pool entry is of a type appropriate to this field |
912 | guarantee_property( |
913 | (constantvalue_index > 0 && |
914 | constantvalue_index < cp->length()), |
915 | "Bad initial value index %u in ConstantValue attribute in class file %s", |
916 | constantvalue_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
917 | |
918 | const constantTag value_type = cp->tag_at(constantvalue_index); |
919 | switch(cp->basic_type_for_signature_at(signature_index)) { |
920 | case T_LONG: { |
921 | guarantee_property(value_type.is_long(), |
922 | "Inconsistent constant value type in class file %s", |
923 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
924 | break; |
925 | } |
926 | case T_FLOAT: { |
927 | guarantee_property(value_type.is_float(), |
928 | "Inconsistent constant value type in class file %s", |
929 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
930 | break; |
931 | } |
932 | case T_DOUBLE: { |
933 | guarantee_property(value_type.is_double(), |
934 | "Inconsistent constant value type in class file %s", |
935 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
936 | break; |
937 | } |
938 | case T_BYTE: |
939 | case T_CHAR: |
940 | case T_SHORT: |
941 | case T_BOOLEAN: |
942 | case T_INT: { |
943 | guarantee_property(value_type.is_int(), |
944 | "Inconsistent constant value type in class file %s", |
945 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
946 | break; |
947 | } |
948 | case T_OBJECT: { |
949 | guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;") |
950 | && value_type.is_string()), |
951 | "Bad string initial value in class file %s", |
952 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
953 | break; |
954 | } |
955 | default: { |
956 | classfile_parse_error("Unable to set initial value %u in class file %s", |
957 | constantvalue_index, |
958 | THREAD__the_thread__); |
959 | } |
960 | } |
961 | } |
962 | |
963 | class AnnotationCollector : public ResourceObj{ |
964 | public: |
965 | enum Location { _in_field, _in_method, _in_class }; |
966 | enum ID { |
967 | _unknown = 0, |
968 | _method_CallerSensitive, |
969 | _method_ForceInline, |
970 | _method_DontInline, |
971 | _method_InjectedProfile, |
972 | _method_LambdaForm_Compiled, |
973 | _method_Hidden, |
974 | _method_Scoped, |
975 | _method_IntrinsicCandidate, |
976 | _jdk_internal_vm_annotation_Contended, |
977 | _field_Stable, |
978 | _jdk_internal_vm_annotation_ReservedStackAccess, |
979 | _jdk_internal_ValueBased, |
980 | _annotation_LIMIT |
981 | }; |
982 | const Location _location; |
983 | int _annotations_present; |
984 | u2 _contended_group; |
985 | |
986 | AnnotationCollector(Location location) |
987 | : _location(location), _annotations_present(0), _contended_group(0) |
988 | { |
989 | assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, "")do { if (!((int)_annotation_LIMIT <= (int)sizeof(_annotations_present ) * BitsPerByte)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 989, "assert(" "(int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte" ") failed", ""); ::breakpoint(); } } while (0); |
990 | } |
991 | // If this annotation name has an ID, report it (or _none). |
992 | ID annotation_index(const ClassLoaderData* loader_data, const Symbol* name, bool can_access_vm_annotations); |
993 | // Set the annotation name: |
994 | void set_annotation(ID id) { |
995 | assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob")do { if (!((int)id >= 0 && (int)id < (int)_annotation_LIMIT )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 995, "assert(" "(int)id >= 0 && (int)id < (int)_annotation_LIMIT" ") failed", "oob"); ::breakpoint(); } } while (0); |
996 | _annotations_present |= nth_bit((int)id)((((int)id) >= BitsPerWord) ? 0 : (OneBit << ((int)id ))); |
997 | } |
998 | |
999 | void remove_annotation(ID id) { |
1000 | assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob")do { if (!((int)id >= 0 && (int)id < (int)_annotation_LIMIT )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1000, "assert(" "(int)id >= 0 && (int)id < (int)_annotation_LIMIT" ") failed", "oob"); ::breakpoint(); } } while (0); |
1001 | _annotations_present &= ~nth_bit((int)id)((((int)id) >= BitsPerWord) ? 0 : (OneBit << ((int)id ))); |
1002 | } |
1003 | |
1004 | // Report if the annotation is present. |
1005 | bool has_any_annotations() const { return _annotations_present != 0; } |
1006 | bool has_annotation(ID id) const { return (nth_bit((int)id)((((int)id) >= BitsPerWord) ? 0 : (OneBit << ((int)id ))) & _annotations_present) != 0; } |
1007 | |
1008 | void set_contended_group(u2 group) { _contended_group = group; } |
1009 | u2 contended_group() const { return _contended_group; } |
1010 | |
1011 | bool is_contended() const { return has_annotation(_jdk_internal_vm_annotation_Contended); } |
1012 | |
1013 | void set_stable(bool stable) { set_annotation(_field_Stable); } |
1014 | bool is_stable() const { return has_annotation(_field_Stable); } |
1015 | }; |
1016 | |
1017 | // This class also doubles as a holder for metadata cleanup. |
1018 | class ClassFileParser::FieldAnnotationCollector : public AnnotationCollector { |
1019 | private: |
1020 | ClassLoaderData* _loader_data; |
1021 | AnnotationArray* _field_annotations; |
1022 | AnnotationArray* _field_type_annotations; |
1023 | public: |
1024 | FieldAnnotationCollector(ClassLoaderData* loader_data) : |
1025 | AnnotationCollector(_in_field), |
1026 | _loader_data(loader_data), |
1027 | _field_annotations(NULL__null), |
1028 | _field_type_annotations(NULL__null) {} |
1029 | ~FieldAnnotationCollector(); |
1030 | void apply_to(FieldInfo* f); |
1031 | AnnotationArray* field_annotations() { return _field_annotations; } |
1032 | AnnotationArray* field_type_annotations() { return _field_type_annotations; } |
1033 | |
1034 | void set_field_annotations(AnnotationArray* a) { _field_annotations = a; } |
1035 | void set_field_type_annotations(AnnotationArray* a) { _field_type_annotations = a; } |
1036 | }; |
1037 | |
1038 | class MethodAnnotationCollector : public AnnotationCollector{ |
1039 | public: |
1040 | MethodAnnotationCollector() : AnnotationCollector(_in_method) { } |
1041 | void apply_to(const methodHandle& m); |
1042 | }; |
1043 | |
1044 | class ClassFileParser::ClassAnnotationCollector : public AnnotationCollector{ |
1045 | public: |
1046 | ClassAnnotationCollector() : AnnotationCollector(_in_class) { } |
1047 | void apply_to(InstanceKlass* ik); |
1048 | }; |
1049 | |
1050 | |
1051 | static int skip_annotation_value(const u1*, int, int); // fwd decl |
1052 | |
1053 | // Safely increment index by val if does not pass limit |
1054 | #define SAFE_ADD(index, limit, val)if (index >= limit - val) return limit; index += val; \ |
1055 | if (index >= limit - val) return limit; \ |
1056 | index += val; |
1057 | |
1058 | // Skip an annotation. Return >=limit if there is any problem. |
1059 | static int skip_annotation(const u1* buffer, int limit, int index) { |
1060 | assert(buffer != NULL, "invariant")do { if (!(buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1060, "assert(" "buffer != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1061 | // annotation := atype:u2 do(nmem:u2) {member:u2 value} |
1062 | // value := switch (tag:u1) { ... } |
1063 | SAFE_ADD(index, limit, 4)if (index >= limit - 4) return limit; index += 4;; // skip atype and read nmem |
1064 | int nmem = Bytes::get_Java_u2((address)buffer + index - 2); |
1065 | while (--nmem >= 0 && index < limit) { |
1066 | SAFE_ADD(index, limit, 2)if (index >= limit - 2) return limit; index += 2;; // skip member |
1067 | index = skip_annotation_value(buffer, limit, index); |
1068 | } |
1069 | return index; |
1070 | } |
1071 | |
1072 | // Skip an annotation value. Return >=limit if there is any problem. |
1073 | static int skip_annotation_value(const u1* buffer, int limit, int index) { |
1074 | assert(buffer != NULL, "invariant")do { if (!(buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1074, "assert(" "buffer != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1075 | |
1076 | // value := switch (tag:u1) { |
1077 | // case B, C, I, S, Z, D, F, J, c: con:u2; |
1078 | // case e: e_class:u2 e_name:u2; |
1079 | // case s: s_con:u2; |
1080 | // case [: do(nval:u2) {value}; |
1081 | // case @: annotation; |
1082 | // case s: s_con:u2; |
1083 | // } |
1084 | SAFE_ADD(index, limit, 1)if (index >= limit - 1) return limit; index += 1;; // read tag |
1085 | const u1 tag = buffer[index - 1]; |
1086 | switch (tag) { |
1087 | case 'B': |
1088 | case 'C': |
1089 | case 'I': |
1090 | case 'S': |
1091 | case 'Z': |
1092 | case 'D': |
1093 | case 'F': |
1094 | case 'J': |
1095 | case 'c': |
1096 | case 's': |
1097 | SAFE_ADD(index, limit, 2)if (index >= limit - 2) return limit; index += 2;; // skip con or s_con |
1098 | break; |
1099 | case 'e': |
1100 | SAFE_ADD(index, limit, 4)if (index >= limit - 4) return limit; index += 4;; // skip e_class, e_name |
1101 | break; |
1102 | case '[': |
1103 | { |
1104 | SAFE_ADD(index, limit, 2)if (index >= limit - 2) return limit; index += 2;; // read nval |
1105 | int nval = Bytes::get_Java_u2((address)buffer + index - 2); |
1106 | while (--nval >= 0 && index < limit) { |
1107 | index = skip_annotation_value(buffer, limit, index); |
1108 | } |
1109 | } |
1110 | break; |
1111 | case '@': |
1112 | index = skip_annotation(buffer, limit, index); |
1113 | break; |
1114 | default: |
1115 | return limit; // bad tag byte |
1116 | } |
1117 | return index; |
1118 | } |
1119 | |
1120 | // Sift through annotations, looking for those significant to the VM: |
1121 | static void parse_annotations(const ConstantPool* const cp, |
1122 | const u1* buffer, int limit, |
1123 | AnnotationCollector* coll, |
1124 | ClassLoaderData* loader_data, |
1125 | const bool can_access_vm_annotations) { |
1126 | |
1127 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1127, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1128 | assert(buffer != NULL, "invariant")do { if (!(buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1128, "assert(" "buffer != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1129 | assert(coll != NULL, "invariant")do { if (!(coll != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1129, "assert(" "coll != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1130 | assert(loader_data != NULL, "invariant")do { if (!(loader_data != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1130, "assert(" "loader_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1131 | |
1132 | // annotations := do(nann:u2) {annotation} |
1133 | int index = 2; // read nann |
1134 | if (index >= limit) return; |
1135 | int nann = Bytes::get_Java_u2((address)buffer + index - 2); |
1136 | enum { // initial annotation layout |
1137 | atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;' |
1138 | count_off = 2, // u2 such as 1 (one value) |
1139 | member_off = 4, // utf8 such as 'value' |
1140 | tag_off = 6, // u1 such as 'c' (type) or 'e' (enum) |
1141 | e_tag_val = 'e', |
1142 | e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;' |
1143 | e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME' |
1144 | e_size = 11, // end of 'e' annotation |
1145 | c_tag_val = 'c', // payload is type |
1146 | c_con_off = 7, // utf8 payload, such as 'I' |
1147 | c_size = 9, // end of 'c' annotation |
1148 | s_tag_val = 's', // payload is String |
1149 | s_con_off = 7, // utf8 payload, such as 'Ljava/lang/String;' |
1150 | s_size = 9, |
1151 | min_size = 6 // smallest possible size (zero members) |
1152 | }; |
1153 | // Cannot add min_size to index in case of overflow MAX_INT |
1154 | while ((--nann) >= 0 && (index - 2 <= limit - min_size)) { |
1155 | int index0 = index; |
1156 | index = skip_annotation(buffer, limit, index); |
1157 | const u1* const abase = buffer + index0; |
1158 | const int atype = Bytes::get_Java_u2((address)abase + atype_off); |
1159 | const int count = Bytes::get_Java_u2((address)abase + count_off); |
1160 | const Symbol* const aname = check_symbol_at(cp, atype); |
1161 | if (aname == NULL__null) break; // invalid annotation name |
1162 | const Symbol* member = NULL__null; |
1163 | if (count >= 1) { |
1164 | const int member_index = Bytes::get_Java_u2((address)abase + member_off); |
1165 | member = check_symbol_at(cp, member_index); |
1166 | if (member == NULL__null) break; // invalid member name |
1167 | } |
1168 | |
1169 | // Here is where parsing particular annotations will take place. |
1170 | AnnotationCollector::ID id = coll->annotation_index(loader_data, aname, can_access_vm_annotations); |
1171 | if (AnnotationCollector::_unknown == id) continue; |
1172 | coll->set_annotation(id); |
1173 | |
1174 | if (AnnotationCollector::_jdk_internal_vm_annotation_Contended == id) { |
1175 | // @Contended can optionally specify the contention group. |
1176 | // |
1177 | // Contended group defines the equivalence class over the fields: |
1178 | // the fields within the same contended group are not treated distinct. |
1179 | // The only exception is default group, which does not incur the |
1180 | // equivalence. Naturally, contention group for classes is meaningless. |
1181 | // |
1182 | // While the contention group is specified as String, annotation |
1183 | // values are already interned, and we might as well use the constant |
1184 | // pool index as the group tag. |
1185 | // |
1186 | u2 group_index = 0; // default contended group |
1187 | if (count == 1 |
1188 | && s_size == (index - index0) // match size |
1189 | && s_tag_val == *(abase + tag_off) |
1190 | && member == vmSymbols::value_name()) { |
1191 | group_index = Bytes::get_Java_u2((address)abase + s_con_off); |
1192 | if (cp->symbol_at(group_index)->utf8_length() == 0) { |
1193 | group_index = 0; // default contended group |
1194 | } |
1195 | } |
1196 | coll->set_contended_group(group_index); |
1197 | } |
1198 | } |
1199 | } |
1200 | |
1201 | |
1202 | // Parse attributes for a field. |
1203 | void ClassFileParser::parse_field_attributes(const ClassFileStream* const cfs, |
1204 | u2 attributes_count, |
1205 | bool is_static, u2 signature_index, |
1206 | u2* const constantvalue_index_addr, |
1207 | bool* const is_synthetic_addr, |
1208 | u2* const generic_signature_index_addr, |
1209 | ClassFileParser::FieldAnnotationCollector* parsed_annotations, |
1210 | TRAPSJavaThread* __the_thread__) { |
1211 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1211, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1212 | assert(constantvalue_index_addr != NULL, "invariant")do { if (!(constantvalue_index_addr != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1212, "assert(" "constantvalue_index_addr != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1213 | assert(is_synthetic_addr != NULL, "invariant")do { if (!(is_synthetic_addr != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1213, "assert(" "is_synthetic_addr != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1214 | assert(generic_signature_index_addr != NULL, "invariant")do { if (!(generic_signature_index_addr != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1214, "assert(" "generic_signature_index_addr != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1215 | assert(parsed_annotations != NULL, "invariant")do { if (!(parsed_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1215, "assert(" "parsed_annotations != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1216 | assert(attributes_count > 0, "attributes_count should be greater than 0")do { if (!(attributes_count > 0)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1216, "assert(" "attributes_count > 0" ") failed", "attributes_count should be greater than 0" ); ::breakpoint(); } } while (0); |
1217 | |
1218 | u2 constantvalue_index = 0; |
1219 | u2 generic_signature_index = 0; |
1220 | bool is_synthetic = false; |
1221 | const u1* runtime_visible_annotations = NULL__null; |
1222 | int runtime_visible_annotations_length = 0; |
1223 | const u1* runtime_invisible_annotations = NULL__null; |
1224 | int runtime_invisible_annotations_length = 0; |
1225 | const u1* runtime_visible_type_annotations = NULL__null; |
1226 | int runtime_visible_type_annotations_length = 0; |
1227 | const u1* runtime_invisible_type_annotations = NULL__null; |
1228 | int runtime_invisible_type_annotations_length = 0; |
1229 | bool runtime_invisible_annotations_exists = false; |
1230 | bool runtime_invisible_type_annotations_exists = false; |
1231 | const ConstantPool* const cp = _cp; |
1232 | |
1233 | while (attributes_count--) { |
1234 | cfs->guarantee_more(6, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // attribute_name_index, attribute_length |
1235 | const u2 attribute_name_index = cfs->get_u2_fast(); |
1236 | const u4 attribute_length = cfs->get_u4_fast(); |
1237 | check_property(valid_symbol_at(attribute_name_index), |
1238 | "Invalid field attribute index %u in class file %s", |
1239 | attribute_name_index, |
1240 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1241 | |
1242 | const Symbol* const attribute_name = cp->symbol_at(attribute_name_index); |
1243 | if (is_static && attribute_name == vmSymbols::tag_constant_value()) { |
1244 | // ignore if non-static |
1245 | if (constantvalue_index != 0) { |
1246 | classfile_parse_error("Duplicate ConstantValue attribute in class file %s", THREAD__the_thread__); |
1247 | return; |
1248 | } |
1249 | check_property( |
1250 | attribute_length == 2, |
1251 | "Invalid ConstantValue field attribute length %u in class file %s", |
1252 | attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1253 | |
1254 | constantvalue_index = cfs->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1255 | if (_need_verify) { |
1256 | verify_constantvalue(cp, constantvalue_index, signature_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1257 | } |
1258 | } else if (attribute_name == vmSymbols::tag_synthetic()) { |
1259 | if (attribute_length != 0) { |
1260 | classfile_parse_error( |
1261 | "Invalid Synthetic field attribute length %u in class file %s", |
1262 | attribute_length, THREAD__the_thread__); |
1263 | return; |
1264 | } |
1265 | is_synthetic = true; |
1266 | } else if (attribute_name == vmSymbols::tag_deprecated()) { // 4276120 |
1267 | if (attribute_length != 0) { |
1268 | classfile_parse_error( |
1269 | "Invalid Deprecated field attribute length %u in class file %s", |
1270 | attribute_length, THREAD__the_thread__); |
1271 | return; |
1272 | } |
1273 | } else if (_major_version >= JAVA_1_5_VERSION49) { |
1274 | if (attribute_name == vmSymbols::tag_signature()) { |
1275 | if (generic_signature_index != 0) { |
1276 | classfile_parse_error( |
1277 | "Multiple Signature attributes for field in class file %s", THREAD__the_thread__); |
1278 | return; |
1279 | } |
1280 | if (attribute_length != 2) { |
1281 | classfile_parse_error( |
1282 | "Wrong size %u for field's Signature attribute in class file %s", |
1283 | attribute_length, THREAD__the_thread__); |
1284 | return; |
1285 | } |
1286 | generic_signature_index = parse_generic_signature_attribute(cfs, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1287 | } else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) { |
1288 | if (runtime_visible_annotations != NULL__null) { |
1289 | classfile_parse_error( |
1290 | "Multiple RuntimeVisibleAnnotations attributes for field in class file %s", THREAD__the_thread__); |
1291 | return; |
1292 | } |
1293 | runtime_visible_annotations_length = attribute_length; |
1294 | runtime_visible_annotations = cfs->current(); |
1295 | assert(runtime_visible_annotations != NULL, "null visible annotations")do { if (!(runtime_visible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1295, "assert(" "runtime_visible_annotations != __null" ") failed" , "null visible annotations"); ::breakpoint(); } } while (0); |
1296 | cfs->guarantee_more(runtime_visible_annotations_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1297 | parse_annotations(cp, |
1298 | runtime_visible_annotations, |
1299 | runtime_visible_annotations_length, |
1300 | parsed_annotations, |
1301 | _loader_data, |
1302 | _can_access_vm_annotations); |
1303 | cfs->skip_u1_fast(runtime_visible_annotations_length); |
1304 | } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { |
1305 | if (runtime_invisible_annotations_exists) { |
1306 | classfile_parse_error( |
1307 | "Multiple RuntimeInvisibleAnnotations attributes for field in class file %s", THREAD__the_thread__); |
1308 | return; |
1309 | } |
1310 | runtime_invisible_annotations_exists = true; |
1311 | if (PreserveAllAnnotations) { |
1312 | runtime_invisible_annotations_length = attribute_length; |
1313 | runtime_invisible_annotations = cfs->current(); |
1314 | assert(runtime_invisible_annotations != NULL, "null invisible annotations")do { if (!(runtime_invisible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1314, "assert(" "runtime_invisible_annotations != __null" ") failed" , "null invisible annotations"); ::breakpoint(); } } while (0 ); |
1315 | } |
1316 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1317 | } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { |
1318 | if (runtime_visible_type_annotations != NULL__null) { |
1319 | classfile_parse_error( |
1320 | "Multiple RuntimeVisibleTypeAnnotations attributes for field in class file %s", THREAD__the_thread__); |
1321 | return; |
1322 | } |
1323 | runtime_visible_type_annotations_length = attribute_length; |
1324 | runtime_visible_type_annotations = cfs->current(); |
1325 | assert(runtime_visible_type_annotations != NULL, "null visible type annotations")do { if (!(runtime_visible_type_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1325, "assert(" "runtime_visible_type_annotations != __null" ") failed", "null visible type annotations"); ::breakpoint() ; } } while (0); |
1326 | cfs->skip_u1(runtime_visible_type_annotations_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1327 | } else if (attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { |
1328 | if (runtime_invisible_type_annotations_exists) { |
1329 | classfile_parse_error( |
1330 | "Multiple RuntimeInvisibleTypeAnnotations attributes for field in class file %s", THREAD__the_thread__); |
1331 | return; |
1332 | } else { |
1333 | runtime_invisible_type_annotations_exists = true; |
1334 | } |
1335 | if (PreserveAllAnnotations) { |
1336 | runtime_invisible_type_annotations_length = attribute_length; |
1337 | runtime_invisible_type_annotations = cfs->current(); |
1338 | assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations")do { if (!(runtime_invisible_type_annotations != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1338, "assert(" "runtime_invisible_type_annotations != __null" ") failed", "null invisible type annotations"); ::breakpoint (); } } while (0); |
1339 | } |
1340 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1341 | } else { |
1342 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // Skip unknown attributes |
1343 | } |
1344 | } else { |
1345 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // Skip unknown attributes |
1346 | } |
1347 | } |
1348 | |
1349 | *constantvalue_index_addr = constantvalue_index; |
1350 | *is_synthetic_addr = is_synthetic; |
1351 | *generic_signature_index_addr = generic_signature_index; |
1352 | AnnotationArray* a = assemble_annotations(runtime_visible_annotations, |
1353 | runtime_visible_annotations_length, |
1354 | runtime_invisible_annotations, |
1355 | runtime_invisible_annotations_length, |
1356 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1357 | parsed_annotations->set_field_annotations(a); |
1358 | a = assemble_annotations(runtime_visible_type_annotations, |
1359 | runtime_visible_type_annotations_length, |
1360 | runtime_invisible_type_annotations, |
1361 | runtime_invisible_type_annotations_length, |
1362 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1363 | parsed_annotations->set_field_type_annotations(a); |
1364 | return; |
1365 | } |
1366 | |
1367 | |
1368 | // Field allocation types. Used for computing field offsets. |
1369 | |
1370 | enum FieldAllocationType { |
1371 | STATIC_OOP, // Oops |
1372 | STATIC_BYTE, // Boolean, Byte, char |
1373 | STATIC_SHORT, // shorts |
1374 | STATIC_WORD, // ints |
1375 | STATIC_DOUBLE, // aligned long or double |
1376 | NONSTATIC_OOP, |
1377 | NONSTATIC_BYTE, |
1378 | NONSTATIC_SHORT, |
1379 | NONSTATIC_WORD, |
1380 | NONSTATIC_DOUBLE, |
1381 | MAX_FIELD_ALLOCATION_TYPE, |
1382 | BAD_ALLOCATION_TYPE = -1 |
1383 | }; |
1384 | |
1385 | static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = { |
1386 | BAD_ALLOCATION_TYPE, // 0 |
1387 | BAD_ALLOCATION_TYPE, // 1 |
1388 | BAD_ALLOCATION_TYPE, // 2 |
1389 | BAD_ALLOCATION_TYPE, // 3 |
1390 | NONSTATIC_BYTE , // T_BOOLEAN = 4, |
1391 | NONSTATIC_SHORT, // T_CHAR = 5, |
1392 | NONSTATIC_WORD, // T_FLOAT = 6, |
1393 | NONSTATIC_DOUBLE, // T_DOUBLE = 7, |
1394 | NONSTATIC_BYTE, // T_BYTE = 8, |
1395 | NONSTATIC_SHORT, // T_SHORT = 9, |
1396 | NONSTATIC_WORD, // T_INT = 10, |
1397 | NONSTATIC_DOUBLE, // T_LONG = 11, |
1398 | NONSTATIC_OOP, // T_OBJECT = 12, |
1399 | NONSTATIC_OOP, // T_ARRAY = 13, |
1400 | BAD_ALLOCATION_TYPE, // T_VOID = 14, |
1401 | BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, |
1402 | BAD_ALLOCATION_TYPE, // T_NARROWOOP = 16, |
1403 | BAD_ALLOCATION_TYPE, // T_METADATA = 17, |
1404 | BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18, |
1405 | BAD_ALLOCATION_TYPE, // T_CONFLICT = 19, |
1406 | BAD_ALLOCATION_TYPE, // 0 |
1407 | BAD_ALLOCATION_TYPE, // 1 |
1408 | BAD_ALLOCATION_TYPE, // 2 |
1409 | BAD_ALLOCATION_TYPE, // 3 |
1410 | STATIC_BYTE , // T_BOOLEAN = 4, |
1411 | STATIC_SHORT, // T_CHAR = 5, |
1412 | STATIC_WORD, // T_FLOAT = 6, |
1413 | STATIC_DOUBLE, // T_DOUBLE = 7, |
1414 | STATIC_BYTE, // T_BYTE = 8, |
1415 | STATIC_SHORT, // T_SHORT = 9, |
1416 | STATIC_WORD, // T_INT = 10, |
1417 | STATIC_DOUBLE, // T_LONG = 11, |
1418 | STATIC_OOP, // T_OBJECT = 12, |
1419 | STATIC_OOP, // T_ARRAY = 13, |
1420 | BAD_ALLOCATION_TYPE, // T_VOID = 14, |
1421 | BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, |
1422 | BAD_ALLOCATION_TYPE, // T_NARROWOOP = 16, |
1423 | BAD_ALLOCATION_TYPE, // T_METADATA = 17, |
1424 | BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18, |
1425 | BAD_ALLOCATION_TYPE, // T_CONFLICT = 19, |
1426 | }; |
1427 | |
1428 | static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) { |
1429 | assert(type >= T_BOOLEAN && type < T_VOID, "only allowable values")do { if (!(type >= T_BOOLEAN && type < T_VOID)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1429, "assert(" "type >= T_BOOLEAN && type < T_VOID" ") failed", "only allowable values"); ::breakpoint(); } } while (0); |
1430 | FieldAllocationType result = _basic_type_to_atype[type + (is_static ? (T_CONFLICT + 1) : 0)]; |
1431 | assert(result != BAD_ALLOCATION_TYPE, "bad type")do { if (!(result != BAD_ALLOCATION_TYPE)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1431, "assert(" "result != BAD_ALLOCATION_TYPE" ") failed", "bad type"); ::breakpoint(); } } while (0); |
1432 | return result; |
1433 | } |
1434 | |
1435 | class ClassFileParser::FieldAllocationCount : public ResourceObj { |
1436 | public: |
1437 | u2 count[MAX_FIELD_ALLOCATION_TYPE]; |
1438 | |
1439 | FieldAllocationCount() { |
1440 | for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) { |
1441 | count[i] = 0; |
1442 | } |
1443 | } |
1444 | |
1445 | void update(bool is_static, BasicType type) { |
1446 | FieldAllocationType atype = basic_type_to_atype(is_static, type); |
1447 | if (atype != BAD_ALLOCATION_TYPE) { |
1448 | // Make sure there is no overflow with injected fields. |
1449 | assert(count[atype] < 0xFFFF, "More than 65535 fields")do { if (!(count[atype] < 0xFFFF)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1449, "assert(" "count[atype] < 0xFFFF" ") failed", "More than 65535 fields" ); ::breakpoint(); } } while (0); |
1450 | count[atype]++; |
1451 | } |
1452 | } |
1453 | }; |
1454 | |
1455 | // Side-effects: populates the _fields, _fields_annotations, |
1456 | // _fields_type_annotations fields |
1457 | void ClassFileParser::parse_fields(const ClassFileStream* const cfs, |
1458 | bool is_interface, |
1459 | FieldAllocationCount* const fac, |
1460 | ConstantPool* cp, |
1461 | const int cp_size, |
1462 | u2* const java_fields_count_ptr, |
1463 | TRAPSJavaThread* __the_thread__) { |
1464 | |
1465 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1465, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1466 | assert(fac != NULL, "invariant")do { if (!(fac != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1466, "assert(" "fac != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1467 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1467, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1468 | assert(java_fields_count_ptr != NULL, "invariant")do { if (!(java_fields_count_ptr != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1468, "assert(" "java_fields_count_ptr != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1469 | |
1470 | assert(NULL == _fields, "invariant")do { if (!(__null == _fields)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1470, "assert(" "__null == _fields" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1471 | assert(NULL == _fields_annotations, "invariant")do { if (!(__null == _fields_annotations)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1471, "assert(" "__null == _fields_annotations" ") failed", "invariant"); ::breakpoint(); } } while (0); |
1472 | assert(NULL == _fields_type_annotations, "invariant")do { if (!(__null == _fields_type_annotations)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1472, "assert(" "__null == _fields_type_annotations" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1473 | |
1474 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // length |
1475 | const u2 length = cfs->get_u2_fast(); |
1476 | *java_fields_count_ptr = length; |
1477 | |
1478 | int num_injected = 0; |
1479 | const InjectedField* const injected = JavaClasses::get_injected(_class_name, |
1480 | &num_injected); |
1481 | const int total_fields = length + num_injected; |
1482 | |
1483 | // The field array starts with tuples of shorts |
1484 | // [access, name index, sig index, initial value index, byte offset]. |
1485 | // A generic signature slot only exists for field with generic |
1486 | // signature attribute. And the access flag is set with |
1487 | // JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE for that field. The generic |
1488 | // signature slots are at the end of the field array and after all |
1489 | // other fields data. |
1490 | // |
1491 | // f1: [access, name index, sig index, initial value index, low_offset, high_offset] |
1492 | // f2: [access, name index, sig index, initial value index, low_offset, high_offset] |
1493 | // ... |
1494 | // fn: [access, name index, sig index, initial value index, low_offset, high_offset] |
1495 | // [generic signature index] |
1496 | // [generic signature index] |
1497 | // ... |
1498 | // |
1499 | // Allocate a temporary resource array for field data. For each field, |
1500 | // a slot is reserved in the temporary array for the generic signature |
1501 | // index. After parsing all fields, the data are copied to a permanent |
1502 | // array and any unused slots will be discarded. |
1503 | ResourceMark rm(THREAD__the_thread__); |
1504 | u2* const fa = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,(u2*) resource_allocate_bytes(__the_thread__, (total_fields * (FieldInfo::field_slots + 1)) * sizeof(u2)) |
1505 | u2,(u2*) resource_allocate_bytes(__the_thread__, (total_fields * (FieldInfo::field_slots + 1)) * sizeof(u2)) |
1506 | total_fields * (FieldInfo::field_slots + 1))(u2*) resource_allocate_bytes(__the_thread__, (total_fields * (FieldInfo::field_slots + 1)) * sizeof(u2)); |
1507 | |
1508 | // The generic signature slots start after all other fields' data. |
1509 | int generic_signature_slot = total_fields * FieldInfo::field_slots; |
1510 | int num_generic_signature = 0; |
1511 | for (int n = 0; n < length; n++) { |
1512 | // access_flags, name_index, descriptor_index, attributes_count |
1513 | cfs->guarantee_more(8, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1514 | |
1515 | AccessFlags access_flags; |
1516 | const jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC | JVM_ACC_FINAL | JVM_ACC_VOLATILE | JVM_ACC_TRANSIENT | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC); |
1517 | verify_legal_field_modifiers(flags, is_interface, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1518 | access_flags.set_flags(flags); |
1519 | |
1520 | const u2 name_index = cfs->get_u2_fast(); |
1521 | check_property(valid_symbol_at(name_index), |
1522 | "Invalid constant pool index %u for field name in class file %s", |
1523 | name_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1524 | const Symbol* const name = cp->symbol_at(name_index); |
1525 | verify_legal_field_name(name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1526 | |
1527 | const u2 signature_index = cfs->get_u2_fast(); |
1528 | check_property(valid_symbol_at(signature_index), |
1529 | "Invalid constant pool index %u for field signature in class file %s", |
1530 | signature_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1531 | const Symbol* const sig = cp->symbol_at(signature_index); |
1532 | verify_legal_field_signature(name, sig, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1533 | |
1534 | u2 constantvalue_index = 0; |
1535 | bool is_synthetic = false; |
1536 | u2 generic_signature_index = 0; |
1537 | const bool is_static = access_flags.is_static(); |
1538 | FieldAnnotationCollector parsed_annotations(_loader_data); |
1539 | |
1540 | const u2 attributes_count = cfs->get_u2_fast(); |
1541 | if (attributes_count > 0) { |
1542 | parse_field_attributes(cfs, |
1543 | attributes_count, |
1544 | is_static, |
1545 | signature_index, |
1546 | &constantvalue_index, |
1547 | &is_synthetic, |
1548 | &generic_signature_index, |
1549 | &parsed_annotations, |
1550 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1551 | |
1552 | if (parsed_annotations.field_annotations() != NULL__null) { |
1553 | if (_fields_annotations == NULL__null) { |
1554 | _fields_annotations = MetadataFactory::new_array<AnnotationArray*>( |
1555 | _loader_data, length, NULL__null, |
1556 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1557 | } |
1558 | _fields_annotations->at_put(n, parsed_annotations.field_annotations()); |
1559 | parsed_annotations.set_field_annotations(NULL__null); |
1560 | } |
1561 | if (parsed_annotations.field_type_annotations() != NULL__null) { |
1562 | if (_fields_type_annotations == NULL__null) { |
1563 | _fields_type_annotations = |
1564 | MetadataFactory::new_array<AnnotationArray*>(_loader_data, |
1565 | length, |
1566 | NULL__null, |
1567 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1568 | } |
1569 | _fields_type_annotations->at_put(n, parsed_annotations.field_type_annotations()); |
1570 | parsed_annotations.set_field_type_annotations(NULL__null); |
1571 | } |
1572 | |
1573 | if (is_synthetic) { |
1574 | access_flags.set_is_synthetic(); |
1575 | } |
1576 | if (generic_signature_index != 0) { |
1577 | access_flags.set_field_has_generic_signature(); |
1578 | fa[generic_signature_slot] = generic_signature_index; |
1579 | generic_signature_slot ++; |
1580 | num_generic_signature ++; |
1581 | } |
1582 | } |
1583 | |
1584 | FieldInfo* const field = FieldInfo::from_field_array(fa, n); |
1585 | field->initialize(access_flags.as_short(), |
1586 | name_index, |
1587 | signature_index, |
1588 | constantvalue_index); |
1589 | const BasicType type = cp->basic_type_for_signature_at(signature_index); |
1590 | |
1591 | // Update FieldAllocationCount for this kind of field |
1592 | fac->update(is_static, type); |
1593 | |
1594 | // After field is initialized with type, we can augment it with aux info |
1595 | if (parsed_annotations.has_any_annotations()) { |
1596 | parsed_annotations.apply_to(field); |
1597 | if (field->is_contended()) { |
1598 | _has_contended_fields = true; |
1599 | } |
1600 | } |
1601 | } |
1602 | |
1603 | int index = length; |
1604 | if (num_injected != 0) { |
1605 | for (int n = 0; n < num_injected; n++) { |
1606 | // Check for duplicates |
1607 | if (injected[n].may_be_java) { |
1608 | const Symbol* const name = injected[n].name(); |
1609 | const Symbol* const signature = injected[n].signature(); |
1610 | bool duplicate = false; |
1611 | for (int i = 0; i < length; i++) { |
1612 | const FieldInfo* const f = FieldInfo::from_field_array(fa, i); |
1613 | if (name == cp->symbol_at(f->name_index()) && |
1614 | signature == cp->symbol_at(f->signature_index())) { |
1615 | // Symbol is desclared in Java so skip this one |
1616 | duplicate = true; |
1617 | break; |
1618 | } |
1619 | } |
1620 | if (duplicate) { |
1621 | // These will be removed from the field array at the end |
1622 | continue; |
1623 | } |
1624 | } |
1625 | |
1626 | // Injected field |
1627 | FieldInfo* const field = FieldInfo::from_field_array(fa, index); |
1628 | field->initialize((u2)JVM_ACC_FIELD_INTERNAL, |
1629 | (u2)(injected[n].name_index), |
1630 | (u2)(injected[n].signature_index), |
1631 | 0); |
1632 | |
1633 | const BasicType type = Signature::basic_type(injected[n].signature()); |
1634 | |
1635 | // Update FieldAllocationCount for this kind of field |
1636 | fac->update(false, type); |
1637 | index++; |
1638 | } |
1639 | } |
1640 | |
1641 | assert(NULL == _fields, "invariant")do { if (!(__null == _fields)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1641, "assert(" "__null == _fields" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1642 | |
1643 | _fields = |
1644 | MetadataFactory::new_array<u2>(_loader_data, |
1645 | index * FieldInfo::field_slots + num_generic_signature, |
1646 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1647 | // Sometimes injected fields already exist in the Java source so |
1648 | // the fields array could be too long. In that case the |
1649 | // fields array is trimed. Also unused slots that were reserved |
1650 | // for generic signature indexes are discarded. |
1651 | { |
1652 | int i = 0; |
1653 | for (; i < index * FieldInfo::field_slots; i++) { |
1654 | _fields->at_put(i, fa[i]); |
1655 | } |
1656 | for (int j = total_fields * FieldInfo::field_slots; |
1657 | j < generic_signature_slot; j++) { |
1658 | _fields->at_put(i++, fa[j]); |
1659 | } |
1660 | assert(_fields->length() == i, "")do { if (!(_fields->length() == i)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1660, "assert(" "_fields->length() == i" ") failed", "") ; ::breakpoint(); } } while (0); |
1661 | } |
1662 | |
1663 | if (_need_verify && length > 1) { |
1664 | // Check duplicated fields |
1665 | ResourceMark rm(THREAD__the_thread__); |
1666 | NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD((NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)) |
1667 | THREAD, NameSigHash*, HASH_ROW_SIZE)(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)); |
1668 | initialize_hashtable(names_and_sigs); |
1669 | bool dup = false; |
1670 | const Symbol* name = NULL__null; |
1671 | const Symbol* sig = NULL__null; |
1672 | { |
1673 | debug_only(NoSafepointVerifier nsv;)NoSafepointVerifier nsv; |
1674 | for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) { |
1675 | name = fs.name(); |
1676 | sig = fs.signature(); |
1677 | // If no duplicates, add name/signature in hashtable names_and_sigs. |
1678 | if (!put_after_lookup(name, sig, names_and_sigs)) { |
1679 | dup = true; |
1680 | break; |
1681 | } |
1682 | } |
1683 | } |
1684 | if (dup) { |
1685 | classfile_parse_error("Duplicate field name \"%s\" with signature \"%s\" in class file %s", |
1686 | name->as_C_string(), sig->as_klass_external_name(), THREAD__the_thread__); |
1687 | } |
1688 | } |
1689 | } |
1690 | |
1691 | |
1692 | const ClassFileParser::unsafe_u2* ClassFileParser::parse_exception_table(const ClassFileStream* const cfs, |
1693 | u4 code_length, |
1694 | u4 exception_table_length, |
1695 | TRAPSJavaThread* __the_thread__) { |
1696 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1696, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1697 | |
1698 | const unsafe_u2* const exception_table_start = cfs->current(); |
1699 | assert(exception_table_start != NULL, "null exception table")do { if (!(exception_table_start != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1699, "assert(" "exception_table_start != __null" ") failed" , "null exception table"); ::breakpoint(); } } while (0); |
1700 | |
1701 | cfs->guarantee_more(8 * exception_table_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // start_pc, |
1702 | // end_pc, |
1703 | // handler_pc, |
1704 | // catch_type_index |
1705 | |
1706 | // Will check legal target after parsing code array in verifier. |
1707 | if (_need_verify) { |
1708 | for (unsigned int i = 0; i < exception_table_length; i++) { |
1709 | const u2 start_pc = cfs->get_u2_fast(); |
1710 | const u2 end_pc = cfs->get_u2_fast(); |
1711 | const u2 handler_pc = cfs->get_u2_fast(); |
1712 | const u2 catch_type_index = cfs->get_u2_fast(); |
1713 | guarantee_property((start_pc < end_pc) && (end_pc <= code_length), |
1714 | "Illegal exception table range in class file %s", |
1715 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1716 | guarantee_property(handler_pc < code_length, |
1717 | "Illegal exception table handler in class file %s", |
1718 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1719 | if (catch_type_index != 0) { |
1720 | guarantee_property(valid_klass_reference_at(catch_type_index), |
1721 | "Catch type in exception table has bad constant type in class file %s", CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1722 | } |
1723 | } |
1724 | } else { |
1725 | cfs->skip_u2_fast(exception_table_length * 4); |
1726 | } |
1727 | return exception_table_start; |
1728 | } |
1729 | |
1730 | void ClassFileParser::parse_linenumber_table(u4 code_attribute_length, |
1731 | u4 code_length, |
1732 | CompressedLineNumberWriteStream**const write_stream, |
1733 | TRAPSJavaThread* __the_thread__) { |
1734 | |
1735 | const ClassFileStream* const cfs = _stream; |
1736 | unsigned int num_entries = cfs->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1737 | |
1738 | // Each entry is a u2 start_pc, and a u2 line_number |
1739 | const unsigned int length_in_bytes = num_entries * (sizeof(u2) * 2); |
1740 | |
1741 | // Verify line number attribute and table length |
1742 | check_property( |
1743 | code_attribute_length == sizeof(u2) + length_in_bytes, |
1744 | "LineNumberTable attribute has wrong length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1745 | |
1746 | cfs->guarantee_more(length_in_bytes, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1747 | |
1748 | if ((*write_stream) == NULL__null) { |
1749 | if (length_in_bytes > fixed_buffer_size) { |
1750 | (*write_stream) = new CompressedLineNumberWriteStream(length_in_bytes); |
1751 | } else { |
1752 | (*write_stream) = new CompressedLineNumberWriteStream( |
1753 | _linenumbertable_buffer, fixed_buffer_size); |
1754 | } |
1755 | } |
1756 | |
1757 | while (num_entries-- > 0) { |
1758 | const u2 bci = cfs->get_u2_fast(); // start_pc |
1759 | const u2 line = cfs->get_u2_fast(); // line_number |
1760 | guarantee_property(bci < code_length, |
1761 | "Invalid pc in LineNumberTable in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
1762 | (*write_stream)->write_pair(bci, line); |
1763 | } |
1764 | } |
1765 | |
1766 | |
1767 | class LVT_Hash : public AllStatic { |
1768 | public: |
1769 | |
1770 | static bool equals(LocalVariableTableElement const& e0, LocalVariableTableElement const& e1) { |
1771 | /* |
1772 | * 3-tuple start_bci/length/slot has to be unique key, |
1773 | * so the following comparison seems to be redundant: |
1774 | * && elem->name_cp_index == entry->_elem->name_cp_index |
1775 | */ |
1776 | return (e0.start_bci == e1.start_bci && |
1777 | e0.length == e1.length && |
1778 | e0.name_cp_index == e1.name_cp_index && |
1779 | e0.slot == e1.slot); |
1780 | } |
1781 | |
1782 | static unsigned int hash(LocalVariableTableElement const& e0) { |
1783 | unsigned int raw_hash = e0.start_bci; |
1784 | |
1785 | raw_hash = e0.length + raw_hash * 37; |
1786 | raw_hash = e0.name_cp_index + raw_hash * 37; |
1787 | raw_hash = e0.slot + raw_hash * 37; |
1788 | |
1789 | return raw_hash; |
1790 | } |
1791 | }; |
1792 | |
1793 | |
1794 | // Class file LocalVariableTable elements. |
1795 | class Classfile_LVT_Element { |
1796 | public: |
1797 | u2 start_bci; |
1798 | u2 length; |
1799 | u2 name_cp_index; |
1800 | u2 descriptor_cp_index; |
1801 | u2 slot; |
1802 | }; |
1803 | |
1804 | static void copy_lvt_element(const Classfile_LVT_Element* const src, |
1805 | LocalVariableTableElement* const lvt) { |
1806 | lvt->start_bci = Bytes::get_Java_u2((u1*) &src->start_bci); |
1807 | lvt->length = Bytes::get_Java_u2((u1*) &src->length); |
1808 | lvt->name_cp_index = Bytes::get_Java_u2((u1*) &src->name_cp_index); |
1809 | lvt->descriptor_cp_index = Bytes::get_Java_u2((u1*) &src->descriptor_cp_index); |
1810 | lvt->signature_cp_index = 0; |
1811 | lvt->slot = Bytes::get_Java_u2((u1*) &src->slot); |
1812 | } |
1813 | |
1814 | // Function is used to parse both attributes: |
1815 | // LocalVariableTable (LVT) and LocalVariableTypeTable (LVTT) |
1816 | const ClassFileParser::unsafe_u2* ClassFileParser::parse_localvariable_table(const ClassFileStream* cfs, |
1817 | u4 code_length, |
1818 | u2 max_locals, |
1819 | u4 code_attribute_length, |
1820 | u2* const localvariable_table_length, |
1821 | bool isLVTT, |
1822 | TRAPSJavaThread* __the_thread__) { |
1823 | const char* const tbl_name = (isLVTT) ? "LocalVariableTypeTable" : "LocalVariableTable"; |
1824 | *localvariable_table_length = cfs->get_u2(CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1825 | const unsigned int size = |
1826 | (*localvariable_table_length) * sizeof(Classfile_LVT_Element) / sizeof(u2); |
1827 | |
1828 | const ConstantPool* const cp = _cp; |
1829 | |
1830 | // Verify local variable table attribute has right length |
1831 | if (_need_verify) { |
1832 | guarantee_property(code_attribute_length == (sizeof(*localvariable_table_length) + size * sizeof(u2)), |
1833 | "%s has wrong length in class file %s", tbl_name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1834 | } |
1835 | |
1836 | const unsafe_u2* const localvariable_table_start = cfs->current(); |
1837 | assert(localvariable_table_start != NULL, "null local variable table")do { if (!(localvariable_table_start != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1837, "assert(" "localvariable_table_start != __null" ") failed" , "null local variable table"); ::breakpoint(); } } while (0); |
1838 | if (!_need_verify) { |
1839 | cfs->skip_u2_fast(size); |
1840 | } else { |
1841 | cfs->guarantee_more(size * 2, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1842 | for(int i = 0; i < (*localvariable_table_length); i++) { |
1843 | const u2 start_pc = cfs->get_u2_fast(); |
1844 | const u2 length = cfs->get_u2_fast(); |
1845 | const u2 name_index = cfs->get_u2_fast(); |
1846 | const u2 descriptor_index = cfs->get_u2_fast(); |
1847 | const u2 index = cfs->get_u2_fast(); |
1848 | // Assign to a u4 to avoid overflow |
1849 | const u4 end_pc = (u4)start_pc + (u4)length; |
1850 | |
1851 | if (start_pc >= code_length) { |
1852 | classfile_parse_error( |
1853 | "Invalid start_pc %u in %s in class file %s", |
1854 | start_pc, tbl_name, THREAD__the_thread__); |
1855 | return NULL__null; |
1856 | } |
1857 | if (end_pc > code_length) { |
1858 | classfile_parse_error( |
1859 | "Invalid length %u in %s in class file %s", |
1860 | length, tbl_name, THREAD__the_thread__); |
1861 | return NULL__null; |
1862 | } |
1863 | const int cp_size = cp->length(); |
1864 | guarantee_property(valid_symbol_at(name_index), |
1865 | "Name index %u in %s has bad constant type in class file %s", |
1866 | name_index, tbl_name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1867 | guarantee_property(valid_symbol_at(descriptor_index), |
1868 | "Signature index %u in %s has bad constant type in class file %s", |
1869 | descriptor_index, tbl_name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1870 | |
1871 | const Symbol* const name = cp->symbol_at(name_index); |
1872 | const Symbol* const sig = cp->symbol_at(descriptor_index); |
1873 | verify_legal_field_name(name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1874 | u2 extra_slot = 0; |
1875 | if (!isLVTT) { |
1876 | verify_legal_field_signature(name, sig, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1877 | |
1878 | // 4894874: check special cases for double and long local variables |
1879 | if (sig == vmSymbols::type_signature(T_DOUBLE) || |
1880 | sig == vmSymbols::type_signature(T_LONG)) { |
1881 | extra_slot = 1; |
1882 | } |
1883 | } |
1884 | guarantee_property((index + extra_slot) < max_locals, |
1885 | "Invalid index %u in %s in class file %s", |
1886 | index, tbl_name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1887 | } |
1888 | } |
1889 | return localvariable_table_start; |
1890 | } |
1891 | |
1892 | static const u1* parse_stackmap_table(const ClassFileStream* const cfs, |
1893 | u4 code_attribute_length, |
1894 | bool need_verify, |
1895 | TRAPSJavaThread* __the_thread__) { |
1896 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1896, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1897 | |
1898 | if (0 == code_attribute_length) { |
1899 | return NULL__null; |
1900 | } |
1901 | |
1902 | const u1* const stackmap_table_start = cfs->current(); |
1903 | assert(stackmap_table_start != NULL, "null stackmap table")do { if (!(stackmap_table_start != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1903, "assert(" "stackmap_table_start != __null" ") failed" , "null stackmap table"); ::breakpoint(); } } while (0); |
1904 | |
1905 | // check code_attribute_length first |
1906 | cfs->skip_u1(code_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1907 | |
1908 | if (!need_verify && !DumpSharedSpaces) { |
1909 | return NULL__null; |
1910 | } |
1911 | return stackmap_table_start; |
1912 | } |
1913 | |
1914 | const ClassFileParser::unsafe_u2* ClassFileParser::parse_checked_exceptions(const ClassFileStream* const cfs, |
1915 | u2* const checked_exceptions_length, |
1916 | u4 method_attribute_length, |
1917 | TRAPSJavaThread* __the_thread__) { |
1918 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1918, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1919 | assert(checked_exceptions_length != NULL, "invariant")do { if (!(checked_exceptions_length != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1919, "assert(" "checked_exceptions_length != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1920 | |
1921 | cfs->guarantee_more(2, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // checked_exceptions_length |
1922 | *checked_exceptions_length = cfs->get_u2_fast(); |
1923 | const unsigned int size = |
1924 | (*checked_exceptions_length) * sizeof(CheckedExceptionElement) / sizeof(u2); |
1925 | const unsafe_u2* const checked_exceptions_start = cfs->current(); |
1926 | assert(checked_exceptions_start != NULL, "null checked exceptions")do { if (!(checked_exceptions_start != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1926, "assert(" "checked_exceptions_start != __null" ") failed" , "null checked exceptions"); ::breakpoint(); } } while (0); |
1927 | if (!_need_verify) { |
1928 | cfs->skip_u2_fast(size); |
1929 | } else { |
1930 | // Verify each value in the checked exception table |
1931 | u2 checked_exception; |
1932 | const u2 len = *checked_exceptions_length; |
1933 | cfs->guarantee_more(2 * len, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1934 | for (int i = 0; i < len; i++) { |
1935 | checked_exception = cfs->get_u2_fast(); |
1936 | check_property( |
1937 | valid_klass_reference_at(checked_exception), |
1938 | "Exception name has bad type at constant pool %u in class file %s", |
1939 | checked_exception, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1940 | } |
1941 | } |
1942 | // check exceptions attribute length |
1943 | if (_need_verify) { |
1944 | guarantee_property(method_attribute_length == (sizeof(*checked_exceptions_length) + |
1945 | sizeof(u2) * size), |
1946 | "Exceptions attribute has wrong length in class file %s", CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
1947 | } |
1948 | return checked_exceptions_start; |
1949 | } |
1950 | |
1951 | void ClassFileParser::throwIllegalSignature(const char* type, |
1952 | const Symbol* name, |
1953 | const Symbol* sig, |
1954 | TRAPSJavaThread* __the_thread__) const { |
1955 | assert(name != NULL, "invariant")do { if (!(name != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1955, "assert(" "name != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1956 | assert(sig != NULL, "invariant")do { if (!(sig != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1956, "assert(" "sig != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1957 | |
1958 | ResourceMark rm(THREAD__the_thread__); |
1959 | Exceptions::fthrow(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1959, |
1960 | vmSymbols::java_lang_ClassFormatError(), |
1961 | "%s \"%s\" in class %s has illegal signature \"%s\"", type, |
1962 | name->as_C_string(), _class_name->as_C_string(), sig->as_C_string()); |
1963 | } |
1964 | |
1965 | AnnotationCollector::ID |
1966 | AnnotationCollector::annotation_index(const ClassLoaderData* loader_data, |
1967 | const Symbol* name, |
1968 | const bool can_access_vm_annotations) { |
1969 | const vmSymbolID sid = vmSymbols::find_sid(name); |
1970 | // Privileged code can use all annotations. Other code silently drops some. |
1971 | const bool privileged = loader_data->is_boot_class_loader_data() || |
1972 | loader_data->is_platform_class_loader_data() || |
1973 | can_access_vm_annotations; |
1974 | switch (sid) { |
1975 | case VM_SYMBOL_ENUM_NAME(reflect_CallerSensitive_signature)vmSymbolID::reflect_CallerSensitive_signature_enum: { |
1976 | if (_location != _in_method) break; // only allow for methods |
1977 | if (!privileged) break; // only allow in privileged code |
1978 | return _method_CallerSensitive; |
1979 | } |
1980 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_ForceInline_signature)vmSymbolID::jdk_internal_vm_annotation_ForceInline_signature_enum: { |
1981 | if (_location != _in_method) break; // only allow for methods |
1982 | if (!privileged) break; // only allow in privileged code |
1983 | return _method_ForceInline; |
1984 | } |
1985 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_DontInline_signature)vmSymbolID::jdk_internal_vm_annotation_DontInline_signature_enum: { |
1986 | if (_location != _in_method) break; // only allow for methods |
1987 | if (!privileged) break; // only allow in privileged code |
1988 | return _method_DontInline; |
1989 | } |
1990 | case VM_SYMBOL_ENUM_NAME(java_lang_invoke_InjectedProfile_signature)vmSymbolID::java_lang_invoke_InjectedProfile_signature_enum: { |
1991 | if (_location != _in_method) break; // only allow for methods |
1992 | if (!privileged) break; // only allow in privileged code |
1993 | return _method_InjectedProfile; |
1994 | } |
1995 | case VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Compiled_signature)vmSymbolID::java_lang_invoke_LambdaForm_Compiled_signature_enum: { |
1996 | if (_location != _in_method) break; // only allow for methods |
1997 | if (!privileged) break; // only allow in privileged code |
1998 | return _method_LambdaForm_Compiled; |
1999 | } |
2000 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Hidden_signature)vmSymbolID::jdk_internal_vm_annotation_Hidden_signature_enum: { |
2001 | if (_location != _in_method) break; // only allow for methods |
2002 | if (!privileged) break; // only allow in privileged code |
2003 | return _method_Hidden; |
2004 | } |
2005 | case VM_SYMBOL_ENUM_NAME(jdk_internal_misc_Scoped_signature)vmSymbolID::jdk_internal_misc_Scoped_signature_enum: { |
2006 | if (_location != _in_method) break; // only allow for methods |
2007 | if (!privileged) break; // only allow in privileged code |
2008 | return _method_Scoped; |
2009 | } |
2010 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_IntrinsicCandidate_signature)vmSymbolID::jdk_internal_vm_annotation_IntrinsicCandidate_signature_enum: { |
2011 | if (_location != _in_method) break; // only allow for methods |
2012 | if (!privileged) break; // only allow in privileged code |
2013 | return _method_IntrinsicCandidate; |
2014 | } |
2015 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Stable_signature)vmSymbolID::jdk_internal_vm_annotation_Stable_signature_enum: { |
2016 | if (_location != _in_field) break; // only allow for fields |
2017 | if (!privileged) break; // only allow in privileged code |
2018 | return _field_Stable; |
2019 | } |
2020 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Contended_signature)vmSymbolID::jdk_internal_vm_annotation_Contended_signature_enum: { |
2021 | if (_location != _in_field && _location != _in_class) { |
2022 | break; // only allow for fields and classes |
2023 | } |
2024 | if (!EnableContended || (RestrictContended && !privileged)) { |
2025 | break; // honor privileges |
2026 | } |
2027 | return _jdk_internal_vm_annotation_Contended; |
2028 | } |
2029 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_ReservedStackAccess_signature)vmSymbolID::jdk_internal_vm_annotation_ReservedStackAccess_signature_enum: { |
2030 | if (_location != _in_method) break; // only allow for methods |
2031 | if (RestrictReservedStack && !privileged) break; // honor privileges |
2032 | return _jdk_internal_vm_annotation_ReservedStackAccess; |
2033 | } |
2034 | case VM_SYMBOL_ENUM_NAME(jdk_internal_ValueBased_signature)vmSymbolID::jdk_internal_ValueBased_signature_enum: { |
2035 | if (_location != _in_class) break; // only allow for classes |
2036 | if (!privileged) break; // only allow in priviledged code |
2037 | return _jdk_internal_ValueBased; |
2038 | } |
2039 | default: { |
2040 | break; |
2041 | } |
2042 | } |
2043 | return AnnotationCollector::_unknown; |
2044 | } |
2045 | |
2046 | void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) { |
2047 | if (is_contended()) |
2048 | f->set_contended_group(contended_group()); |
2049 | if (is_stable()) |
2050 | f->set_stable(true); |
2051 | } |
2052 | |
2053 | ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() { |
2054 | // If there's an error deallocate metadata for field annotations |
2055 | MetadataFactory::free_array<u1>(_loader_data, _field_annotations); |
2056 | MetadataFactory::free_array<u1>(_loader_data, _field_type_annotations); |
2057 | } |
2058 | |
2059 | void MethodAnnotationCollector::apply_to(const methodHandle& m) { |
2060 | if (has_annotation(_method_CallerSensitive)) |
2061 | m->set_caller_sensitive(true); |
2062 | if (has_annotation(_method_ForceInline)) |
2063 | m->set_force_inline(true); |
2064 | if (has_annotation(_method_DontInline)) |
2065 | m->set_dont_inline(true); |
2066 | if (has_annotation(_method_InjectedProfile)) |
2067 | m->set_has_injected_profile(true); |
2068 | if (has_annotation(_method_LambdaForm_Compiled) && m->intrinsic_id() == vmIntrinsics::_none) |
2069 | m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm); |
2070 | if (has_annotation(_method_Hidden)) |
2071 | m->set_hidden(true); |
2072 | if (has_annotation(_method_Scoped)) |
2073 | m->set_scoped(true); |
2074 | if (has_annotation(_method_IntrinsicCandidate) && !m->is_synthetic()) |
2075 | m->set_intrinsic_candidate(true); |
2076 | if (has_annotation(_jdk_internal_vm_annotation_ReservedStackAccess)) |
2077 | m->set_has_reserved_stack_access(true); |
2078 | } |
2079 | |
2080 | void ClassFileParser::ClassAnnotationCollector::apply_to(InstanceKlass* ik) { |
2081 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2081, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
2082 | if (has_annotation(_jdk_internal_vm_annotation_Contended)) { |
2083 | ik->set_is_contended(is_contended()); |
2084 | } |
2085 | if (has_annotation(_jdk_internal_ValueBased)) { |
2086 | ik->set_has_value_based_class_annotation(); |
2087 | if (DiagnoseSyncOnValueBasedClasses) { |
2088 | ik->set_is_value_based(); |
2089 | } |
2090 | } |
2091 | } |
2092 | |
2093 | #define MAX_ARGS_SIZE255 255 |
2094 | #define MAX_CODE_SIZE65535 65535 |
2095 | #define INITIAL_MAX_LVT_NUMBER256 256 |
2096 | |
2097 | /* Copy class file LVT's/LVTT's into the HotSpot internal LVT. |
2098 | * |
2099 | * Rules for LVT's and LVTT's are: |
2100 | * - There can be any number of LVT's and LVTT's. |
2101 | * - If there are n LVT's, it is the same as if there was just |
2102 | * one LVT containing all the entries from the n LVT's. |
2103 | * - There may be no more than one LVT entry per local variable. |
2104 | * Two LVT entries are 'equal' if these fields are the same: |
2105 | * start_pc, length, name, slot |
2106 | * - There may be no more than one LVTT entry per each LVT entry. |
2107 | * Each LVTT entry has to match some LVT entry. |
2108 | * - HotSpot internal LVT keeps natural ordering of class file LVT entries. |
2109 | */ |
2110 | void ClassFileParser::copy_localvariable_table(const ConstMethod* cm, |
2111 | int lvt_cnt, |
2112 | u2* const localvariable_table_length, |
2113 | const unsafe_u2** const localvariable_table_start, |
2114 | int lvtt_cnt, |
2115 | u2* const localvariable_type_table_length, |
2116 | const unsafe_u2** const localvariable_type_table_start, |
2117 | TRAPSJavaThread* __the_thread__) { |
2118 | |
2119 | ResourceMark rm(THREAD__the_thread__); |
2120 | |
2121 | typedef ResourceHashtable<LocalVariableTableElement, LocalVariableTableElement*, |
2122 | 256, ResourceObj::RESOURCE_AREA, mtInternal, |
2123 | &LVT_Hash::hash, &LVT_Hash::equals> LVT_HashTable; |
2124 | |
2125 | LVT_HashTable* const table = new LVT_HashTable(); |
2126 | |
2127 | // To fill LocalVariableTable in |
2128 | const Classfile_LVT_Element* cf_lvt; |
2129 | LocalVariableTableElement* lvt = cm->localvariable_table_start(); |
2130 | |
2131 | for (int tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) { |
2132 | cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no]; |
2133 | for (int idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) { |
2134 | copy_lvt_element(&cf_lvt[idx], lvt); |
2135 | // If no duplicates, add LVT elem in hashtable. |
2136 | if (table->put(*lvt, lvt) == false |
2137 | && _need_verify |
2138 | && _major_version >= JAVA_1_5_VERSION49) { |
2139 | classfile_parse_error("Duplicated LocalVariableTable attribute " |
2140 | "entry for '%s' in class file %s", |
2141 | _cp->symbol_at(lvt->name_cp_index)->as_utf8(), |
2142 | THREAD__the_thread__); |
2143 | return; |
2144 | } |
2145 | } |
2146 | } |
2147 | |
2148 | // To merge LocalVariableTable and LocalVariableTypeTable |
2149 | const Classfile_LVT_Element* cf_lvtt; |
2150 | LocalVariableTableElement lvtt_elem; |
2151 | |
2152 | for (int tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) { |
2153 | cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no]; |
2154 | for (int idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) { |
2155 | copy_lvt_element(&cf_lvtt[idx], &lvtt_elem); |
2156 | LocalVariableTableElement** entry = table->get(lvtt_elem); |
2157 | if (entry == NULL__null) { |
2158 | if (_need_verify) { |
2159 | classfile_parse_error("LVTT entry for '%s' in class file %s " |
2160 | "does not match any LVT entry", |
2161 | _cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(), |
2162 | THREAD__the_thread__); |
2163 | return; |
2164 | } |
2165 | } else if ((*entry)->signature_cp_index != 0 && _need_verify) { |
2166 | classfile_parse_error("Duplicated LocalVariableTypeTable attribute " |
2167 | "entry for '%s' in class file %s", |
2168 | _cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(), |
2169 | THREAD__the_thread__); |
2170 | return; |
2171 | } else { |
2172 | // to add generic signatures into LocalVariableTable |
2173 | (*entry)->signature_cp_index = lvtt_elem.descriptor_cp_index; |
2174 | } |
2175 | } |
2176 | } |
2177 | } |
2178 | |
2179 | |
2180 | void ClassFileParser::copy_method_annotations(ConstMethod* cm, |
2181 | const u1* runtime_visible_annotations, |
2182 | int runtime_visible_annotations_length, |
2183 | const u1* runtime_invisible_annotations, |
2184 | int runtime_invisible_annotations_length, |
2185 | const u1* runtime_visible_parameter_annotations, |
2186 | int runtime_visible_parameter_annotations_length, |
2187 | const u1* runtime_invisible_parameter_annotations, |
2188 | int runtime_invisible_parameter_annotations_length, |
2189 | const u1* runtime_visible_type_annotations, |
2190 | int runtime_visible_type_annotations_length, |
2191 | const u1* runtime_invisible_type_annotations, |
2192 | int runtime_invisible_type_annotations_length, |
2193 | const u1* annotation_default, |
2194 | int annotation_default_length, |
2195 | TRAPSJavaThread* __the_thread__) { |
2196 | |
2197 | AnnotationArray* a; |
2198 | |
2199 | if (runtime_visible_annotations_length + |
2200 | runtime_invisible_annotations_length > 0) { |
2201 | a = assemble_annotations(runtime_visible_annotations, |
2202 | runtime_visible_annotations_length, |
2203 | runtime_invisible_annotations, |
2204 | runtime_invisible_annotations_length, |
2205 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
2206 | cm->set_method_annotations(a); |
2207 | } |
2208 | |
2209 | if (runtime_visible_parameter_annotations_length + |
2210 | runtime_invisible_parameter_annotations_length > 0) { |
2211 | a = assemble_annotations(runtime_visible_parameter_annotations, |
2212 | runtime_visible_parameter_annotations_length, |
2213 | runtime_invisible_parameter_annotations, |
2214 | runtime_invisible_parameter_annotations_length, |
2215 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
2216 | cm->set_parameter_annotations(a); |
2217 | } |
2218 | |
2219 | if (annotation_default_length > 0) { |
2220 | a = assemble_annotations(annotation_default, |
2221 | annotation_default_length, |
2222 | NULL__null, |
2223 | 0, |
2224 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
2225 | cm->set_default_annotations(a); |
2226 | } |
2227 | |
2228 | if (runtime_visible_type_annotations_length + |
2229 | runtime_invisible_type_annotations_length > 0) { |
2230 | a = assemble_annotations(runtime_visible_type_annotations, |
2231 | runtime_visible_type_annotations_length, |
2232 | runtime_invisible_type_annotations, |
2233 | runtime_invisible_type_annotations_length, |
2234 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
2235 | cm->set_type_annotations(a); |
2236 | } |
2237 | } |
2238 | |
2239 | |
2240 | // Note: the parse_method below is big and clunky because all parsing of the code and exceptions |
2241 | // attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the |
2242 | // Method* to save footprint, so we only know the size of the resulting Method* when the |
2243 | // entire method attribute is parsed. |
2244 | // |
2245 | // The promoted_flags parameter is used to pass relevant access_flags |
2246 | // from the method back up to the containing klass. These flag values |
2247 | // are added to klass's access_flags. |
2248 | |
2249 | Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, |
2250 | bool is_interface, |
2251 | const ConstantPool* cp, |
2252 | AccessFlags* const promoted_flags, |
2253 | TRAPSJavaThread* __the_thread__) { |
2254 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2254, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
2255 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2255, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
2256 | assert(promoted_flags != NULL, "invariant")do { if (!(promoted_flags != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2256, "assert(" "promoted_flags != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
2257 | |
2258 | ResourceMark rm(THREAD__the_thread__); |
2259 | // Parse fixed parts: |
2260 | // access_flags, name_index, descriptor_index, attributes_count |
2261 | cfs->guarantee_more(8, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2262 | |
2263 | int flags = cfs->get_u2_fast(); |
2264 | const u2 name_index = cfs->get_u2_fast(); |
2265 | const int cp_size = cp->length(); |
Value stored to 'cp_size' during its initialization is never read | |
2266 | check_property( |
2267 | valid_symbol_at(name_index), |
2268 | "Illegal constant pool index %u for method name in class file %s", |
2269 | name_index, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2270 | const Symbol* const name = cp->symbol_at(name_index); |
2271 | verify_legal_method_name(name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2272 | |
2273 | const u2 signature_index = cfs->get_u2_fast(); |
2274 | guarantee_property( |
2275 | valid_symbol_at(signature_index), |
2276 | "Illegal constant pool index %u for method signature in class file %s", |
2277 | signature_index, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2278 | const Symbol* const signature = cp->symbol_at(signature_index); |
2279 | |
2280 | if (name == vmSymbols::class_initializer_name()) { |
2281 | // We ignore the other access flags for a valid class initializer. |
2282 | // (JVM Spec 2nd ed., chapter 4.6) |
2283 | if (_major_version < 51) { // backward compatibility |
2284 | flags = JVM_ACC_STATIC; |
2285 | } else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) { |
2286 | flags &= JVM_ACC_STATIC | (_major_version <= JAVA_16_VERSION60 ? JVM_ACC_STRICT : 0); |
2287 | } else { |
2288 | classfile_parse_error("Method <clinit> is not static in class file %s", THREAD__the_thread__); |
2289 | return NULL__null; |
2290 | } |
2291 | } else { |
2292 | verify_legal_method_modifiers(flags, is_interface, name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2293 | } |
2294 | |
2295 | if (name == vmSymbols::object_initializer_name() && is_interface) { |
2296 | classfile_parse_error("Interface cannot have a method named <init>, class file %s", THREAD__the_thread__); |
2297 | return NULL__null; |
2298 | } |
2299 | |
2300 | int args_size = -1; // only used when _need_verify is true |
2301 | if (_need_verify) { |
2302 | verify_legal_name_with_signature(name, signature, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2303 | args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) + |
2304 | verify_legal_method_signature(name, signature, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2305 | if (args_size > MAX_ARGS_SIZE255) { |
2306 | classfile_parse_error("Too many arguments in method signature in class file %s", THREAD__the_thread__); |
2307 | return NULL__null; |
2308 | } |
2309 | } |
2310 | |
2311 | AccessFlags access_flags(flags & JVM_RECOGNIZED_METHOD_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC | JVM_ACC_FINAL | JVM_ACC_SYNCHRONIZED | JVM_ACC_BRIDGE | JVM_ACC_VARARGS | JVM_ACC_NATIVE | JVM_ACC_ABSTRACT | JVM_ACC_STRICT | JVM_ACC_SYNTHETIC )); |
2312 | |
2313 | // Default values for code and exceptions attribute elements |
2314 | u2 max_stack = 0; |
2315 | u2 max_locals = 0; |
2316 | u4 code_length = 0; |
2317 | const u1* code_start = 0; |
2318 | u2 exception_table_length = 0; |
2319 | const unsafe_u2* exception_table_start = NULL__null; // (potentially unaligned) pointer to array of u2 elements |
2320 | Array<int>* exception_handlers = Universe::the_empty_int_array(); |
2321 | u2 checked_exceptions_length = 0; |
2322 | const unsafe_u2* checked_exceptions_start = NULL__null; // (potentially unaligned) pointer to array of u2 elements |
2323 | CompressedLineNumberWriteStream* linenumber_table = NULL__null; |
2324 | int linenumber_table_length = 0; |
2325 | int total_lvt_length = 0; |
2326 | u2 lvt_cnt = 0; |
2327 | u2 lvtt_cnt = 0; |
2328 | bool lvt_allocated = false; |
2329 | u2 max_lvt_cnt = INITIAL_MAX_LVT_NUMBER256; |
2330 | u2 max_lvtt_cnt = INITIAL_MAX_LVT_NUMBER256; |
2331 | u2* localvariable_table_length = NULL__null; |
2332 | const unsafe_u2** localvariable_table_start = NULL__null; // (potentially unaligned) pointer to array of LVT attributes |
2333 | u2* localvariable_type_table_length = NULL__null; |
2334 | const unsafe_u2** localvariable_type_table_start = NULL__null; // (potentially unaligned) pointer to LVTT attributes |
2335 | int method_parameters_length = -1; |
2336 | const u1* method_parameters_data = NULL__null; |
2337 | bool method_parameters_seen = false; |
2338 | bool parsed_code_attribute = false; |
2339 | bool parsed_checked_exceptions_attribute = false; |
2340 | bool parsed_stackmap_attribute = false; |
2341 | // stackmap attribute - JDK1.5 |
2342 | const u1* stackmap_data = NULL__null; |
2343 | int stackmap_data_length = 0; |
2344 | u2 generic_signature_index = 0; |
2345 | MethodAnnotationCollector parsed_annotations; |
2346 | const u1* runtime_visible_annotations = NULL__null; |
2347 | int runtime_visible_annotations_length = 0; |
2348 | const u1* runtime_invisible_annotations = NULL__null; |
2349 | int runtime_invisible_annotations_length = 0; |
2350 | const u1* runtime_visible_parameter_annotations = NULL__null; |
2351 | int runtime_visible_parameter_annotations_length = 0; |
2352 | const u1* runtime_invisible_parameter_annotations = NULL__null; |
2353 | int runtime_invisible_parameter_annotations_length = 0; |
2354 | const u1* runtime_visible_type_annotations = NULL__null; |
2355 | int runtime_visible_type_annotations_length = 0; |
2356 | const u1* runtime_invisible_type_annotations = NULL__null; |
2357 | int runtime_invisible_type_annotations_length = 0; |
2358 | bool runtime_invisible_annotations_exists = false; |
2359 | bool runtime_invisible_type_annotations_exists = false; |
2360 | bool runtime_invisible_parameter_annotations_exists = false; |
2361 | const u1* annotation_default = NULL__null; |
2362 | int annotation_default_length = 0; |
2363 | |
2364 | // Parse code and exceptions attribute |
2365 | u2 method_attributes_count = cfs->get_u2_fast(); |
2366 | while (method_attributes_count--) { |
2367 | cfs->guarantee_more(6, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // method_attribute_name_index, method_attribute_length |
2368 | const u2 method_attribute_name_index = cfs->get_u2_fast(); |
2369 | const u4 method_attribute_length = cfs->get_u4_fast(); |
2370 | check_property( |
2371 | valid_symbol_at(method_attribute_name_index), |
2372 | "Invalid method attribute name index %u in class file %s", |
2373 | method_attribute_name_index, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2374 | |
2375 | const Symbol* const method_attribute_name = cp->symbol_at(method_attribute_name_index); |
2376 | if (method_attribute_name == vmSymbols::tag_code()) { |
2377 | // Parse Code attribute |
2378 | if (_need_verify) { |
2379 | guarantee_property( |
2380 | !access_flags.is_native() && !access_flags.is_abstract(), |
2381 | "Code attribute in native or abstract methods in class file %s", |
2382 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2383 | } |
2384 | if (parsed_code_attribute) { |
2385 | classfile_parse_error("Multiple Code attributes in class file %s", |
2386 | THREAD__the_thread__); |
2387 | return NULL__null; |
2388 | } |
2389 | parsed_code_attribute = true; |
2390 | |
2391 | // Stack size, locals size, and code size |
2392 | cfs->guarantee_more(8, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2393 | max_stack = cfs->get_u2_fast(); |
2394 | max_locals = cfs->get_u2_fast(); |
2395 | code_length = cfs->get_u4_fast(); |
2396 | if (_need_verify) { |
2397 | guarantee_property(args_size <= max_locals, |
2398 | "Arguments can't fit into locals in class file %s", |
2399 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2400 | guarantee_property(code_length > 0 && code_length <= MAX_CODE_SIZE65535, |
2401 | "Invalid method Code length %u in class file %s", |
2402 | code_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2403 | } |
2404 | // Code pointer |
2405 | code_start = cfs->current(); |
2406 | assert(code_start != NULL, "null code start")do { if (!(code_start != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2406, "assert(" "code_start != __null" ") failed", "null code start" ); ::breakpoint(); } } while (0); |
2407 | cfs->guarantee_more(code_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2408 | cfs->skip_u1_fast(code_length); |
2409 | |
2410 | // Exception handler table |
2411 | cfs->guarantee_more(2, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // exception_table_length |
2412 | exception_table_length = cfs->get_u2_fast(); |
2413 | if (exception_table_length > 0) { |
2414 | exception_table_start = parse_exception_table(cfs, |
2415 | code_length, |
2416 | exception_table_length, |
2417 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2418 | } |
2419 | |
2420 | // Parse additional attributes in code attribute |
2421 | cfs->guarantee_more(2, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // code_attributes_count |
2422 | u2 code_attributes_count = cfs->get_u2_fast(); |
2423 | |
2424 | unsigned int calculated_attribute_length = 0; |
2425 | |
2426 | calculated_attribute_length = |
2427 | sizeof(max_stack) + sizeof(max_locals) + sizeof(code_length); |
2428 | calculated_attribute_length += |
2429 | code_length + |
2430 | sizeof(exception_table_length) + |
2431 | sizeof(code_attributes_count) + |
2432 | exception_table_length * |
2433 | ( sizeof(u2) + // start_pc |
2434 | sizeof(u2) + // end_pc |
2435 | sizeof(u2) + // handler_pc |
2436 | sizeof(u2) ); // catch_type_index |
2437 | |
2438 | while (code_attributes_count--) { |
2439 | cfs->guarantee_more(6, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // code_attribute_name_index, code_attribute_length |
2440 | const u2 code_attribute_name_index = cfs->get_u2_fast(); |
2441 | const u4 code_attribute_length = cfs->get_u4_fast(); |
2442 | calculated_attribute_length += code_attribute_length + |
2443 | sizeof(code_attribute_name_index) + |
2444 | sizeof(code_attribute_length); |
2445 | check_property(valid_symbol_at(code_attribute_name_index), |
2446 | "Invalid code attribute name index %u in class file %s", |
2447 | code_attribute_name_index, |
2448 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2449 | if (LoadLineNumberTables && |
2450 | cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) { |
2451 | // Parse and compress line number table |
2452 | parse_linenumber_table(code_attribute_length, |
2453 | code_length, |
2454 | &linenumber_table, |
2455 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2456 | |
2457 | } else if (LoadLocalVariableTables && |
2458 | cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) { |
2459 | // Parse local variable table |
2460 | if (!lvt_allocated) { |
2461 | localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD((u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)) |
2462 | THREAD, u2, INITIAL_MAX_LVT_NUMBER)(u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)); |
2463 | localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD((const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)) |
2464 | THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER)(const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)); |
2465 | localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD((u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)) |
2466 | THREAD, u2, INITIAL_MAX_LVT_NUMBER)(u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)); |
2467 | localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD((const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)) |
2468 | THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER)(const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)); |
2469 | lvt_allocated = true; |
2470 | } |
2471 | if (lvt_cnt == max_lvt_cnt) { |
2472 | max_lvt_cnt <<= 1; |
2473 | localvariable_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_table_length, lvt_cnt, max_lvt_cnt)(u2*) resource_reallocate_bytes((char*)(localvariable_table_length ), (lvt_cnt) * sizeof(u2), (max_lvt_cnt) * sizeof(u2)); |
2474 | localvariable_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_table_start, lvt_cnt, max_lvt_cnt)(const unsafe_u2**) resource_reallocate_bytes((char*)(localvariable_table_start ), (lvt_cnt) * sizeof(const unsafe_u2*), (max_lvt_cnt) * sizeof (const unsafe_u2*)); |
2475 | } |
2476 | localvariable_table_start[lvt_cnt] = |
2477 | parse_localvariable_table(cfs, |
2478 | code_length, |
2479 | max_locals, |
2480 | code_attribute_length, |
2481 | &localvariable_table_length[lvt_cnt], |
2482 | false, // is not LVTT |
2483 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2484 | total_lvt_length += localvariable_table_length[lvt_cnt]; |
2485 | lvt_cnt++; |
2486 | } else if (LoadLocalVariableTypeTables && |
2487 | _major_version >= JAVA_1_5_VERSION49 && |
2488 | cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) { |
2489 | if (!lvt_allocated) { |
2490 | localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD((u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)) |
2491 | THREAD, u2, INITIAL_MAX_LVT_NUMBER)(u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)); |
2492 | localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD((const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)) |
2493 | THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER)(const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)); |
2494 | localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD((u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)) |
2495 | THREAD, u2, INITIAL_MAX_LVT_NUMBER)(u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)); |
2496 | localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD((const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)) |
2497 | THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER)(const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)); |
2498 | lvt_allocated = true; |
2499 | } |
2500 | // Parse local variable type table |
2501 | if (lvtt_cnt == max_lvtt_cnt) { |
2502 | max_lvtt_cnt <<= 1; |
2503 | localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt)(u2*) resource_reallocate_bytes((char*)(localvariable_type_table_length ), (lvtt_cnt) * sizeof(u2), (max_lvtt_cnt) * sizeof(u2)); |
2504 | localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt)(const unsafe_u2**) resource_reallocate_bytes((char*)(localvariable_type_table_start ), (lvtt_cnt) * sizeof(const unsafe_u2*), (max_lvtt_cnt) * sizeof (const unsafe_u2*)); |
2505 | } |
2506 | localvariable_type_table_start[lvtt_cnt] = |
2507 | parse_localvariable_table(cfs, |
2508 | code_length, |
2509 | max_locals, |
2510 | code_attribute_length, |
2511 | &localvariable_type_table_length[lvtt_cnt], |
2512 | true, // is LVTT |
2513 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2514 | lvtt_cnt++; |
2515 | } else if (_major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION && |
2516 | cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) { |
2517 | // Stack map is only needed by the new verifier in JDK1.5. |
2518 | if (parsed_stackmap_attribute) { |
2519 | classfile_parse_error("Multiple StackMapTable attributes in class file %s", THREAD__the_thread__); |
2520 | return NULL__null; |
2521 | } |
2522 | stackmap_data = parse_stackmap_table(cfs, code_attribute_length, _need_verify, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2523 | stackmap_data_length = code_attribute_length; |
2524 | parsed_stackmap_attribute = true; |
2525 | } else { |
2526 | // Skip unknown attributes |
2527 | cfs->skip_u1(code_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2528 | } |
2529 | } |
2530 | // check method attribute length |
2531 | if (_need_verify) { |
2532 | guarantee_property(method_attribute_length == calculated_attribute_length, |
2533 | "Code segment has wrong length in class file %s", |
2534 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2535 | } |
2536 | } else if (method_attribute_name == vmSymbols::tag_exceptions()) { |
2537 | // Parse Exceptions attribute |
2538 | if (parsed_checked_exceptions_attribute) { |
2539 | classfile_parse_error("Multiple Exceptions attributes in class file %s", |
2540 | THREAD__the_thread__); |
2541 | return NULL__null; |
2542 | } |
2543 | parsed_checked_exceptions_attribute = true; |
2544 | checked_exceptions_start = |
2545 | parse_checked_exceptions(cfs, |
2546 | &checked_exceptions_length, |
2547 | method_attribute_length, |
2548 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2549 | } else if (method_attribute_name == vmSymbols::tag_method_parameters()) { |
2550 | // reject multiple method parameters |
2551 | if (method_parameters_seen) { |
2552 | classfile_parse_error("Multiple MethodParameters attributes in class file %s", |
2553 | THREAD__the_thread__); |
2554 | return NULL__null; |
2555 | } |
2556 | method_parameters_seen = true; |
2557 | method_parameters_length = cfs->get_u1_fast(); |
2558 | const u2 real_length = (method_parameters_length * 4u) + 1u; |
2559 | if (method_attribute_length != real_length) { |
2560 | classfile_parse_error( |
2561 | "Invalid MethodParameters method attribute length %u in class file", |
2562 | method_attribute_length, THREAD__the_thread__); |
2563 | return NULL__null; |
2564 | } |
2565 | method_parameters_data = cfs->current(); |
2566 | cfs->skip_u2_fast(method_parameters_length); |
2567 | cfs->skip_u2_fast(method_parameters_length); |
2568 | // ignore this attribute if it cannot be reflected |
2569 | if (!vmClasses::Parameter_klass_loaded()) |
2570 | method_parameters_length = -1; |
2571 | } else if (method_attribute_name == vmSymbols::tag_synthetic()) { |
2572 | if (method_attribute_length != 0) { |
2573 | classfile_parse_error( |
2574 | "Invalid Synthetic method attribute length %u in class file %s", |
2575 | method_attribute_length, THREAD__the_thread__); |
2576 | return NULL__null; |
2577 | } |
2578 | // Should we check that there hasn't already been a synthetic attribute? |
2579 | access_flags.set_is_synthetic(); |
2580 | } else if (method_attribute_name == vmSymbols::tag_deprecated()) { // 4276120 |
2581 | if (method_attribute_length != 0) { |
2582 | classfile_parse_error( |
2583 | "Invalid Deprecated method attribute length %u in class file %s", |
2584 | method_attribute_length, THREAD__the_thread__); |
2585 | return NULL__null; |
2586 | } |
2587 | } else if (_major_version >= JAVA_1_5_VERSION49) { |
2588 | if (method_attribute_name == vmSymbols::tag_signature()) { |
2589 | if (generic_signature_index != 0) { |
2590 | classfile_parse_error( |
2591 | "Multiple Signature attributes for method in class file %s", |
2592 | THREAD__the_thread__); |
2593 | return NULL__null; |
2594 | } |
2595 | if (method_attribute_length != 2) { |
2596 | classfile_parse_error( |
2597 | "Invalid Signature attribute length %u in class file %s", |
2598 | method_attribute_length, THREAD__the_thread__); |
2599 | return NULL__null; |
2600 | } |
2601 | generic_signature_index = parse_generic_signature_attribute(cfs, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2602 | } else if (method_attribute_name == vmSymbols::tag_runtime_visible_annotations()) { |
2603 | if (runtime_visible_annotations != NULL__null) { |
2604 | classfile_parse_error( |
2605 | "Multiple RuntimeVisibleAnnotations attributes for method in class file %s", |
2606 | THREAD__the_thread__); |
2607 | return NULL__null; |
2608 | } |
2609 | runtime_visible_annotations_length = method_attribute_length; |
2610 | runtime_visible_annotations = cfs->current(); |
2611 | assert(runtime_visible_annotations != NULL, "null visible annotations")do { if (!(runtime_visible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2611, "assert(" "runtime_visible_annotations != __null" ") failed" , "null visible annotations"); ::breakpoint(); } } while (0); |
2612 | cfs->guarantee_more(runtime_visible_annotations_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2613 | parse_annotations(cp, |
2614 | runtime_visible_annotations, |
2615 | runtime_visible_annotations_length, |
2616 | &parsed_annotations, |
2617 | _loader_data, |
2618 | _can_access_vm_annotations); |
2619 | cfs->skip_u1_fast(runtime_visible_annotations_length); |
2620 | } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { |
2621 | if (runtime_invisible_annotations_exists) { |
2622 | classfile_parse_error( |
2623 | "Multiple RuntimeInvisibleAnnotations attributes for method in class file %s", |
2624 | THREAD__the_thread__); |
2625 | return NULL__null; |
2626 | } |
2627 | runtime_invisible_annotations_exists = true; |
2628 | if (PreserveAllAnnotations) { |
2629 | runtime_invisible_annotations_length = method_attribute_length; |
2630 | runtime_invisible_annotations = cfs->current(); |
2631 | assert(runtime_invisible_annotations != NULL, "null invisible annotations")do { if (!(runtime_invisible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2631, "assert(" "runtime_invisible_annotations != __null" ") failed" , "null invisible annotations"); ::breakpoint(); } } while (0 ); |
2632 | } |
2633 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2634 | } else if (method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) { |
2635 | if (runtime_visible_parameter_annotations != NULL__null) { |
2636 | classfile_parse_error( |
2637 | "Multiple RuntimeVisibleParameterAnnotations attributes for method in class file %s", |
2638 | THREAD__the_thread__); |
2639 | return NULL__null; |
2640 | } |
2641 | runtime_visible_parameter_annotations_length = method_attribute_length; |
2642 | runtime_visible_parameter_annotations = cfs->current(); |
2643 | assert(runtime_visible_parameter_annotations != NULL, "null visible parameter annotations")do { if (!(runtime_visible_parameter_annotations != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2643, "assert(" "runtime_visible_parameter_annotations != __null" ") failed", "null visible parameter annotations"); ::breakpoint (); } } while (0); |
2644 | cfs->skip_u1(runtime_visible_parameter_annotations_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2645 | } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_parameter_annotations()) { |
2646 | if (runtime_invisible_parameter_annotations_exists) { |
2647 | classfile_parse_error( |
2648 | "Multiple RuntimeInvisibleParameterAnnotations attributes for method in class file %s", |
2649 | THREAD__the_thread__); |
2650 | return NULL__null; |
2651 | } |
2652 | runtime_invisible_parameter_annotations_exists = true; |
2653 | if (PreserveAllAnnotations) { |
2654 | runtime_invisible_parameter_annotations_length = method_attribute_length; |
2655 | runtime_invisible_parameter_annotations = cfs->current(); |
2656 | assert(runtime_invisible_parameter_annotations != NULL,do { if (!(runtime_invisible_parameter_annotations != __null) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2657, "assert(" "runtime_invisible_parameter_annotations != __null" ") failed", "null invisible parameter annotations"); ::breakpoint (); } } while (0) |
2657 | "null invisible parameter annotations")do { if (!(runtime_invisible_parameter_annotations != __null) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2657, "assert(" "runtime_invisible_parameter_annotations != __null" ") failed", "null invisible parameter annotations"); ::breakpoint (); } } while (0); |
2658 | } |
2659 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2660 | } else if (method_attribute_name == vmSymbols::tag_annotation_default()) { |
2661 | if (annotation_default != NULL__null) { |
2662 | classfile_parse_error( |
2663 | "Multiple AnnotationDefault attributes for method in class file %s", |
2664 | THREAD__the_thread__); |
2665 | return NULL__null; |
2666 | } |
2667 | annotation_default_length = method_attribute_length; |
2668 | annotation_default = cfs->current(); |
2669 | assert(annotation_default != NULL, "null annotation default")do { if (!(annotation_default != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2669, "assert(" "annotation_default != __null" ") failed", "null annotation default" ); ::breakpoint(); } } while (0); |
2670 | cfs->skip_u1(annotation_default_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2671 | } else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { |
2672 | if (runtime_visible_type_annotations != NULL__null) { |
2673 | classfile_parse_error( |
2674 | "Multiple RuntimeVisibleTypeAnnotations attributes for method in class file %s", |
2675 | THREAD__the_thread__); |
2676 | return NULL__null; |
2677 | } |
2678 | runtime_visible_type_annotations_length = method_attribute_length; |
2679 | runtime_visible_type_annotations = cfs->current(); |
2680 | assert(runtime_visible_type_annotations != NULL, "null visible type annotations")do { if (!(runtime_visible_type_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2680, "assert(" "runtime_visible_type_annotations != __null" ") failed", "null visible type annotations"); ::breakpoint() ; } } while (0); |
2681 | // No need for the VM to parse Type annotations |
2682 | cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2683 | } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { |
2684 | if (runtime_invisible_type_annotations_exists) { |
2685 | classfile_parse_error( |
2686 | "Multiple RuntimeInvisibleTypeAnnotations attributes for method in class file %s", |
2687 | THREAD__the_thread__); |
2688 | return NULL__null; |
2689 | } else { |
2690 | runtime_invisible_type_annotations_exists = true; |
2691 | } |
2692 | if (PreserveAllAnnotations) { |
2693 | runtime_invisible_type_annotations_length = method_attribute_length; |
2694 | runtime_invisible_type_annotations = cfs->current(); |
2695 | assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations")do { if (!(runtime_invisible_type_annotations != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2695, "assert(" "runtime_invisible_type_annotations != __null" ") failed", "null invisible type annotations"); ::breakpoint (); } } while (0); |
2696 | } |
2697 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2698 | } else { |
2699 | // Skip unknown attributes |
2700 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2701 | } |
2702 | } else { |
2703 | // Skip unknown attributes |
2704 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2705 | } |
2706 | } |
2707 | |
2708 | if (linenumber_table != NULL__null) { |
2709 | linenumber_table->write_terminator(); |
2710 | linenumber_table_length = linenumber_table->position(); |
2711 | } |
2712 | |
2713 | // Make sure there's at least one Code attribute in non-native/non-abstract method |
2714 | if (_need_verify) { |
2715 | guarantee_property(access_flags.is_native() || |
2716 | access_flags.is_abstract() || |
2717 | parsed_code_attribute, |
2718 | "Absent Code attribute in method that is not native or abstract in class file %s", |
2719 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2720 | } |
2721 | |
2722 | // All sizing information for a Method* is finally available, now create it |
2723 | InlineTableSizes sizes( |
2724 | total_lvt_length, |
2725 | linenumber_table_length, |
2726 | exception_table_length, |
2727 | checked_exceptions_length, |
2728 | method_parameters_length, |
2729 | generic_signature_index, |
2730 | runtime_visible_annotations_length + |
2731 | runtime_invisible_annotations_length, |
2732 | runtime_visible_parameter_annotations_length + |
2733 | runtime_invisible_parameter_annotations_length, |
2734 | runtime_visible_type_annotations_length + |
2735 | runtime_invisible_type_annotations_length, |
2736 | annotation_default_length, |
2737 | 0); |
2738 | |
2739 | Method* const m = Method::allocate(_loader_data, |
2740 | code_length, |
2741 | access_flags, |
2742 | &sizes, |
2743 | ConstMethod::NORMAL, |
2744 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2745 | |
2746 | ClassLoadingService::add_class_method_size(m->size()*wordSize); |
2747 | |
2748 | // Fill in information from fixed part (access_flags already set) |
2749 | m->set_constants(_cp); |
2750 | m->set_name_index(name_index); |
2751 | m->set_signature_index(signature_index); |
2752 | m->compute_from_signature(cp->symbol_at(signature_index)); |
2753 | assert(args_size < 0 || args_size == m->size_of_parameters(), "")do { if (!(args_size < 0 || args_size == m->size_of_parameters ())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2753, "assert(" "args_size < 0 || args_size == m->size_of_parameters()" ") failed", ""); ::breakpoint(); } } while (0); |
2754 | |
2755 | // Fill in code attribute information |
2756 | m->set_max_stack(max_stack); |
2757 | m->set_max_locals(max_locals); |
2758 | if (stackmap_data != NULL__null) { |
2759 | m->constMethod()->copy_stackmap_data(_loader_data, |
2760 | (u1*)stackmap_data, |
2761 | stackmap_data_length, |
2762 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2763 | } |
2764 | |
2765 | // Copy byte codes |
2766 | m->set_code((u1*)code_start); |
2767 | |
2768 | // Copy line number table |
2769 | if (linenumber_table != NULL__null) { |
2770 | memcpy(m->compressed_linenumber_table(), |
2771 | linenumber_table->buffer(), |
2772 | linenumber_table_length); |
2773 | } |
2774 | |
2775 | // Copy exception table |
2776 | if (exception_table_length > 0) { |
2777 | Copy::conjoint_swap_if_needed<Endian::JAVA>(exception_table_start, |
2778 | m->exception_table_start(), |
2779 | exception_table_length * sizeof(ExceptionTableElement), |
2780 | sizeof(u2)); |
2781 | } |
2782 | |
2783 | // Copy method parameters |
2784 | if (method_parameters_length > 0) { |
2785 | MethodParametersElement* elem = m->constMethod()->method_parameters_start(); |
2786 | for (int i = 0; i < method_parameters_length; i++) { |
2787 | elem[i].name_cp_index = Bytes::get_Java_u2((address)method_parameters_data); |
2788 | method_parameters_data += 2; |
2789 | elem[i].flags = Bytes::get_Java_u2((address)method_parameters_data); |
2790 | method_parameters_data += 2; |
2791 | } |
2792 | } |
2793 | |
2794 | // Copy checked exceptions |
2795 | if (checked_exceptions_length > 0) { |
2796 | Copy::conjoint_swap_if_needed<Endian::JAVA>(checked_exceptions_start, |
2797 | m->checked_exceptions_start(), |
2798 | checked_exceptions_length * sizeof(CheckedExceptionElement), |
2799 | sizeof(u2)); |
2800 | } |
2801 | |
2802 | // Copy class file LVT's/LVTT's into the HotSpot internal LVT. |
2803 | if (total_lvt_length > 0) { |
2804 | promoted_flags->set_has_localvariable_table(); |
2805 | copy_localvariable_table(m->constMethod(), |
2806 | lvt_cnt, |
2807 | localvariable_table_length, |
2808 | localvariable_table_start, |
2809 | lvtt_cnt, |
2810 | localvariable_type_table_length, |
2811 | localvariable_type_table_start, |
2812 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2813 | } |
2814 | |
2815 | if (parsed_annotations.has_any_annotations()) |
2816 | parsed_annotations.apply_to(methodHandle(THREAD__the_thread__, m)); |
2817 | |
2818 | if (is_hidden()) { // Mark methods in hidden classes as 'hidden'. |
2819 | m->set_hidden(true); |
2820 | } |
2821 | |
2822 | // Copy annotations |
2823 | copy_method_annotations(m->constMethod(), |
2824 | runtime_visible_annotations, |
2825 | runtime_visible_annotations_length, |
2826 | runtime_invisible_annotations, |
2827 | runtime_invisible_annotations_length, |
2828 | runtime_visible_parameter_annotations, |
2829 | runtime_visible_parameter_annotations_length, |
2830 | runtime_invisible_parameter_annotations, |
2831 | runtime_invisible_parameter_annotations_length, |
2832 | runtime_visible_type_annotations, |
2833 | runtime_visible_type_annotations_length, |
2834 | runtime_invisible_type_annotations, |
2835 | runtime_invisible_type_annotations_length, |
2836 | annotation_default, |
2837 | annotation_default_length, |
2838 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
2839 | |
2840 | if (InstanceKlass::is_finalization_enabled() && |
2841 | name == vmSymbols::finalize_method_name() && |
2842 | signature == vmSymbols::void_method_signature()) { |
2843 | if (m->is_empty_method()) { |
2844 | _has_empty_finalizer = true; |
2845 | } else { |
2846 | _has_finalizer = true; |
2847 | } |
2848 | } |
2849 | if (name == vmSymbols::object_initializer_name() && |
2850 | signature == vmSymbols::void_method_signature() && |
2851 | m->is_vanilla_constructor()) { |
2852 | _has_vanilla_constructor = true; |
2853 | } |
2854 | |
2855 | NOT_PRODUCT(m->verify())m->verify(); |
2856 | return m; |
2857 | } |
2858 | |
2859 | |
2860 | // The promoted_flags parameter is used to pass relevant access_flags |
2861 | // from the methods back up to the containing klass. These flag values |
2862 | // are added to klass's access_flags. |
2863 | // Side-effects: populates the _methods field in the parser |
2864 | void ClassFileParser::parse_methods(const ClassFileStream* const cfs, |
2865 | bool is_interface, |
2866 | AccessFlags* promoted_flags, |
2867 | bool* has_final_method, |
2868 | bool* declares_nonstatic_concrete_methods, |
2869 | TRAPSJavaThread* __the_thread__) { |
2870 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2870, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
2871 | assert(promoted_flags != NULL, "invariant")do { if (!(promoted_flags != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2871, "assert(" "promoted_flags != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
2872 | assert(has_final_method != NULL, "invariant")do { if (!(has_final_method != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2872, "assert(" "has_final_method != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
2873 | assert(declares_nonstatic_concrete_methods != NULL, "invariant")do { if (!(declares_nonstatic_concrete_methods != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2873, "assert(" "declares_nonstatic_concrete_methods != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
2874 | |
2875 | assert(NULL == _methods, "invariant")do { if (!(__null == _methods)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2875, "assert(" "__null == _methods" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
2876 | |
2877 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // length |
2878 | const u2 length = cfs->get_u2_fast(); |
2879 | if (length == 0) { |
2880 | _methods = Universe::the_empty_method_array(); |
2881 | } else { |
2882 | _methods = MetadataFactory::new_array<Method*>(_loader_data, |
2883 | length, |
2884 | NULL__null, |
2885 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
2886 | |
2887 | for (int index = 0; index < length; index++) { |
2888 | Method* method = parse_method(cfs, |
2889 | is_interface, |
2890 | _cp, |
2891 | promoted_flags, |
2892 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
2893 | |
2894 | if (method->is_final()) { |
2895 | *has_final_method = true; |
2896 | } |
2897 | // declares_nonstatic_concrete_methods: declares concrete instance methods, any access flags |
2898 | // used for interface initialization, and default method inheritance analysis |
2899 | if (is_interface && !(*declares_nonstatic_concrete_methods) |
2900 | && !method->is_abstract() && !method->is_static()) { |
2901 | *declares_nonstatic_concrete_methods = true; |
2902 | } |
2903 | _methods->at_put(index, method); |
2904 | } |
2905 | |
2906 | if (_need_verify && length > 1) { |
2907 | // Check duplicated methods |
2908 | ResourceMark rm(THREAD__the_thread__); |
2909 | NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD((NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)) |
2910 | THREAD, NameSigHash*, HASH_ROW_SIZE)(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)); |
2911 | initialize_hashtable(names_and_sigs); |
2912 | bool dup = false; |
2913 | const Symbol* name = NULL__null; |
2914 | const Symbol* sig = NULL__null; |
2915 | { |
2916 | debug_only(NoSafepointVerifier nsv;)NoSafepointVerifier nsv; |
2917 | for (int i = 0; i < length; i++) { |
2918 | const Method* const m = _methods->at(i); |
2919 | name = m->name(); |
2920 | sig = m->signature(); |
2921 | // If no duplicates, add name/signature in hashtable names_and_sigs. |
2922 | if (!put_after_lookup(name, sig, names_and_sigs)) { |
2923 | dup = true; |
2924 | break; |
2925 | } |
2926 | } |
2927 | } |
2928 | if (dup) { |
2929 | classfile_parse_error("Duplicate method name \"%s\" with signature \"%s\" in class file %s", |
2930 | name->as_C_string(), sig->as_klass_external_name(), THREAD__the_thread__); |
2931 | } |
2932 | } |
2933 | } |
2934 | } |
2935 | |
2936 | static const intArray* sort_methods(Array<Method*>* methods) { |
2937 | const int length = methods->length(); |
2938 | // If JVMTI original method ordering or sharing is enabled we have to |
2939 | // remember the original class file ordering. |
2940 | // We temporarily use the vtable_index field in the Method* to store the |
2941 | // class file index, so we can read in after calling qsort. |
2942 | // Put the method ordering in the shared archive. |
2943 | if (JvmtiExport::can_maintain_original_method_order() || Arguments::is_dumping_archive()) { |
2944 | for (int index = 0; index < length; index++) { |
2945 | Method* const m = methods->at(index); |
2946 | assert(!m->valid_vtable_index(), "vtable index should not be set")do { if (!(!m->valid_vtable_index())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2946, "assert(" "!m->valid_vtable_index()" ") failed", "vtable index should not be set" ); ::breakpoint(); } } while (0); |
2947 | m->set_vtable_index(index); |
2948 | } |
2949 | } |
2950 | // Sort method array by ascending method name (for faster lookups & vtable construction) |
2951 | // Note that the ordering is not alphabetical, see Symbol::fast_compare |
2952 | Method::sort_methods(methods); |
2953 | |
2954 | intArray* method_ordering = NULL__null; |
2955 | // If JVMTI original method ordering or sharing is enabled construct int |
2956 | // array remembering the original ordering |
2957 | if (JvmtiExport::can_maintain_original_method_order() || Arguments::is_dumping_archive()) { |
2958 | method_ordering = new intArray(length, length, -1); |
2959 | for (int index = 0; index < length; index++) { |
2960 | Method* const m = methods->at(index); |
2961 | const int old_index = m->vtable_index(); |
2962 | assert(old_index >= 0 && old_index < length, "invalid method index")do { if (!(old_index >= 0 && old_index < length )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2962, "assert(" "old_index >= 0 && old_index < length" ") failed", "invalid method index"); ::breakpoint(); } } while (0); |
2963 | method_ordering->at_put(index, old_index); |
2964 | m->set_vtable_index(Method::invalid_vtable_index); |
2965 | } |
2966 | } |
2967 | return method_ordering; |
2968 | } |
2969 | |
2970 | // Parse generic_signature attribute for methods and fields |
2971 | u2 ClassFileParser::parse_generic_signature_attribute(const ClassFileStream* const cfs, |
2972 | TRAPSJavaThread* __the_thread__) { |
2973 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2973, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
2974 | |
2975 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // generic_signature_index |
2976 | const u2 generic_signature_index = cfs->get_u2_fast(); |
2977 | check_property( |
2978 | valid_symbol_at(generic_signature_index), |
2979 | "Invalid Signature attribute at constant pool index %u in class file %s", |
2980 | generic_signature_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
2981 | return generic_signature_index; |
2982 | } |
2983 | |
2984 | void ClassFileParser::parse_classfile_sourcefile_attribute(const ClassFileStream* const cfs, |
2985 | TRAPSJavaThread* __the_thread__) { |
2986 | |
2987 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2987, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
2988 | |
2989 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // sourcefile_index |
2990 | const u2 sourcefile_index = cfs->get_u2_fast(); |
2991 | check_property( |
2992 | valid_symbol_at(sourcefile_index), |
2993 | "Invalid SourceFile attribute at constant pool index %u in class file %s", |
2994 | sourcefile_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
2995 | set_class_sourcefile_index(sourcefile_index); |
2996 | } |
2997 | |
2998 | void ClassFileParser::parse_classfile_source_debug_extension_attribute(const ClassFileStream* const cfs, |
2999 | int length, |
3000 | TRAPSJavaThread* __the_thread__) { |
3001 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3001, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
3002 | |
3003 | const u1* const sde_buffer = cfs->current(); |
3004 | assert(sde_buffer != NULL, "null sde buffer")do { if (!(sde_buffer != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3004, "assert(" "sde_buffer != __null" ") failed", "null sde buffer" ); ::breakpoint(); } } while (0); |
3005 | |
3006 | // Don't bother storing it if there is no way to retrieve it |
3007 | if (JvmtiExport::can_get_source_debug_extension()) { |
3008 | assert((length+1) > length, "Overflow checking")do { if (!((length+1) > length)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3008, "assert(" "(length+1) > length" ") failed", "Overflow checking" ); ::breakpoint(); } } while (0); |
3009 | u1* const sde = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, u1, length+1)(u1*) resource_allocate_bytes(__the_thread__, (length+1) * sizeof (u1)); |
3010 | for (int i = 0; i < length; i++) { |
3011 | sde[i] = sde_buffer[i]; |
3012 | } |
3013 | sde[length] = '\0'; |
3014 | set_class_sde_buffer((const char*)sde, length); |
3015 | } |
3016 | // Got utf8 string, set stream position forward |
3017 | cfs->skip_u1(length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3018 | } |
3019 | |
3020 | |
3021 | // Inner classes can be static, private or protected (classic VM does this) |
3022 | #define RECOGNIZED_INNER_CLASS_MODIFIERS( (JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC ) ( JVM_RECOGNIZED_CLASS_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | \ |
3023 | JVM_ACC_PRIVATE | \ |
3024 | JVM_ACC_PROTECTED | \ |
3025 | JVM_ACC_STATIC \ |
3026 | ) |
3027 | |
3028 | // Find index of the InnerClasses entry for the specified inner_class_info_index. |
3029 | // Return -1 if none is found. |
3030 | static int inner_classes_find_index(const Array<u2>* inner_classes, int inner, const ConstantPool* cp, int length) { |
3031 | Symbol* cp_klass_name = cp->klass_name_at(inner); |
3032 | for (int idx = 0; idx < length; idx += InstanceKlass::inner_class_next_offset) { |
3033 | int idx_inner = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset); |
3034 | if (cp->klass_name_at(idx_inner) == cp_klass_name) { |
3035 | return idx; |
3036 | } |
3037 | } |
3038 | return -1; |
3039 | } |
3040 | |
3041 | // Return the outer_class_info_index for the InnerClasses entry containing the |
3042 | // specified inner_class_info_index. Return -1 if no InnerClasses entry is found. |
3043 | static int inner_classes_jump_to_outer(const Array<u2>* inner_classes, int inner, const ConstantPool* cp, int length) { |
3044 | if (inner == 0) return -1; |
3045 | int idx = inner_classes_find_index(inner_classes, inner, cp, length); |
3046 | if (idx == -1) return -1; |
3047 | int result = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset); |
3048 | return result; |
3049 | } |
3050 | |
3051 | // Return true if circularity is found, false if no circularity is found. |
3052 | // Use Floyd's cycle finding algorithm. |
3053 | static bool inner_classes_check_loop_through_outer(const Array<u2>* inner_classes, int idx, const ConstantPool* cp, int length) { |
3054 | int slow = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset); |
3055 | int fast = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset); |
3056 | while (fast != -1 && fast != 0) { |
3057 | if (slow != 0 && (cp->klass_name_at(slow) == cp->klass_name_at(fast))) { |
3058 | return true; // found a circularity |
3059 | } |
3060 | fast = inner_classes_jump_to_outer(inner_classes, fast, cp, length); |
3061 | if (fast == -1) return false; |
3062 | fast = inner_classes_jump_to_outer(inner_classes, fast, cp, length); |
3063 | if (fast == -1) return false; |
3064 | slow = inner_classes_jump_to_outer(inner_classes, slow, cp, length); |
3065 | assert(slow != -1, "sanity check")do { if (!(slow != -1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3065, "assert(" "slow != -1" ") failed", "sanity check"); :: breakpoint(); } } while (0); |
3066 | } |
3067 | return false; |
3068 | } |
3069 | |
3070 | // Loop through each InnerClasses entry checking for circularities and duplications |
3071 | // with other entries. If duplicate entries are found then throw CFE. Otherwise, |
3072 | // return true if a circularity or entries with duplicate inner_class_info_indexes |
3073 | // are found. |
3074 | bool ClassFileParser::check_inner_classes_circularity(const ConstantPool* cp, int length, TRAPSJavaThread* __the_thread__) { |
3075 | // Loop through each InnerClasses entry. |
3076 | for (int idx = 0; idx < length; idx += InstanceKlass::inner_class_next_offset) { |
3077 | // Return true if there are circular entries. |
3078 | if (inner_classes_check_loop_through_outer(_inner_classes, idx, cp, length)) { |
3079 | return true; |
3080 | } |
3081 | // Check if there are duplicate entries or entries with the same inner_class_info_index. |
3082 | for (int y = idx + InstanceKlass::inner_class_next_offset; y < length; |
3083 | y += InstanceKlass::inner_class_next_offset) { |
3084 | |
3085 | // To maintain compatibility, throw an exception if duplicate inner classes |
3086 | // entries are found. |
3087 | guarantee_property((_inner_classes->at(idx) != _inner_classes->at(y) || |
3088 | _inner_classes->at(idx+1) != _inner_classes->at(y+1) || |
3089 | _inner_classes->at(idx+2) != _inner_classes->at(y+2) || |
3090 | _inner_classes->at(idx+3) != _inner_classes->at(y+3)), |
3091 | "Duplicate entry in InnerClasses attribute in class file %s", |
3092 | CHECK_(true)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return true; (void)(0); |
3093 | // Return true if there are two entries with the same inner_class_info_index. |
3094 | if (_inner_classes->at(y) == _inner_classes->at(idx)) { |
3095 | return true; |
3096 | } |
3097 | } |
3098 | } |
3099 | return false; |
3100 | } |
3101 | |
3102 | // Return number of classes in the inner classes attribute table |
3103 | u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs, |
3104 | const ConstantPool* cp, |
3105 | const u1* const inner_classes_attribute_start, |
3106 | bool parsed_enclosingmethod_attribute, |
3107 | u2 enclosing_method_class_index, |
3108 | u2 enclosing_method_method_index, |
3109 | TRAPSJavaThread* __the_thread__) { |
3110 | const u1* const current_mark = cfs->current(); |
3111 | u2 length = 0; |
3112 | if (inner_classes_attribute_start != NULL__null) { |
3113 | cfs->set_current(inner_classes_attribute_start); |
3114 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // length |
3115 | length = cfs->get_u2_fast(); |
3116 | } |
3117 | |
3118 | // 4-tuples of shorts of inner classes data and 2 shorts of enclosing |
3119 | // method data: |
3120 | // [inner_class_info_index, |
3121 | // outer_class_info_index, |
3122 | // inner_name_index, |
3123 | // inner_class_access_flags, |
3124 | // ... |
3125 | // enclosing_method_class_index, |
3126 | // enclosing_method_method_index] |
3127 | const int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0); |
3128 | Array<u2>* inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3129 | _inner_classes = inner_classes; |
3130 | |
3131 | int index = 0; |
3132 | cfs->guarantee_more(8 * length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // 4-tuples of u2 |
3133 | for (int n = 0; n < length; n++) { |
3134 | // Inner class index |
3135 | const u2 inner_class_info_index = cfs->get_u2_fast(); |
3136 | check_property( |
3137 | valid_klass_reference_at(inner_class_info_index), |
3138 | "inner_class_info_index %u has bad constant type in class file %s", |
3139 | inner_class_info_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3140 | // Outer class index |
3141 | const u2 outer_class_info_index = cfs->get_u2_fast(); |
3142 | check_property( |
3143 | outer_class_info_index == 0 || |
3144 | valid_klass_reference_at(outer_class_info_index), |
3145 | "outer_class_info_index %u has bad constant type in class file %s", |
3146 | outer_class_info_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3147 | |
3148 | if (outer_class_info_index != 0) { |
3149 | const Symbol* const outer_class_name = cp->klass_name_at(outer_class_info_index); |
3150 | char* bytes = (char*)outer_class_name->bytes(); |
3151 | guarantee_property(bytes[0] != JVM_SIGNATURE_ARRAY, |
3152 | "Outer class is an array class in class file %s", CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3153 | } |
3154 | // Inner class name |
3155 | const u2 inner_name_index = cfs->get_u2_fast(); |
3156 | check_property( |
3157 | inner_name_index == 0 || valid_symbol_at(inner_name_index), |
3158 | "inner_name_index %u has bad constant type in class file %s", |
3159 | inner_name_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3160 | if (_need_verify) { |
3161 | guarantee_property(inner_class_info_index != outer_class_info_index, |
3162 | "Class is both outer and inner class in class file %s", CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3163 | } |
3164 | // Access flags |
3165 | jint flags; |
3166 | // JVM_ACC_MODULE is defined in JDK-9 and later. |
3167 | if (_major_version >= JAVA_9_VERSION53) { |
3168 | flags = cfs->get_u2_fast() & (RECOGNIZED_INNER_CLASS_MODIFIERS( (JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC ) | JVM_ACC_MODULE); |
3169 | } else { |
3170 | flags = cfs->get_u2_fast() & RECOGNIZED_INNER_CLASS_MODIFIERS( (JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC ); |
3171 | } |
3172 | if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION50) { |
3173 | // Set abstract bit for old class files for backward compatibility |
3174 | flags |= JVM_ACC_ABSTRACT; |
3175 | } |
3176 | verify_legal_class_modifiers(flags, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3177 | AccessFlags inner_access_flags(flags); |
3178 | |
3179 | inner_classes->at_put(index++, inner_class_info_index); |
3180 | inner_classes->at_put(index++, outer_class_info_index); |
3181 | inner_classes->at_put(index++, inner_name_index); |
3182 | inner_classes->at_put(index++, inner_access_flags.as_short()); |
3183 | } |
3184 | |
3185 | // 4347400: make sure there's no duplicate entry in the classes array |
3186 | // Also, check for circular entries. |
3187 | bool has_circularity = false; |
3188 | if (_need_verify && _major_version >= JAVA_1_5_VERSION49) { |
3189 | has_circularity = check_inner_classes_circularity(cp, length * 4, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3190 | if (has_circularity) { |
3191 | // If circularity check failed then ignore InnerClasses attribute. |
3192 | MetadataFactory::free_array<u2>(_loader_data, _inner_classes); |
3193 | index = 0; |
3194 | if (parsed_enclosingmethod_attribute) { |
3195 | inner_classes = MetadataFactory::new_array<u2>(_loader_data, 2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3196 | _inner_classes = inner_classes; |
3197 | } else { |
3198 | _inner_classes = Universe::the_empty_short_array(); |
3199 | } |
3200 | } |
3201 | } |
3202 | // Set EnclosingMethod class and method indexes. |
3203 | if (parsed_enclosingmethod_attribute) { |
3204 | inner_classes->at_put(index++, enclosing_method_class_index); |
3205 | inner_classes->at_put(index++, enclosing_method_method_index); |
3206 | } |
3207 | assert(index == size || has_circularity, "wrong size")do { if (!(index == size || has_circularity)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3207, "assert(" "index == size || has_circularity" ") failed" , "wrong size"); ::breakpoint(); } } while (0); |
3208 | |
3209 | // Restore buffer's current position. |
3210 | cfs->set_current(current_mark); |
3211 | |
3212 | return length; |
3213 | } |
3214 | |
3215 | u2 ClassFileParser::parse_classfile_nest_members_attribute(const ClassFileStream* const cfs, |
3216 | const u1* const nest_members_attribute_start, |
3217 | TRAPSJavaThread* __the_thread__) { |
3218 | const u1* const current_mark = cfs->current(); |
3219 | u2 length = 0; |
3220 | if (nest_members_attribute_start != NULL__null) { |
3221 | cfs->set_current(nest_members_attribute_start); |
3222 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // length |
3223 | length = cfs->get_u2_fast(); |
3224 | } |
3225 | const int size = length; |
3226 | Array<u2>* const nest_members = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3227 | _nest_members = nest_members; |
3228 | |
3229 | int index = 0; |
3230 | cfs->guarantee_more(2 * length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3231 | for (int n = 0; n < length; n++) { |
3232 | const u2 class_info_index = cfs->get_u2_fast(); |
3233 | check_property( |
3234 | valid_klass_reference_at(class_info_index), |
3235 | "Nest member class_info_index %u has bad constant type in class file %s", |
3236 | class_info_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3237 | nest_members->at_put(index++, class_info_index); |
3238 | } |
3239 | assert(index == size, "wrong size")do { if (!(index == size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3239, "assert(" "index == size" ") failed", "wrong size"); :: breakpoint(); } } while (0); |
3240 | |
3241 | // Restore buffer's current position. |
3242 | cfs->set_current(current_mark); |
3243 | |
3244 | return length; |
3245 | } |
3246 | |
3247 | u2 ClassFileParser::parse_classfile_permitted_subclasses_attribute(const ClassFileStream* const cfs, |
3248 | const u1* const permitted_subclasses_attribute_start, |
3249 | TRAPSJavaThread* __the_thread__) { |
3250 | const u1* const current_mark = cfs->current(); |
3251 | u2 length = 0; |
3252 | if (permitted_subclasses_attribute_start != NULL__null) { |
3253 | cfs->set_current(permitted_subclasses_attribute_start); |
3254 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // length |
3255 | length = cfs->get_u2_fast(); |
3256 | } |
3257 | const int size = length; |
3258 | Array<u2>* const permitted_subclasses = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3259 | _permitted_subclasses = permitted_subclasses; |
3260 | |
3261 | if (length > 0) { |
3262 | int index = 0; |
3263 | cfs->guarantee_more(2 * length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3264 | for (int n = 0; n < length; n++) { |
3265 | const u2 class_info_index = cfs->get_u2_fast(); |
3266 | check_property( |
3267 | valid_klass_reference_at(class_info_index), |
3268 | "Permitted subclass class_info_index %u has bad constant type in class file %s", |
3269 | class_info_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3270 | permitted_subclasses->at_put(index++, class_info_index); |
3271 | } |
3272 | assert(index == size, "wrong size")do { if (!(index == size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3272, "assert(" "index == size" ") failed", "wrong size"); :: breakpoint(); } } while (0); |
3273 | } |
3274 | |
3275 | // Restore buffer's current position. |
3276 | cfs->set_current(current_mark); |
3277 | |
3278 | return length; |
3279 | } |
3280 | |
3281 | // Record { |
3282 | // u2 attribute_name_index; |
3283 | // u4 attribute_length; |
3284 | // u2 components_count; |
3285 | // component_info components[components_count]; |
3286 | // } |
3287 | // component_info { |
3288 | // u2 name_index; |
3289 | // u2 descriptor_index |
3290 | // u2 attributes_count; |
3291 | // attribute_info_attributes[attributes_count]; |
3292 | // } |
3293 | u2 ClassFileParser::parse_classfile_record_attribute(const ClassFileStream* const cfs, |
3294 | const ConstantPool* cp, |
3295 | const u1* const record_attribute_start, |
3296 | TRAPSJavaThread* __the_thread__) { |
3297 | const u1* const current_mark = cfs->current(); |
3298 | int components_count = 0; |
3299 | unsigned int calculate_attr_size = 0; |
3300 | if (record_attribute_start != NULL__null) { |
3301 | cfs->set_current(record_attribute_start); |
3302 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // num of components |
3303 | components_count = (int)cfs->get_u2_fast(); |
3304 | calculate_attr_size = 2; |
3305 | } |
3306 | |
3307 | Array<RecordComponent*>* const record_components = |
3308 | MetadataFactory::new_array<RecordComponent*>(_loader_data, components_count, NULL__null, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3309 | _record_components = record_components; |
3310 | |
3311 | for (int x = 0; x < components_count; x++) { |
3312 | cfs->guarantee_more(6, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // name_index, descriptor_index, attributes_count |
3313 | |
3314 | const u2 name_index = cfs->get_u2_fast(); |
3315 | check_property(valid_symbol_at(name_index), |
3316 | "Invalid constant pool index %u for name in Record attribute in class file %s", |
3317 | name_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3318 | const Symbol* const name = cp->symbol_at(name_index); |
3319 | verify_legal_field_name(name, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3320 | |
3321 | const u2 descriptor_index = cfs->get_u2_fast(); |
3322 | check_property(valid_symbol_at(descriptor_index), |
3323 | "Invalid constant pool index %u for descriptor in Record attribute in class file %s", |
3324 | descriptor_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3325 | const Symbol* const descr = cp->symbol_at(descriptor_index); |
3326 | verify_legal_field_signature(name, descr, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3327 | |
3328 | const u2 attributes_count = cfs->get_u2_fast(); |
3329 | calculate_attr_size += 6; |
3330 | u2 generic_sig_index = 0; |
3331 | const u1* runtime_visible_annotations = NULL__null; |
3332 | int runtime_visible_annotations_length = 0; |
3333 | const u1* runtime_invisible_annotations = NULL__null; |
3334 | int runtime_invisible_annotations_length = 0; |
3335 | bool runtime_invisible_annotations_exists = false; |
3336 | const u1* runtime_visible_type_annotations = NULL__null; |
3337 | int runtime_visible_type_annotations_length = 0; |
3338 | const u1* runtime_invisible_type_annotations = NULL__null; |
3339 | int runtime_invisible_type_annotations_length = 0; |
3340 | bool runtime_invisible_type_annotations_exists = false; |
3341 | |
3342 | // Expected attributes for record components are Signature, Runtime(In)VisibleAnnotations, |
3343 | // and Runtime(In)VisibleTypeAnnotations. Other attributes are ignored. |
3344 | for (int y = 0; y < attributes_count; y++) { |
3345 | cfs->guarantee_more(6, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // attribute_name_index, attribute_length |
3346 | const u2 attribute_name_index = cfs->get_u2_fast(); |
3347 | const u4 attribute_length = cfs->get_u4_fast(); |
3348 | calculate_attr_size += 6; |
3349 | check_property( |
3350 | valid_symbol_at(attribute_name_index), |
3351 | "Invalid Record attribute name index %u in class file %s", |
3352 | attribute_name_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3353 | |
3354 | const Symbol* const attribute_name = cp->symbol_at(attribute_name_index); |
3355 | if (attribute_name == vmSymbols::tag_signature()) { |
3356 | if (generic_sig_index != 0) { |
3357 | classfile_parse_error( |
3358 | "Multiple Signature attributes for Record component in class file %s", |
3359 | THREAD__the_thread__); |
3360 | return 0; |
3361 | } |
3362 | if (attribute_length != 2) { |
3363 | classfile_parse_error( |
3364 | "Invalid Signature attribute length %u in Record component in class file %s", |
3365 | attribute_length, THREAD__the_thread__); |
3366 | return 0; |
3367 | } |
3368 | generic_sig_index = parse_generic_signature_attribute(cfs, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3369 | |
3370 | } else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) { |
3371 | if (runtime_visible_annotations != NULL__null) { |
3372 | classfile_parse_error( |
3373 | "Multiple RuntimeVisibleAnnotations attributes for Record component in class file %s", THREAD__the_thread__); |
3374 | return 0; |
3375 | } |
3376 | runtime_visible_annotations_length = attribute_length; |
3377 | runtime_visible_annotations = cfs->current(); |
3378 | |
3379 | assert(runtime_visible_annotations != NULL, "null record component visible annotation")do { if (!(runtime_visible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3379, "assert(" "runtime_visible_annotations != __null" ") failed" , "null record component visible annotation"); ::breakpoint() ; } } while (0); |
3380 | cfs->guarantee_more(runtime_visible_annotations_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3381 | cfs->skip_u1_fast(runtime_visible_annotations_length); |
3382 | |
3383 | } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { |
3384 | if (runtime_invisible_annotations_exists) { |
3385 | classfile_parse_error( |
3386 | "Multiple RuntimeInvisibleAnnotations attributes for Record component in class file %s", THREAD__the_thread__); |
3387 | return 0; |
3388 | } |
3389 | runtime_invisible_annotations_exists = true; |
3390 | if (PreserveAllAnnotations) { |
3391 | runtime_invisible_annotations_length = attribute_length; |
3392 | runtime_invisible_annotations = cfs->current(); |
3393 | assert(runtime_invisible_annotations != NULL, "null record component invisible annotation")do { if (!(runtime_invisible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3393, "assert(" "runtime_invisible_annotations != __null" ") failed" , "null record component invisible annotation"); ::breakpoint (); } } while (0); |
3394 | } |
3395 | cfs->skip_u1(attribute_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3396 | |
3397 | } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { |
3398 | if (runtime_visible_type_annotations != NULL__null) { |
3399 | classfile_parse_error( |
3400 | "Multiple RuntimeVisibleTypeAnnotations attributes for Record component in class file %s", THREAD__the_thread__); |
3401 | return 0; |
3402 | } |
3403 | runtime_visible_type_annotations_length = attribute_length; |
3404 | runtime_visible_type_annotations = cfs->current(); |
3405 | |
3406 | assert(runtime_visible_type_annotations != NULL, "null record component visible type annotation")do { if (!(runtime_visible_type_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3406, "assert(" "runtime_visible_type_annotations != __null" ") failed", "null record component visible type annotation") ; ::breakpoint(); } } while (0); |
3407 | cfs->guarantee_more(runtime_visible_type_annotations_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3408 | cfs->skip_u1_fast(runtime_visible_type_annotations_length); |
3409 | |
3410 | } else if (attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { |
3411 | if (runtime_invisible_type_annotations_exists) { |
3412 | classfile_parse_error( |
3413 | "Multiple RuntimeInvisibleTypeAnnotations attributes for Record component in class file %s", THREAD__the_thread__); |
3414 | return 0; |
3415 | } |
3416 | runtime_invisible_type_annotations_exists = true; |
3417 | if (PreserveAllAnnotations) { |
3418 | runtime_invisible_type_annotations_length = attribute_length; |
3419 | runtime_invisible_type_annotations = cfs->current(); |
3420 | assert(runtime_invisible_type_annotations != NULL, "null record component invisible type annotation")do { if (!(runtime_invisible_type_annotations != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3420, "assert(" "runtime_invisible_type_annotations != __null" ") failed", "null record component invisible type annotation" ); ::breakpoint(); } } while (0); |
3421 | } |
3422 | cfs->skip_u1(attribute_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3423 | |
3424 | } else { |
3425 | // Skip unknown attributes |
3426 | cfs->skip_u1(attribute_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3427 | } |
3428 | calculate_attr_size += attribute_length; |
3429 | } // End of attributes For loop |
3430 | |
3431 | AnnotationArray* annotations = assemble_annotations(runtime_visible_annotations, |
3432 | runtime_visible_annotations_length, |
3433 | runtime_invisible_annotations, |
3434 | runtime_invisible_annotations_length, |
3435 | CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3436 | AnnotationArray* type_annotations = assemble_annotations(runtime_visible_type_annotations, |
3437 | runtime_visible_type_annotations_length, |
3438 | runtime_invisible_type_annotations, |
3439 | runtime_invisible_type_annotations_length, |
3440 | CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3441 | |
3442 | RecordComponent* record_component = |
3443 | RecordComponent::allocate(_loader_data, name_index, descriptor_index, |
3444 | attributes_count, generic_sig_index, |
3445 | annotations, type_annotations, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
3446 | record_components->at_put(x, record_component); |
3447 | } // End of component processing loop |
3448 | |
3449 | // Restore buffer's current position. |
3450 | cfs->set_current(current_mark); |
3451 | return calculate_attr_size; |
3452 | } |
3453 | |
3454 | void ClassFileParser::parse_classfile_synthetic_attribute() { |
3455 | set_class_synthetic_flag(true); |
3456 | } |
3457 | |
3458 | void ClassFileParser::parse_classfile_signature_attribute(const ClassFileStream* const cfs, TRAPSJavaThread* __the_thread__) { |
3459 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3459, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
3460 | |
3461 | const u2 signature_index = cfs->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3462 | check_property( |
3463 | valid_symbol_at(signature_index), |
3464 | "Invalid constant pool index %u in Signature attribute in class file %s", |
3465 | signature_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3466 | set_class_generic_signature_index(signature_index); |
3467 | } |
3468 | |
3469 | void ClassFileParser::parse_classfile_bootstrap_methods_attribute(const ClassFileStream* const cfs, |
3470 | ConstantPool* cp, |
3471 | u4 attribute_byte_length, |
3472 | TRAPSJavaThread* __the_thread__) { |
3473 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3473, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
3474 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3474, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
3475 | |
3476 | const u1* const current_start = cfs->current(); |
3477 | |
3478 | guarantee_property(attribute_byte_length >= sizeof(u2), |
3479 | "Invalid BootstrapMethods attribute length %u in class file %s", |
3480 | attribute_byte_length, |
3481 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3482 | |
3483 | cfs->guarantee_more(attribute_byte_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3484 | |
3485 | const int attribute_array_length = cfs->get_u2_fast(); |
3486 | |
3487 | guarantee_property(_max_bootstrap_specifier_index < attribute_array_length, |
3488 | "Short length on BootstrapMethods in class file %s", |
3489 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3490 | |
3491 | |
3492 | // The attribute contains a counted array of counted tuples of shorts, |
3493 | // represending bootstrap specifiers: |
3494 | // length*{bootstrap_method_index, argument_count*{argument_index}} |
3495 | const int operand_count = (attribute_byte_length - sizeof(u2)) / sizeof(u2); |
3496 | // operand_count = number of shorts in attr, except for leading length |
3497 | |
3498 | // The attribute is copied into a short[] array. |
3499 | // The array begins with a series of short[2] pairs, one for each tuple. |
3500 | const int index_size = (attribute_array_length * 2); |
3501 | |
3502 | Array<u2>* const operands = |
3503 | MetadataFactory::new_array<u2>(_loader_data, index_size + operand_count, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3504 | |
3505 | // Eagerly assign operands so they will be deallocated with the constant |
3506 | // pool if there is an error. |
3507 | cp->set_operands(operands); |
3508 | |
3509 | int operand_fill_index = index_size; |
3510 | const int cp_size = cp->length(); |
3511 | |
3512 | for (int n = 0; n < attribute_array_length; n++) { |
3513 | // Store a 32-bit offset into the header of the operand array. |
3514 | ConstantPool::operand_offset_at_put(operands, n, operand_fill_index); |
3515 | |
3516 | // Read a bootstrap specifier. |
3517 | cfs->guarantee_more(sizeof(u2) * 2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bsm, argc |
3518 | const u2 bootstrap_method_index = cfs->get_u2_fast(); |
3519 | const u2 argument_count = cfs->get_u2_fast(); |
3520 | check_property( |
3521 | valid_cp_range(bootstrap_method_index, cp_size) && |
3522 | cp->tag_at(bootstrap_method_index).is_method_handle(), |
3523 | "bootstrap_method_index %u has bad constant type in class file %s", |
3524 | bootstrap_method_index, |
3525 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3526 | |
3527 | guarantee_property((operand_fill_index + 1 + argument_count) < operands->length(), |
3528 | "Invalid BootstrapMethods num_bootstrap_methods or num_bootstrap_arguments value in class file %s", |
3529 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3530 | |
3531 | operands->at_put(operand_fill_index++, bootstrap_method_index); |
3532 | operands->at_put(operand_fill_index++, argument_count); |
3533 | |
3534 | cfs->guarantee_more(sizeof(u2) * argument_count, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // argv[argc] |
3535 | for (int j = 0; j < argument_count; j++) { |
3536 | const u2 argument_index = cfs->get_u2_fast(); |
3537 | check_property( |
3538 | valid_cp_range(argument_index, cp_size) && |
3539 | cp->tag_at(argument_index).is_loadable_constant(), |
3540 | "argument_index %u has bad constant type in class file %s", |
3541 | argument_index, |
3542 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3543 | operands->at_put(operand_fill_index++, argument_index); |
3544 | } |
3545 | } |
3546 | guarantee_property(current_start + attribute_byte_length == cfs->current(), |
3547 | "Bad length on BootstrapMethods in class file %s", |
3548 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3549 | } |
3550 | |
3551 | void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cfs, |
3552 | ConstantPool* cp, |
3553 | ClassFileParser::ClassAnnotationCollector* parsed_annotations, |
3554 | TRAPSJavaThread* __the_thread__) { |
3555 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3555, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
3556 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3556, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
3557 | assert(parsed_annotations != NULL, "invariant")do { if (!(parsed_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3557, "assert(" "parsed_annotations != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
3558 | |
3559 | // Set inner classes attribute to default sentinel |
3560 | _inner_classes = Universe::the_empty_short_array(); |
3561 | // Set nest members attribute to default sentinel |
3562 | _nest_members = Universe::the_empty_short_array(); |
3563 | // Set _permitted_subclasses attribute to default sentinel |
3564 | _permitted_subclasses = Universe::the_empty_short_array(); |
3565 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // attributes_count |
3566 | u2 attributes_count = cfs->get_u2_fast(); |
3567 | bool parsed_sourcefile_attribute = false; |
3568 | bool parsed_innerclasses_attribute = false; |
3569 | bool parsed_nest_members_attribute = false; |
3570 | bool parsed_permitted_subclasses_attribute = false; |
3571 | bool parsed_nest_host_attribute = false; |
3572 | bool parsed_record_attribute = false; |
3573 | bool parsed_enclosingmethod_attribute = false; |
3574 | bool parsed_bootstrap_methods_attribute = false; |
3575 | const u1* runtime_visible_annotations = NULL__null; |
3576 | int runtime_visible_annotations_length = 0; |
3577 | const u1* runtime_invisible_annotations = NULL__null; |
3578 | int runtime_invisible_annotations_length = 0; |
3579 | const u1* runtime_visible_type_annotations = NULL__null; |
3580 | int runtime_visible_type_annotations_length = 0; |
3581 | const u1* runtime_invisible_type_annotations = NULL__null; |
3582 | int runtime_invisible_type_annotations_length = 0; |
3583 | bool runtime_invisible_type_annotations_exists = false; |
3584 | bool runtime_invisible_annotations_exists = false; |
3585 | bool parsed_source_debug_ext_annotations_exist = false; |
3586 | const u1* inner_classes_attribute_start = NULL__null; |
3587 | u4 inner_classes_attribute_length = 0; |
3588 | u2 enclosing_method_class_index = 0; |
3589 | u2 enclosing_method_method_index = 0; |
3590 | const u1* nest_members_attribute_start = NULL__null; |
3591 | u4 nest_members_attribute_length = 0; |
3592 | const u1* record_attribute_start = NULL__null; |
3593 | u4 record_attribute_length = 0; |
3594 | const u1* permitted_subclasses_attribute_start = NULL__null; |
3595 | u4 permitted_subclasses_attribute_length = 0; |
3596 | |
3597 | // Iterate over attributes |
3598 | while (attributes_count--) { |
3599 | cfs->guarantee_more(6, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // attribute_name_index, attribute_length |
3600 | const u2 attribute_name_index = cfs->get_u2_fast(); |
3601 | const u4 attribute_length = cfs->get_u4_fast(); |
3602 | check_property( |
3603 | valid_symbol_at(attribute_name_index), |
3604 | "Attribute name has bad constant pool index %u in class file %s", |
3605 | attribute_name_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3606 | const Symbol* const tag = cp->symbol_at(attribute_name_index); |
3607 | if (tag == vmSymbols::tag_source_file()) { |
3608 | // Check for SourceFile tag |
3609 | if (_need_verify) { |
3610 | guarantee_property(attribute_length == 2, "Wrong SourceFile attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3611 | } |
3612 | if (parsed_sourcefile_attribute) { |
3613 | classfile_parse_error("Multiple SourceFile attributes in class file %s", THREAD__the_thread__); |
3614 | return; |
3615 | } else { |
3616 | parsed_sourcefile_attribute = true; |
3617 | } |
3618 | parse_classfile_sourcefile_attribute(cfs, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3619 | } else if (tag == vmSymbols::tag_source_debug_extension()) { |
3620 | // Check for SourceDebugExtension tag |
3621 | if (parsed_source_debug_ext_annotations_exist) { |
3622 | classfile_parse_error( |
3623 | "Multiple SourceDebugExtension attributes in class file %s", THREAD__the_thread__); |
3624 | return; |
3625 | } |
3626 | parsed_source_debug_ext_annotations_exist = true; |
3627 | parse_classfile_source_debug_extension_attribute(cfs, (int)attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3628 | } else if (tag == vmSymbols::tag_inner_classes()) { |
3629 | // Check for InnerClasses tag |
3630 | if (parsed_innerclasses_attribute) { |
3631 | classfile_parse_error("Multiple InnerClasses attributes in class file %s", THREAD__the_thread__); |
3632 | return; |
3633 | } else { |
3634 | parsed_innerclasses_attribute = true; |
3635 | } |
3636 | inner_classes_attribute_start = cfs->current(); |
3637 | inner_classes_attribute_length = attribute_length; |
3638 | cfs->skip_u1(inner_classes_attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3639 | } else if (tag == vmSymbols::tag_synthetic()) { |
3640 | // Check for Synthetic tag |
3641 | // Shouldn't we check that the synthetic flags wasn't already set? - not required in spec |
3642 | if (attribute_length != 0) { |
3643 | classfile_parse_error( |
3644 | "Invalid Synthetic classfile attribute length %u in class file %s", |
3645 | attribute_length, THREAD__the_thread__); |
3646 | return; |
3647 | } |
3648 | parse_classfile_synthetic_attribute(); |
3649 | } else if (tag == vmSymbols::tag_deprecated()) { |
3650 | // Check for Deprecated tag - 4276120 |
3651 | if (attribute_length != 0) { |
3652 | classfile_parse_error( |
3653 | "Invalid Deprecated classfile attribute length %u in class file %s", |
3654 | attribute_length, THREAD__the_thread__); |
3655 | return; |
3656 | } |
3657 | } else if (_major_version >= JAVA_1_5_VERSION49) { |
3658 | if (tag == vmSymbols::tag_signature()) { |
3659 | if (_generic_signature_index != 0) { |
3660 | classfile_parse_error( |
3661 | "Multiple Signature attributes in class file %s", THREAD__the_thread__); |
3662 | return; |
3663 | } |
3664 | if (attribute_length != 2) { |
3665 | classfile_parse_error( |
3666 | "Wrong Signature attribute length %u in class file %s", |
3667 | attribute_length, THREAD__the_thread__); |
3668 | return; |
3669 | } |
3670 | parse_classfile_signature_attribute(cfs, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3671 | } else if (tag == vmSymbols::tag_runtime_visible_annotations()) { |
3672 | if (runtime_visible_annotations != NULL__null) { |
3673 | classfile_parse_error( |
3674 | "Multiple RuntimeVisibleAnnotations attributes in class file %s", THREAD__the_thread__); |
3675 | return; |
3676 | } |
3677 | runtime_visible_annotations_length = attribute_length; |
3678 | runtime_visible_annotations = cfs->current(); |
3679 | assert(runtime_visible_annotations != NULL, "null visible annotations")do { if (!(runtime_visible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3679, "assert(" "runtime_visible_annotations != __null" ") failed" , "null visible annotations"); ::breakpoint(); } } while (0); |
3680 | cfs->guarantee_more(runtime_visible_annotations_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3681 | parse_annotations(cp, |
3682 | runtime_visible_annotations, |
3683 | runtime_visible_annotations_length, |
3684 | parsed_annotations, |
3685 | _loader_data, |
3686 | _can_access_vm_annotations); |
3687 | cfs->skip_u1_fast(runtime_visible_annotations_length); |
3688 | } else if (tag == vmSymbols::tag_runtime_invisible_annotations()) { |
3689 | if (runtime_invisible_annotations_exists) { |
3690 | classfile_parse_error( |
3691 | "Multiple RuntimeInvisibleAnnotations attributes in class file %s", THREAD__the_thread__); |
3692 | return; |
3693 | } |
3694 | runtime_invisible_annotations_exists = true; |
3695 | if (PreserveAllAnnotations) { |
3696 | runtime_invisible_annotations_length = attribute_length; |
3697 | runtime_invisible_annotations = cfs->current(); |
3698 | assert(runtime_invisible_annotations != NULL, "null invisible annotations")do { if (!(runtime_invisible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3698, "assert(" "runtime_invisible_annotations != __null" ") failed" , "null invisible annotations"); ::breakpoint(); } } while (0 ); |
3699 | } |
3700 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3701 | } else if (tag == vmSymbols::tag_enclosing_method()) { |
3702 | if (parsed_enclosingmethod_attribute) { |
3703 | classfile_parse_error("Multiple EnclosingMethod attributes in class file %s", THREAD__the_thread__); |
3704 | return; |
3705 | } else { |
3706 | parsed_enclosingmethod_attribute = true; |
3707 | } |
3708 | guarantee_property(attribute_length == 4, |
3709 | "Wrong EnclosingMethod attribute length %u in class file %s", |
3710 | attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3711 | cfs->guarantee_more(4, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // class_index, method_index |
3712 | enclosing_method_class_index = cfs->get_u2_fast(); |
3713 | enclosing_method_method_index = cfs->get_u2_fast(); |
3714 | if (enclosing_method_class_index == 0) { |
3715 | classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", THREAD__the_thread__); |
3716 | return; |
3717 | } |
3718 | // Validate the constant pool indices and types |
3719 | check_property(valid_klass_reference_at(enclosing_method_class_index), |
3720 | "Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3721 | if (enclosing_method_method_index != 0 && |
3722 | (!cp->is_within_bounds(enclosing_method_method_index) || |
3723 | !cp->tag_at(enclosing_method_method_index).is_name_and_type())) { |
3724 | classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", THREAD__the_thread__); |
3725 | return; |
3726 | } |
3727 | } else if (tag == vmSymbols::tag_bootstrap_methods() && |
3728 | _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { |
3729 | if (parsed_bootstrap_methods_attribute) { |
3730 | classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", THREAD__the_thread__); |
3731 | return; |
3732 | } |
3733 | parsed_bootstrap_methods_attribute = true; |
3734 | parse_classfile_bootstrap_methods_attribute(cfs, cp, attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3735 | } else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) { |
3736 | if (runtime_visible_type_annotations != NULL__null) { |
3737 | classfile_parse_error( |
3738 | "Multiple RuntimeVisibleTypeAnnotations attributes in class file %s", THREAD__the_thread__); |
3739 | return; |
3740 | } |
3741 | runtime_visible_type_annotations_length = attribute_length; |
3742 | runtime_visible_type_annotations = cfs->current(); |
3743 | assert(runtime_visible_type_annotations != NULL, "null visible type annotations")do { if (!(runtime_visible_type_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3743, "assert(" "runtime_visible_type_annotations != __null" ") failed", "null visible type annotations"); ::breakpoint() ; } } while (0); |
3744 | // No need for the VM to parse Type annotations |
3745 | cfs->skip_u1(runtime_visible_type_annotations_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3746 | } else if (tag == vmSymbols::tag_runtime_invisible_type_annotations()) { |
3747 | if (runtime_invisible_type_annotations_exists) { |
3748 | classfile_parse_error( |
3749 | "Multiple RuntimeInvisibleTypeAnnotations attributes in class file %s", THREAD__the_thread__); |
3750 | return; |
3751 | } else { |
3752 | runtime_invisible_type_annotations_exists = true; |
3753 | } |
3754 | if (PreserveAllAnnotations) { |
3755 | runtime_invisible_type_annotations_length = attribute_length; |
3756 | runtime_invisible_type_annotations = cfs->current(); |
3757 | assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations")do { if (!(runtime_invisible_type_annotations != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3757, "assert(" "runtime_invisible_type_annotations != __null" ") failed", "null invisible type annotations"); ::breakpoint (); } } while (0); |
3758 | } |
3759 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3760 | } else if (_major_version >= JAVA_11_VERSION55) { |
3761 | if (tag == vmSymbols::tag_nest_members()) { |
3762 | // Check for NestMembers tag |
3763 | if (parsed_nest_members_attribute) { |
3764 | classfile_parse_error("Multiple NestMembers attributes in class file %s", THREAD__the_thread__); |
3765 | return; |
3766 | } else { |
3767 | parsed_nest_members_attribute = true; |
3768 | } |
3769 | if (parsed_nest_host_attribute) { |
3770 | classfile_parse_error("Conflicting NestHost and NestMembers attributes in class file %s", THREAD__the_thread__); |
3771 | return; |
3772 | } |
3773 | nest_members_attribute_start = cfs->current(); |
3774 | nest_members_attribute_length = attribute_length; |
3775 | cfs->skip_u1(nest_members_attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3776 | } else if (tag == vmSymbols::tag_nest_host()) { |
3777 | if (parsed_nest_host_attribute) { |
3778 | classfile_parse_error("Multiple NestHost attributes in class file %s", THREAD__the_thread__); |
3779 | return; |
3780 | } else { |
3781 | parsed_nest_host_attribute = true; |
3782 | } |
3783 | if (parsed_nest_members_attribute) { |
3784 | classfile_parse_error("Conflicting NestMembers and NestHost attributes in class file %s", THREAD__the_thread__); |
3785 | return; |
3786 | } |
3787 | if (_need_verify) { |
3788 | guarantee_property(attribute_length == 2, "Wrong NestHost attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3789 | } |
3790 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3791 | u2 class_info_index = cfs->get_u2_fast(); |
3792 | check_property( |
3793 | valid_klass_reference_at(class_info_index), |
3794 | "Nest-host class_info_index %u has bad constant type in class file %s", |
3795 | class_info_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3796 | _nest_host = class_info_index; |
3797 | |
3798 | } else if (_major_version >= JAVA_16_VERSION60) { |
3799 | if (tag == vmSymbols::tag_record()) { |
3800 | if (parsed_record_attribute) { |
3801 | classfile_parse_error("Multiple Record attributes in class file %s", THREAD__the_thread__); |
3802 | return; |
3803 | } |
3804 | parsed_record_attribute = true; |
3805 | record_attribute_start = cfs->current(); |
3806 | record_attribute_length = attribute_length; |
3807 | } else if (_major_version >= JAVA_17_VERSION61) { |
3808 | if (tag == vmSymbols::tag_permitted_subclasses()) { |
3809 | if (parsed_permitted_subclasses_attribute) { |
3810 | classfile_parse_error("Multiple PermittedSubclasses attributes in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3811 | return; |
3812 | } |
3813 | // Classes marked ACC_FINAL cannot have a PermittedSubclasses attribute. |
3814 | if (_access_flags.is_final()) { |
3815 | classfile_parse_error("PermittedSubclasses attribute in final class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3816 | return; |
3817 | } |
3818 | parsed_permitted_subclasses_attribute = true; |
3819 | permitted_subclasses_attribute_start = cfs->current(); |
3820 | permitted_subclasses_attribute_length = attribute_length; |
3821 | } |
3822 | } |
3823 | // Skip attribute_length for any attribute where major_verson >= JAVA_17_VERSION |
3824 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3825 | } else { |
3826 | // Unknown attribute |
3827 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3828 | } |
3829 | } else { |
3830 | // Unknown attribute |
3831 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3832 | } |
3833 | } else { |
3834 | // Unknown attribute |
3835 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3836 | } |
3837 | } |
3838 | _class_annotations = assemble_annotations(runtime_visible_annotations, |
3839 | runtime_visible_annotations_length, |
3840 | runtime_invisible_annotations, |
3841 | runtime_invisible_annotations_length, |
3842 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3843 | _class_type_annotations = assemble_annotations(runtime_visible_type_annotations, |
3844 | runtime_visible_type_annotations_length, |
3845 | runtime_invisible_type_annotations, |
3846 | runtime_invisible_type_annotations_length, |
3847 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3848 | |
3849 | if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) { |
3850 | const u2 num_of_classes = parse_classfile_inner_classes_attribute( |
3851 | cfs, |
3852 | cp, |
3853 | inner_classes_attribute_start, |
3854 | parsed_innerclasses_attribute, |
3855 | enclosing_method_class_index, |
3856 | enclosing_method_method_index, |
3857 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3858 | if (parsed_innerclasses_attribute && _need_verify && _major_version >= JAVA_1_5_VERSION49) { |
3859 | guarantee_property( |
3860 | inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, |
3861 | "Wrong InnerClasses attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3862 | } |
3863 | } |
3864 | |
3865 | if (parsed_nest_members_attribute) { |
3866 | const u2 num_of_classes = parse_classfile_nest_members_attribute( |
3867 | cfs, |
3868 | nest_members_attribute_start, |
3869 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3870 | if (_need_verify) { |
3871 | guarantee_property( |
3872 | nest_members_attribute_length == sizeof(num_of_classes) + sizeof(u2) * num_of_classes, |
3873 | "Wrong NestMembers attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3874 | } |
3875 | } |
3876 | |
3877 | if (parsed_record_attribute) { |
3878 | const unsigned int calculated_attr_length = parse_classfile_record_attribute( |
3879 | cfs, |
3880 | cp, |
3881 | record_attribute_start, |
3882 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3883 | if (_need_verify) { |
3884 | guarantee_property(record_attribute_length == calculated_attr_length, |
3885 | "Record attribute has wrong length in class file %s", |
3886 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3887 | } |
3888 | } |
3889 | |
3890 | if (parsed_permitted_subclasses_attribute) { |
3891 | const u2 num_subclasses = parse_classfile_permitted_subclasses_attribute( |
3892 | cfs, |
3893 | permitted_subclasses_attribute_start, |
3894 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3895 | if (_need_verify) { |
3896 | guarantee_property( |
3897 | permitted_subclasses_attribute_length == sizeof(num_subclasses) + sizeof(u2) * num_subclasses, |
3898 | "Wrong PermittedSubclasses attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3899 | } |
3900 | } |
3901 | |
3902 | if (_max_bootstrap_specifier_index >= 0) { |
3903 | guarantee_property(parsed_bootstrap_methods_attribute, |
3904 | "Missing BootstrapMethods attribute in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3905 | } |
3906 | } |
3907 | |
3908 | void ClassFileParser::apply_parsed_class_attributes(InstanceKlass* k) { |
3909 | assert(k != NULL, "invariant")do { if (!(k != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3909, "assert(" "k != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); |
3910 | |
3911 | if (_synthetic_flag) |
3912 | k->set_is_synthetic(); |
3913 | if (_sourcefile_index != 0) { |
3914 | k->set_source_file_name_index(_sourcefile_index); |
3915 | } |
3916 | if (_generic_signature_index != 0) { |
3917 | k->set_generic_signature_index(_generic_signature_index); |
3918 | } |
3919 | if (_sde_buffer != NULL__null) { |
3920 | k->set_source_debug_extension(_sde_buffer, _sde_length); |
3921 | } |
3922 | } |
3923 | |
3924 | // Create the Annotations object that will |
3925 | // hold the annotations array for the Klass. |
3926 | void ClassFileParser::create_combined_annotations(TRAPSJavaThread* __the_thread__) { |
3927 | if (_class_annotations == NULL__null && |
3928 | _class_type_annotations == NULL__null && |
3929 | _fields_annotations == NULL__null && |
3930 | _fields_type_annotations == NULL__null) { |
3931 | // Don't create the Annotations object unnecessarily. |
3932 | return; |
3933 | } |
3934 | |
3935 | Annotations* const annotations = Annotations::allocate(_loader_data, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
3936 | annotations->set_class_annotations(_class_annotations); |
3937 | annotations->set_class_type_annotations(_class_type_annotations); |
3938 | annotations->set_fields_annotations(_fields_annotations); |
3939 | annotations->set_fields_type_annotations(_fields_type_annotations); |
3940 | |
3941 | // This is the Annotations object that will be |
3942 | // assigned to InstanceKlass being constructed. |
3943 | _combined_annotations = annotations; |
3944 | |
3945 | // The annotations arrays below has been transfered the |
3946 | // _combined_annotations so these fields can now be cleared. |
3947 | _class_annotations = NULL__null; |
3948 | _class_type_annotations = NULL__null; |
3949 | _fields_annotations = NULL__null; |
3950 | _fields_type_annotations = NULL__null; |
3951 | } |
3952 | |
3953 | // Transfer ownership of metadata allocated to the InstanceKlass. |
3954 | void ClassFileParser::apply_parsed_class_metadata( |
3955 | InstanceKlass* this_klass, |
3956 | int java_fields_count) { |
3957 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3957, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
3958 | |
3959 | _cp->set_pool_holder(this_klass); |
3960 | this_klass->set_constants(_cp); |
3961 | this_klass->set_fields(_fields, java_fields_count); |
3962 | this_klass->set_methods(_methods); |
3963 | this_klass->set_inner_classes(_inner_classes); |
3964 | this_klass->set_nest_members(_nest_members); |
3965 | this_klass->set_nest_host_index(_nest_host); |
3966 | this_klass->set_annotations(_combined_annotations); |
3967 | this_klass->set_permitted_subclasses(_permitted_subclasses); |
3968 | this_klass->set_record_components(_record_components); |
3969 | // Delay the setting of _local_interfaces and _transitive_interfaces until after |
3970 | // initialize_supers() in fill_instance_klass(). It is because the _local_interfaces could |
3971 | // be shared with _transitive_interfaces and _transitive_interfaces may be shared with |
3972 | // its _super. If an OOM occurs while loading the current klass, its _super field |
3973 | // may not have been set. When GC tries to free the klass, the _transitive_interfaces |
3974 | // may be deallocated mistakenly in InstanceKlass::deallocate_interfaces(). Subsequent |
3975 | // dereferences to the deallocated _transitive_interfaces will result in a crash. |
3976 | |
3977 | // Clear out these fields so they don't get deallocated by the destructor |
3978 | clear_class_metadata(); |
3979 | } |
3980 | |
3981 | AnnotationArray* ClassFileParser::assemble_annotations(const u1* const runtime_visible_annotations, |
3982 | int runtime_visible_annotations_length, |
3983 | const u1* const runtime_invisible_annotations, |
3984 | int runtime_invisible_annotations_length, |
3985 | TRAPSJavaThread* __the_thread__) { |
3986 | AnnotationArray* annotations = NULL__null; |
3987 | if (runtime_visible_annotations != NULL__null || |
3988 | runtime_invisible_annotations != NULL__null) { |
3989 | annotations = MetadataFactory::new_array<u1>(_loader_data, |
3990 | runtime_visible_annotations_length + |
3991 | runtime_invisible_annotations_length, |
3992 | CHECK_(annotations)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return annotations; (void)(0); |
3993 | if (runtime_visible_annotations != NULL__null) { |
3994 | for (int i = 0; i < runtime_visible_annotations_length; i++) { |
3995 | annotations->at_put(i, runtime_visible_annotations[i]); |
3996 | } |
3997 | } |
3998 | if (runtime_invisible_annotations != NULL__null) { |
3999 | for (int i = 0; i < runtime_invisible_annotations_length; i++) { |
4000 | int append = runtime_visible_annotations_length+i; |
4001 | annotations->at_put(append, runtime_invisible_annotations[i]); |
4002 | } |
4003 | } |
4004 | } |
4005 | return annotations; |
4006 | } |
4007 | |
4008 | const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp, |
4009 | const int super_class_index, |
4010 | const bool need_verify, |
4011 | TRAPSJavaThread* __the_thread__) { |
4012 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4012, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
4013 | const InstanceKlass* super_klass = NULL__null; |
4014 | |
4015 | if (super_class_index == 0) { |
4016 | check_property(_class_name == vmSymbols::java_lang_Object(), |
4017 | "Invalid superclass index %u in class file %s", |
4018 | super_class_index, |
4019 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
4020 | } else { |
4021 | check_property(valid_klass_reference_at(super_class_index), |
4022 | "Invalid superclass index %u in class file %s", |
4023 | super_class_index, |
4024 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
4025 | // The class name should be legal because it is checked when parsing constant pool. |
4026 | // However, make sure it is not an array type. |
4027 | bool is_array = false; |
4028 | if (cp->tag_at(super_class_index).is_klass()) { |
4029 | super_klass = InstanceKlass::cast(cp->resolved_klass_at(super_class_index)); |
4030 | if (need_verify) |
4031 | is_array = super_klass->is_array_klass(); |
4032 | } else if (need_verify) { |
4033 | is_array = (cp->klass_name_at(super_class_index)->char_at(0) == JVM_SIGNATURE_ARRAY); |
4034 | } |
4035 | if (need_verify) { |
4036 | guarantee_property(!is_array, |
4037 | "Bad superclass name in class file %s", CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
4038 | } |
4039 | } |
4040 | return super_klass; |
4041 | } |
4042 | |
4043 | OopMapBlocksBuilder::OopMapBlocksBuilder(unsigned int max_blocks) { |
4044 | _max_nonstatic_oop_maps = max_blocks; |
4045 | _nonstatic_oop_map_count = 0; |
4046 | if (max_blocks == 0) { |
4047 | _nonstatic_oop_maps = NULL__null; |
4048 | } else { |
4049 | _nonstatic_oop_maps = |
4050 | NEW_RESOURCE_ARRAY(OopMapBlock, _max_nonstatic_oop_maps)(OopMapBlock*) resource_allocate_bytes((_max_nonstatic_oop_maps ) * sizeof(OopMapBlock)); |
4051 | memset(_nonstatic_oop_maps, 0, sizeof(OopMapBlock) * max_blocks); |
4052 | } |
4053 | } |
4054 | |
4055 | OopMapBlock* OopMapBlocksBuilder::last_oop_map() const { |
4056 | assert(_nonstatic_oop_map_count > 0, "Has no oop maps")do { if (!(_nonstatic_oop_map_count > 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4056, "assert(" "_nonstatic_oop_map_count > 0" ") failed" , "Has no oop maps"); ::breakpoint(); } } while (0); |
4057 | return _nonstatic_oop_maps + (_nonstatic_oop_map_count - 1); |
4058 | } |
4059 | |
4060 | // addition of super oop maps |
4061 | void OopMapBlocksBuilder::initialize_inherited_blocks(OopMapBlock* blocks, unsigned int nof_blocks) { |
4062 | assert(nof_blocks && _nonstatic_oop_map_count == 0 &&do { if (!(nof_blocks && _nonstatic_oop_map_count == 0 && nof_blocks <= _max_nonstatic_oop_maps)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4063, "assert(" "nof_blocks && _nonstatic_oop_map_count == 0 && nof_blocks <= _max_nonstatic_oop_maps" ") failed", "invariant"); ::breakpoint(); } } while (0) |
4063 | nof_blocks <= _max_nonstatic_oop_maps, "invariant")do { if (!(nof_blocks && _nonstatic_oop_map_count == 0 && nof_blocks <= _max_nonstatic_oop_maps)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4063, "assert(" "nof_blocks && _nonstatic_oop_map_count == 0 && nof_blocks <= _max_nonstatic_oop_maps" ") failed", "invariant"); ::breakpoint(); } } while (0); |
4064 | |
4065 | memcpy(_nonstatic_oop_maps, blocks, sizeof(OopMapBlock) * nof_blocks); |
4066 | _nonstatic_oop_map_count += nof_blocks; |
4067 | } |
4068 | |
4069 | // collection of oops |
4070 | void OopMapBlocksBuilder::add(int offset, int count) { |
4071 | if (_nonstatic_oop_map_count == 0) { |
4072 | _nonstatic_oop_map_count++; |
4073 | } |
4074 | OopMapBlock* nonstatic_oop_map = last_oop_map(); |
4075 | if (nonstatic_oop_map->count() == 0) { // Unused map, set it up |
4076 | nonstatic_oop_map->set_offset(offset); |
4077 | nonstatic_oop_map->set_count(count); |
4078 | } else if (nonstatic_oop_map->is_contiguous(offset)) { // contiguous, add |
4079 | nonstatic_oop_map->increment_count(count); |
4080 | } else { // Need a new one... |
4081 | _nonstatic_oop_map_count++; |
4082 | assert(_nonstatic_oop_map_count <= _max_nonstatic_oop_maps, "range check")do { if (!(_nonstatic_oop_map_count <= _max_nonstatic_oop_maps )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4082, "assert(" "_nonstatic_oop_map_count <= _max_nonstatic_oop_maps" ") failed", "range check"); ::breakpoint(); } } while (0); |
4083 | nonstatic_oop_map = last_oop_map(); |
4084 | nonstatic_oop_map->set_offset(offset); |
4085 | nonstatic_oop_map->set_count(count); |
4086 | } |
4087 | } |
4088 | |
4089 | // general purpose copy, e.g. into allocated instanceKlass |
4090 | void OopMapBlocksBuilder::copy(OopMapBlock* dst) { |
4091 | if (_nonstatic_oop_map_count != 0) { |
4092 | memcpy(dst, _nonstatic_oop_maps, sizeof(OopMapBlock) * _nonstatic_oop_map_count); |
4093 | } |
4094 | } |
4095 | |
4096 | // Sort and compact adjacent blocks |
4097 | void OopMapBlocksBuilder::compact() { |
4098 | if (_nonstatic_oop_map_count <= 1) { |
4099 | return; |
4100 | } |
4101 | /* |
4102 | * Since field layout sneeks in oops before values, we will be able to condense |
4103 | * blocks. There is potential to compact between super, own refs and values |
4104 | * containing refs. |
4105 | * |
4106 | * Currently compaction is slightly limited due to values being 8 byte aligned. |
4107 | * This may well change: FixMe if it doesn't, the code below is fairly general purpose |
4108 | * and maybe it doesn't need to be. |
4109 | */ |
4110 | qsort(_nonstatic_oop_maps, _nonstatic_oop_map_count, sizeof(OopMapBlock), |
4111 | (_sort_Fn)OopMapBlock::compare_offset); |
4112 | if (_nonstatic_oop_map_count < 2) { |
4113 | return; |
4114 | } |
4115 | |
4116 | // Make a temp copy, and iterate through and copy back into the original |
4117 | ResourceMark rm; |
4118 | OopMapBlock* oop_maps_copy = |
4119 | NEW_RESOURCE_ARRAY(OopMapBlock, _nonstatic_oop_map_count)(OopMapBlock*) resource_allocate_bytes((_nonstatic_oop_map_count ) * sizeof(OopMapBlock)); |
4120 | OopMapBlock* oop_maps_copy_end = oop_maps_copy + _nonstatic_oop_map_count; |
4121 | copy(oop_maps_copy); |
4122 | OopMapBlock* nonstatic_oop_map = _nonstatic_oop_maps; |
4123 | unsigned int new_count = 1; |
4124 | oop_maps_copy++; |
4125 | while(oop_maps_copy < oop_maps_copy_end) { |
4126 | assert(nonstatic_oop_map->offset() < oop_maps_copy->offset(), "invariant")do { if (!(nonstatic_oop_map->offset() < oop_maps_copy-> offset())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4126, "assert(" "nonstatic_oop_map->offset() < oop_maps_copy->offset()" ") failed", "invariant"); ::breakpoint(); } } while (0); |
4127 | if (nonstatic_oop_map->is_contiguous(oop_maps_copy->offset())) { |
4128 | nonstatic_oop_map->increment_count(oop_maps_copy->count()); |
4129 | } else { |
4130 | nonstatic_oop_map++; |
4131 | new_count++; |
4132 | nonstatic_oop_map->set_offset(oop_maps_copy->offset()); |
4133 | nonstatic_oop_map->set_count(oop_maps_copy->count()); |
4134 | } |
4135 | oop_maps_copy++; |
4136 | } |
4137 | assert(new_count <= _nonstatic_oop_map_count, "end up with more maps after compact() ?")do { if (!(new_count <= _nonstatic_oop_map_count)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4137, "assert(" "new_count <= _nonstatic_oop_map_count" ") failed" , "end up with more maps after compact() ?"); ::breakpoint(); } } while (0); |
4138 | _nonstatic_oop_map_count = new_count; |
4139 | } |
4140 | |
4141 | void OopMapBlocksBuilder::print_on(outputStream* st) const { |
4142 | st->print_cr(" OopMapBlocks: %3d /%3d", _nonstatic_oop_map_count, _max_nonstatic_oop_maps); |
4143 | if (_nonstatic_oop_map_count > 0) { |
4144 | OopMapBlock* map = _nonstatic_oop_maps; |
4145 | OopMapBlock* last_map = last_oop_map(); |
4146 | assert(map <= last_map, "Last less than first")do { if (!(map <= last_map)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4146, "assert(" "map <= last_map" ") failed", "Last less than first" ); ::breakpoint(); } } while (0); |
4147 | while (map <= last_map) { |
4148 | st->print_cr(" Offset: %3d -%3d Count: %3d", map->offset(), |
4149 | map->offset() + map->offset_span() - heapOopSize, map->count()); |
4150 | map++; |
4151 | } |
4152 | } |
4153 | } |
4154 | |
4155 | void OopMapBlocksBuilder::print_value_on(outputStream* st) const { |
4156 | print_on(st); |
4157 | } |
4158 | |
4159 | void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) { |
4160 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4160, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
4161 | |
4162 | const Klass* const super = ik->super(); |
4163 | |
4164 | // Check if this klass has an empty finalize method (i.e. one with return bytecode only), |
4165 | // in which case we don't have to register objects as finalizable |
4166 | if (!_has_empty_finalizer) { |
4167 | if (_has_finalizer || |
4168 | (super != NULL__null && super->has_finalizer())) { |
4169 | ik->set_has_finalizer(); |
4170 | } |
4171 | } |
4172 | |
4173 | #ifdef ASSERT1 |
4174 | bool f = false; |
4175 | const Method* const m = ik->lookup_method(vmSymbols::finalize_method_name(), |
4176 | vmSymbols::void_method_signature()); |
4177 | if (InstanceKlass::is_finalization_enabled() && |
4178 | (m != NULL__null) && !m->is_empty_method()) { |
4179 | f = true; |
4180 | } |
4181 | |
4182 | // Spec doesn't prevent agent from redefinition of empty finalizer. |
4183 | // Despite the fact that it's generally bad idea and redefined finalizer |
4184 | // will not work as expected we shouldn't abort vm in this case |
4185 | if (!ik->has_redefined_this_or_super()) { |
4186 | assert(ik->has_finalizer() == f, "inconsistent has_finalizer")do { if (!(ik->has_finalizer() == f)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4186, "assert(" "ik->has_finalizer() == f" ") failed", "inconsistent has_finalizer" ); ::breakpoint(); } } while (0); |
4187 | } |
4188 | #endif |
4189 | |
4190 | // Check if this klass supports the java.lang.Cloneable interface |
4191 | if (vmClasses::Cloneable_klass_loaded()) { |
4192 | if (ik->is_subtype_of(vmClasses::Cloneable_klass())) { |
4193 | ik->set_is_cloneable(); |
4194 | } |
4195 | } |
4196 | |
4197 | // Check if this klass has a vanilla default constructor |
4198 | if (super == NULL__null) { |
4199 | // java.lang.Object has empty default constructor |
4200 | ik->set_has_vanilla_constructor(); |
4201 | } else { |
4202 | if (super->has_vanilla_constructor() && |
4203 | _has_vanilla_constructor) { |
4204 | ik->set_has_vanilla_constructor(); |
4205 | } |
4206 | #ifdef ASSERT1 |
4207 | bool v = false; |
4208 | if (super->has_vanilla_constructor()) { |
4209 | const Method* const constructor = |
4210 | ik->find_method(vmSymbols::object_initializer_name(), |
4211 | vmSymbols::void_method_signature()); |
4212 | if (constructor != NULL__null && constructor->is_vanilla_constructor()) { |
4213 | v = true; |
4214 | } |
4215 | } |
4216 | assert(v == ik->has_vanilla_constructor(), "inconsistent has_vanilla_constructor")do { if (!(v == ik->has_vanilla_constructor())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4216, "assert(" "v == ik->has_vanilla_constructor()" ") failed" , "inconsistent has_vanilla_constructor"); ::breakpoint(); } } while (0); |
4217 | #endif |
4218 | } |
4219 | |
4220 | // If it cannot be fast-path allocated, set a bit in the layout helper. |
4221 | // See documentation of InstanceKlass::can_be_fastpath_allocated(). |
4222 | assert(ik->size_helper() > 0, "layout_helper is initialized")do { if (!(ik->size_helper() > 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4222, "assert(" "ik->size_helper() > 0" ") failed", "layout_helper is initialized" ); ::breakpoint(); } } while (0); |
4223 | if ((!RegisterFinalizersAtInit && ik->has_finalizer()) |
4224 | || ik->is_abstract() || ik->is_interface() |
4225 | || (ik->name() == vmSymbols::java_lang_Class() && ik->class_loader() == NULL__null) |
4226 | || ik->size_helper() >= FastAllocateSizeLimit) { |
4227 | // Forbid fast-path allocation. |
4228 | const jint lh = Klass::instance_layout_helper(ik->size_helper(), true); |
4229 | ik->set_layout_helper(lh); |
4230 | } |
4231 | } |
4232 | |
4233 | // utility methods for appending an array with check for duplicates |
4234 | |
4235 | static void append_interfaces(GrowableArray<InstanceKlass*>* result, |
4236 | const Array<InstanceKlass*>* const ifs) { |
4237 | // iterate over new interfaces |
4238 | for (int i = 0; i < ifs->length(); i++) { |
4239 | InstanceKlass* const e = ifs->at(i); |
4240 | assert(e->is_klass() && e->is_interface(), "just checking")do { if (!(e->is_klass() && e->is_interface())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4240, "assert(" "e->is_klass() && e->is_interface()" ") failed", "just checking"); ::breakpoint(); } } while (0); |
4241 | // add new interface |
4242 | result->append_if_missing(e); |
4243 | } |
4244 | } |
4245 | |
4246 | static Array<InstanceKlass*>* compute_transitive_interfaces(const InstanceKlass* super, |
4247 | Array<InstanceKlass*>* local_ifs, |
4248 | ClassLoaderData* loader_data, |
4249 | TRAPSJavaThread* __the_thread__) { |
4250 | assert(local_ifs != NULL, "invariant")do { if (!(local_ifs != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4250, "assert(" "local_ifs != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
4251 | assert(loader_data != NULL, "invariant")do { if (!(loader_data != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4251, "assert(" "loader_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
4252 | |
4253 | // Compute maximum size for transitive interfaces |
4254 | int max_transitive_size = 0; |
4255 | int super_size = 0; |
4256 | // Add superclass transitive interfaces size |
4257 | if (super != NULL__null) { |
4258 | super_size = super->transitive_interfaces()->length(); |
4259 | max_transitive_size += super_size; |
4260 | } |
4261 | // Add local interfaces' super interfaces |
4262 | const int local_size = local_ifs->length(); |
4263 | for (int i = 0; i < local_size; i++) { |
4264 | InstanceKlass* const l = local_ifs->at(i); |
4265 | max_transitive_size += l->transitive_interfaces()->length(); |
4266 | } |
4267 | // Finally add local interfaces |
4268 | max_transitive_size += local_size; |
4269 | // Construct array |
4270 | if (max_transitive_size == 0) { |
4271 | // no interfaces, use canonicalized array |
4272 | return Universe::the_empty_instance_klass_array(); |
4273 | } else if (max_transitive_size == super_size) { |
4274 | // no new local interfaces added, share superklass' transitive interface array |
4275 | return super->transitive_interfaces(); |
4276 | } else if (max_transitive_size == local_size) { |
4277 | // only local interfaces added, share local interface array |
4278 | return local_ifs; |
4279 | } else { |
4280 | ResourceMark rm; |
4281 | GrowableArray<InstanceKlass*>* const result = new GrowableArray<InstanceKlass*>(max_transitive_size); |
4282 | |
4283 | // Copy down from superclass |
4284 | if (super != NULL__null) { |
4285 | append_interfaces(result, super->transitive_interfaces()); |
4286 | } |
4287 | |
4288 | // Copy down from local interfaces' superinterfaces |
4289 | for (int i = 0; i < local_size; i++) { |
4290 | InstanceKlass* const l = local_ifs->at(i); |
4291 | append_interfaces(result, l->transitive_interfaces()); |
4292 | } |
4293 | // Finally add local interfaces |
4294 | append_interfaces(result, local_ifs); |
4295 | |
4296 | // length will be less than the max_transitive_size if duplicates were removed |
4297 | const int length = result->length(); |
4298 | assert(length <= max_transitive_size, "just checking")do { if (!(length <= max_transitive_size)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4298, "assert(" "length <= max_transitive_size" ") failed" , "just checking"); ::breakpoint(); } } while (0); |
4299 | Array<InstanceKlass*>* const new_result = |
4300 | MetadataFactory::new_array<InstanceKlass*>(loader_data, length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
4301 | for (int i = 0; i < length; i++) { |
4302 | InstanceKlass* const e = result->at(i); |
4303 | assert(e != NULL, "just checking")do { if (!(e != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4303, "assert(" "e != __null" ") failed", "just checking"); ::breakpoint(); } } while (0); |
4304 | new_result->at_put(i, e); |
4305 | } |
4306 | return new_result; |
4307 | } |
4308 | } |
4309 | |
4310 | void ClassFileParser::check_super_class_access(const InstanceKlass* this_klass, TRAPSJavaThread* __the_thread__) { |
4311 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4311, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
4312 | const Klass* const super = this_klass->super(); |
4313 | |
4314 | if (super != NULL__null) { |
4315 | const InstanceKlass* super_ik = InstanceKlass::cast(super); |
4316 | |
4317 | if (super->is_final()) { |
4318 | classfile_icce_error("class %s cannot inherit from final class %s", super_ik, THREAD__the_thread__); |
4319 | return; |
4320 | } |
4321 | |
4322 | if (super_ik->is_sealed() && !super_ik->has_as_permitted_subclass(this_klass)) { |
4323 | classfile_icce_error("class %s cannot inherit from sealed class %s", super_ik, THREAD__the_thread__); |
4324 | return; |
4325 | } |
4326 | |
4327 | // If the loader is not the boot loader then throw an exception if its |
4328 | // superclass is in package jdk.internal.reflect and its loader is not a |
4329 | // special reflection class loader |
4330 | if (!this_klass->class_loader_data()->is_the_null_class_loader_data()) { |
4331 | PackageEntry* super_package = super->package(); |
4332 | if (super_package != NULL__null && |
4333 | super_package->name()->fast_compare(vmSymbols::jdk_internal_reflect()) == 0 && |
4334 | !java_lang_ClassLoader::is_reflection_class_loader(this_klass->class_loader())) { |
4335 | ResourceMark rm(THREAD__the_thread__); |
4336 | Exceptions::fthrow( |
4337 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4337, |
4338 | vmSymbols::java_lang_IllegalAccessError(), |
4339 | "class %s loaded by %s cannot access jdk/internal/reflect superclass %s", |
4340 | this_klass->external_name(), |
4341 | this_klass->class_loader_data()->loader_name_and_id(), |
4342 | super->external_name()); |
4343 | return; |
4344 | } |
4345 | } |
4346 | |
4347 | Reflection::VerifyClassAccessResults vca_result = |
4348 | Reflection::verify_class_access(this_klass, InstanceKlass::cast(super), false); |
4349 | if (vca_result != Reflection::ACCESS_OK) { |
4350 | ResourceMark rm(THREAD__the_thread__); |
4351 | char* msg = Reflection::verify_class_access_msg(this_klass, |
4352 | InstanceKlass::cast(super), |
4353 | vca_result); |
4354 | if (msg == NULL__null) { |
4355 | bool same_module = (this_klass->module() == super->module()); |
4356 | Exceptions::fthrow( |
4357 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4357, |
4358 | vmSymbols::java_lang_IllegalAccessError(), |
4359 | "class %s cannot access its %ssuperclass %s (%s%s%s)", |
4360 | this_klass->external_name(), |
4361 | super->is_abstract() ? "abstract " : "", |
4362 | super->external_name(), |
4363 | (same_module) ? this_klass->joint_in_module_of_loader(super) : this_klass->class_in_module_of_loader(), |
4364 | (same_module) ? "" : "; ", |
4365 | (same_module) ? "" : super->class_in_module_of_loader()); |
4366 | } else { |
4367 | // Add additional message content. |
4368 | Exceptions::fthrow( |
4369 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4369, |
4370 | vmSymbols::java_lang_IllegalAccessError(), |
4371 | "superclass access check failed: %s", |
4372 | msg); |
4373 | } |
4374 | } |
4375 | } |
4376 | } |
4377 | |
4378 | |
4379 | void ClassFileParser::check_super_interface_access(const InstanceKlass* this_klass, TRAPSJavaThread* __the_thread__) { |
4380 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4380, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
4381 | const Array<InstanceKlass*>* const local_interfaces = this_klass->local_interfaces(); |
4382 | const int lng = local_interfaces->length(); |
4383 | for (int i = lng - 1; i >= 0; i--) { |
4384 | InstanceKlass* const k = local_interfaces->at(i); |
4385 | assert (k != NULL && k->is_interface(), "invalid interface")do { if (!(k != __null && k->is_interface())) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4385, "assert(" "k != __null && k->is_interface()" ") failed", "invalid interface"); ::breakpoint(); } } while ( 0); |
4386 | |
4387 | if (k->is_sealed() && !k->has_as_permitted_subclass(this_klass)) { |
4388 | classfile_icce_error(this_klass->is_interface() ? |
4389 | "class %s cannot extend sealed interface %s" : |
4390 | "class %s cannot implement sealed interface %s", |
4391 | k, THREAD__the_thread__); |
4392 | return; |
4393 | } |
4394 | |
4395 | Reflection::VerifyClassAccessResults vca_result = |
4396 | Reflection::verify_class_access(this_klass, k, false); |
4397 | if (vca_result != Reflection::ACCESS_OK) { |
4398 | ResourceMark rm(THREAD__the_thread__); |
4399 | char* msg = Reflection::verify_class_access_msg(this_klass, |
4400 | k, |
4401 | vca_result); |
4402 | if (msg == NULL__null) { |
4403 | bool same_module = (this_klass->module() == k->module()); |
4404 | Exceptions::fthrow( |
4405 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4405, |
4406 | vmSymbols::java_lang_IllegalAccessError(), |
4407 | "class %s cannot access its superinterface %s (%s%s%s)", |
4408 | this_klass->external_name(), |
4409 | k->external_name(), |
4410 | (same_module) ? this_klass->joint_in_module_of_loader(k) : this_klass->class_in_module_of_loader(), |
4411 | (same_module) ? "" : "; ", |
4412 | (same_module) ? "" : k->class_in_module_of_loader()); |
4413 | } else { |
4414 | // Add additional message content. |
4415 | Exceptions::fthrow( |
4416 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4416, |
4417 | vmSymbols::java_lang_IllegalAccessError(), |
4418 | "superinterface check failed: %s", |
4419 | msg); |
4420 | } |
4421 | } |
4422 | } |
4423 | } |
4424 | |
4425 | |
4426 | static void check_final_method_override(const InstanceKlass* this_klass, TRAPSJavaThread* __the_thread__) { |
4427 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4427, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
4428 | const Array<Method*>* const methods = this_klass->methods(); |
4429 | const int num_methods = methods->length(); |
4430 | |
4431 | // go thru each method and check if it overrides a final method |
4432 | for (int index = 0; index < num_methods; index++) { |
4433 | const Method* const m = methods->at(index); |
4434 | |
4435 | // skip private, static, and <init> methods |
4436 | if ((!m->is_private() && !m->is_static()) && |
4437 | (m->name() != vmSymbols::object_initializer_name())) { |
4438 | |
4439 | const Symbol* const name = m->name(); |
4440 | const Symbol* const signature = m->signature(); |
4441 | const Klass* k = this_klass->super(); |
4442 | const Method* super_m = NULL__null; |
4443 | while (k != NULL__null) { |
4444 | // skip supers that don't have final methods. |
4445 | if (k->has_final_method()) { |
4446 | // lookup a matching method in the super class hierarchy |
4447 | super_m = InstanceKlass::cast(k)->lookup_method(name, signature); |
4448 | if (super_m == NULL__null) { |
4449 | break; // didn't find any match; get out |
4450 | } |
4451 | |
4452 | if (super_m->is_final() && !super_m->is_static() && |
4453 | !super_m->access_flags().is_private()) { |
4454 | // matching method in super is final, and not static or private |
4455 | bool can_access = Reflection::verify_member_access(this_klass, |
4456 | super_m->method_holder(), |
4457 | super_m->method_holder(), |
4458 | super_m->access_flags(), |
4459 | false, false, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
4460 | if (can_access) { |
4461 | // this class can access super final method and therefore override |
4462 | ResourceMark rm(THREAD__the_thread__); |
4463 | THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } |
4464 | err_msg("class %s overrides final method %s.%s%s",{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } |
4465 | this_klass->external_name(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } |
4466 | super_m->method_holder()->external_name(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } |
4467 | name->as_C_string(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } |
4468 | signature->as_C_string())){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; }; |
4469 | } |
4470 | } |
4471 | |
4472 | // continue to look from super_m's holder's super. |
4473 | k = super_m->method_holder()->super(); |
4474 | continue; |
4475 | } |
4476 | |
4477 | k = k->super(); |
4478 | } |
4479 | } |
4480 | } |
4481 | } |
4482 | |
4483 | |
4484 | // assumes that this_klass is an interface |
4485 | static void check_illegal_static_method(const InstanceKlass* this_klass, TRAPSJavaThread* __the_thread__) { |
4486 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4486, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
4487 | assert(this_klass->is_interface(), "not an interface")do { if (!(this_klass->is_interface())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4487, "assert(" "this_klass->is_interface()" ") failed", "not an interface"); ::breakpoint(); } } while (0); |
4488 | const Array<Method*>* methods = this_klass->methods(); |
4489 | const int num_methods = methods->length(); |
4490 | |
4491 | for (int index = 0; index < num_methods; index++) { |
4492 | const Method* const m = methods->at(index); |
4493 | // if m is static and not the init method, throw a verify error |
4494 | if ((m->is_static()) && (m->name() != vmSymbols::class_initializer_name())) { |
4495 | ResourceMark rm(THREAD__the_thread__); |
4496 | Exceptions::fthrow( |
4497 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4497, |
4498 | vmSymbols::java_lang_VerifyError(), |
4499 | "Illegal static method %s in interface %s", |
4500 | m->name()->as_C_string(), |
4501 | this_klass->external_name() |
4502 | ); |
4503 | return; |
4504 | } |
4505 | } |
4506 | } |
4507 | |
4508 | // utility methods for format checking |
4509 | |
4510 | void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPSJavaThread* __the_thread__) const { |
4511 | const bool is_module = (flags & JVM_ACC_MODULE) != 0; |
4512 | assert(_major_version >= JAVA_9_VERSION || !is_module, "JVM_ACC_MODULE should not be set")do { if (!(_major_version >= 53 || !is_module)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4512, "assert(" "_major_version >= 53 || !is_module" ") failed" , "JVM_ACC_MODULE should not be set"); ::breakpoint(); } } while (0); |
4513 | if (is_module) { |
4514 | ResourceMark rm(THREAD__the_thread__); |
4515 | Exceptions::fthrow( |
4516 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4516, |
4517 | vmSymbols::java_lang_NoClassDefFoundError(), |
4518 | "%s is not a class because access_flag ACC_MODULE is set", |
4519 | _class_name->as_C_string()); |
4520 | return; |
4521 | } |
4522 | |
4523 | if (!_need_verify) { return; } |
4524 | |
4525 | const bool is_interface = (flags & JVM_ACC_INTERFACE) != 0; |
4526 | const bool is_abstract = (flags & JVM_ACC_ABSTRACT) != 0; |
4527 | const bool is_final = (flags & JVM_ACC_FINAL) != 0; |
4528 | const bool is_super = (flags & JVM_ACC_SUPER) != 0; |
4529 | const bool is_enum = (flags & JVM_ACC_ENUM) != 0; |
4530 | const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0; |
4531 | const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION49; |
4532 | |
4533 | if ((is_abstract && is_final) || |
4534 | (is_interface && !is_abstract) || |
4535 | (is_interface && major_gte_1_5 && (is_super || is_enum)) || |
4536 | (!is_interface && major_gte_1_5 && is_annotation)) { |
4537 | ResourceMark rm(THREAD__the_thread__); |
4538 | Exceptions::fthrow( |
4539 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4539, |
4540 | vmSymbols::java_lang_ClassFormatError(), |
4541 | "Illegal class modifiers in class %s: 0x%X", |
4542 | _class_name->as_C_string(), flags |
4543 | ); |
4544 | return; |
4545 | } |
4546 | } |
4547 | |
4548 | static bool has_illegal_visibility(jint flags) { |
4549 | const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; |
4550 | const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; |
4551 | const bool is_private = (flags & JVM_ACC_PRIVATE) != 0; |
4552 | |
4553 | return ((is_public && is_protected) || |
4554 | (is_public && is_private) || |
4555 | (is_protected && is_private)); |
4556 | } |
4557 | |
4558 | // A legal major_version.minor_version must be one of the following: |
4559 | // |
4560 | // Major_version >= 45 and major_version < 56, any minor_version. |
4561 | // Major_version >= 56 and major_version <= JVM_CLASSFILE_MAJOR_VERSION and minor_version = 0. |
4562 | // Major_version = JVM_CLASSFILE_MAJOR_VERSION and minor_version = 65535 and --enable-preview is present. |
4563 | // |
4564 | void ClassFileParser::verify_class_version(u2 major, u2 minor, Symbol* class_name, TRAPSJavaThread* __the_thread__){ |
4565 | ResourceMark rm(THREAD__the_thread__); |
4566 | const u2 max_version = JVM_CLASSFILE_MAJOR_VERSION63; |
4567 | if (major < JAVA_MIN_SUPPORTED_VERSION45) { |
4568 | classfile_ucve_error("%s (class file version %u.%u) was compiled with an invalid major version", |
4569 | class_name, major, minor, THREAD__the_thread__); |
4570 | return; |
4571 | } |
4572 | |
4573 | if (major > max_version) { |
4574 | Exceptions::fthrow( |
4575 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4575, |
4576 | vmSymbols::java_lang_UnsupportedClassVersionError(), |
4577 | "%s has been compiled by a more recent version of the Java Runtime (class file version %u.%u), " |
4578 | "this version of the Java Runtime only recognizes class file versions up to %u.0", |
4579 | class_name->as_C_string(), major, minor, JVM_CLASSFILE_MAJOR_VERSION63); |
4580 | return; |
4581 | } |
4582 | |
4583 | if (major < JAVA_12_VERSION56 || minor == 0) { |
4584 | return; |
4585 | } |
4586 | |
4587 | if (minor == JAVA_PREVIEW_MINOR_VERSION65535) { |
4588 | if (major != max_version) { |
4589 | Exceptions::fthrow( |
4590 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4590, |
4591 | vmSymbols::java_lang_UnsupportedClassVersionError(), |
4592 | "%s (class file version %u.%u) was compiled with preview features that are unsupported. " |
4593 | "This version of the Java Runtime only recognizes preview features for class file version %u.%u", |
4594 | class_name->as_C_string(), major, minor, JVM_CLASSFILE_MAJOR_VERSION63, JAVA_PREVIEW_MINOR_VERSION65535); |
4595 | return; |
4596 | } |
4597 | |
4598 | if (!Arguments::enable_preview()) { |
4599 | classfile_ucve_error("Preview features are not enabled for %s (class file version %u.%u). Try running with '--enable-preview'", |
4600 | class_name, major, minor, THREAD__the_thread__); |
4601 | return; |
4602 | } |
4603 | |
4604 | } else { // minor != JAVA_PREVIEW_MINOR_VERSION |
4605 | classfile_ucve_error("%s (class file version %u.%u) was compiled with an invalid non-zero minor version", |
4606 | class_name, major, minor, THREAD__the_thread__); |
4607 | } |
4608 | } |
4609 | |
4610 | void ClassFileParser::verify_legal_field_modifiers(jint flags, |
4611 | bool is_interface, |
4612 | TRAPSJavaThread* __the_thread__) const { |
4613 | if (!_need_verify) { return; } |
4614 | |
4615 | const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; |
4616 | const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; |
4617 | const bool is_private = (flags & JVM_ACC_PRIVATE) != 0; |
4618 | const bool is_static = (flags & JVM_ACC_STATIC) != 0; |
4619 | const bool is_final = (flags & JVM_ACC_FINAL) != 0; |
4620 | const bool is_volatile = (flags & JVM_ACC_VOLATILE) != 0; |
4621 | const bool is_transient = (flags & JVM_ACC_TRANSIENT) != 0; |
4622 | const bool is_enum = (flags & JVM_ACC_ENUM) != 0; |
4623 | const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION49; |
4624 | |
4625 | bool is_illegal = false; |
4626 | |
4627 | if (is_interface) { |
4628 | if (!is_public || !is_static || !is_final || is_private || |
4629 | is_protected || is_volatile || is_transient || |
4630 | (major_gte_1_5 && is_enum)) { |
4631 | is_illegal = true; |
4632 | } |
4633 | } else { // not interface |
4634 | if (has_illegal_visibility(flags) || (is_final && is_volatile)) { |
4635 | is_illegal = true; |
4636 | } |
4637 | } |
4638 | |
4639 | if (is_illegal) { |
4640 | ResourceMark rm(THREAD__the_thread__); |
4641 | Exceptions::fthrow( |
4642 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4642, |
4643 | vmSymbols::java_lang_ClassFormatError(), |
4644 | "Illegal field modifiers in class %s: 0x%X", |
4645 | _class_name->as_C_string(), flags); |
4646 | return; |
4647 | } |
4648 | } |
4649 | |
4650 | void ClassFileParser::verify_legal_method_modifiers(jint flags, |
4651 | bool is_interface, |
4652 | const Symbol* name, |
4653 | TRAPSJavaThread* __the_thread__) const { |
4654 | if (!_need_verify) { return; } |
4655 | |
4656 | const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; |
4657 | const bool is_private = (flags & JVM_ACC_PRIVATE) != 0; |
4658 | const bool is_static = (flags & JVM_ACC_STATIC) != 0; |
4659 | const bool is_final = (flags & JVM_ACC_FINAL) != 0; |
4660 | const bool is_native = (flags & JVM_ACC_NATIVE) != 0; |
4661 | const bool is_abstract = (flags & JVM_ACC_ABSTRACT) != 0; |
4662 | const bool is_bridge = (flags & JVM_ACC_BRIDGE) != 0; |
4663 | const bool is_strict = (flags & JVM_ACC_STRICT) != 0; |
4664 | const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0; |
4665 | const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; |
4666 | const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION49; |
4667 | const bool major_gte_8 = _major_version >= JAVA_8_VERSION52; |
4668 | const bool major_gte_17 = _major_version >= JAVA_17_VERSION61; |
4669 | const bool is_initializer = (name == vmSymbols::object_initializer_name()); |
4670 | |
4671 | bool is_illegal = false; |
4672 | |
4673 | if (is_interface) { |
4674 | if (major_gte_8) { |
4675 | // Class file version is JAVA_8_VERSION or later Methods of |
4676 | // interfaces may set any of the flags except ACC_PROTECTED, |
4677 | // ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED; they must |
4678 | // have exactly one of the ACC_PUBLIC or ACC_PRIVATE flags set. |
4679 | if ((is_public == is_private) || /* Only one of private and public should be true - XNOR */ |
4680 | (is_native || is_protected || is_final || is_synchronized) || |
4681 | // If a specific method of a class or interface has its |
4682 | // ACC_ABSTRACT flag set, it must not have any of its |
4683 | // ACC_FINAL, ACC_NATIVE, ACC_PRIVATE, ACC_STATIC, |
4684 | // ACC_STRICT, or ACC_SYNCHRONIZED flags set. No need to |
4685 | // check for ACC_FINAL, ACC_NATIVE or ACC_SYNCHRONIZED as |
4686 | // those flags are illegal irrespective of ACC_ABSTRACT being set or not. |
4687 | (is_abstract && (is_private || is_static || (!major_gte_17 && is_strict)))) { |
4688 | is_illegal = true; |
4689 | } |
4690 | } else if (major_gte_1_5) { |
4691 | // Class file version in the interval [JAVA_1_5_VERSION, JAVA_8_VERSION) |
4692 | if (!is_public || is_private || is_protected || is_static || is_final || |
4693 | is_synchronized || is_native || !is_abstract || is_strict) { |
4694 | is_illegal = true; |
4695 | } |
4696 | } else { |
4697 | // Class file version is pre-JAVA_1_5_VERSION |
4698 | if (!is_public || is_static || is_final || is_native || !is_abstract) { |
4699 | is_illegal = true; |
4700 | } |
4701 | } |
4702 | } else { // not interface |
4703 | if (has_illegal_visibility(flags)) { |
4704 | is_illegal = true; |
4705 | } else { |
4706 | if (is_initializer) { |
4707 | if (is_static || is_final || is_synchronized || is_native || |
4708 | is_abstract || (major_gte_1_5 && is_bridge)) { |
4709 | is_illegal = true; |
4710 | } |
4711 | } else { // not initializer |
4712 | if (is_abstract) { |
4713 | if ((is_final || is_native || is_private || is_static || |
4714 | (major_gte_1_5 && (is_synchronized || (!major_gte_17 && is_strict))))) { |
4715 | is_illegal = true; |
4716 | } |
4717 | } |
4718 | } |
4719 | } |
4720 | } |
4721 | |
4722 | if (is_illegal) { |
4723 | ResourceMark rm(THREAD__the_thread__); |
4724 | Exceptions::fthrow( |
4725 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4725, |
4726 | vmSymbols::java_lang_ClassFormatError(), |
4727 | "Method %s in class %s has illegal modifiers: 0x%X", |
4728 | name->as_C_string(), _class_name->as_C_string(), flags); |
4729 | return; |
4730 | } |
4731 | } |
4732 | |
4733 | void ClassFileParser::verify_legal_utf8(const unsigned char* buffer, |
4734 | int length, |
4735 | TRAPSJavaThread* __the_thread__) const { |
4736 | assert(_need_verify, "only called when _need_verify is true")do { if (!(_need_verify)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4736, "assert(" "_need_verify" ") failed", "only called when _need_verify is true" ); ::breakpoint(); } } while (0); |
4737 | if (!UTF8::is_legal_utf8(buffer, length, _major_version <= 47)) { |
4738 | classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", THREAD__the_thread__); |
4739 | } |
4740 | } |
4741 | |
4742 | // Unqualified names may not contain the characters '.', ';', '[', or '/'. |
4743 | // In class names, '/' separates unqualified names. This is verified in this function also. |
4744 | // Method names also may not contain the characters '<' or '>', unless <init> |
4745 | // or <clinit>. Note that method names may not be <init> or <clinit> in this |
4746 | // method. Because these names have been checked as special cases before |
4747 | // calling this method in verify_legal_method_name. |
4748 | // |
4749 | // This method is also called from the modular system APIs in modules.cpp |
4750 | // to verify the validity of module and package names. |
4751 | bool ClassFileParser::verify_unqualified_name(const char* name, |
4752 | unsigned int length, |
4753 | int type) { |
4754 | if (length == 0) return false; // Must have at least one char. |
4755 | for (const char* p = name; p != name + length; p++) { |
4756 | switch(*p) { |
4757 | case JVM_SIGNATURE_DOT: |
4758 | case JVM_SIGNATURE_ENDCLASS: |
4759 | case JVM_SIGNATURE_ARRAY: |
4760 | // do not permit '.', ';', or '[' |
4761 | return false; |
4762 | case JVM_SIGNATURE_SLASH: |
4763 | // check for '//' or leading or trailing '/' which are not legal |
4764 | // unqualified name must not be empty |
4765 | if (type == ClassFileParser::LegalClass) { |
4766 | if (p == name || p+1 >= name+length || |
4767 | *(p+1) == JVM_SIGNATURE_SLASH) { |
4768 | return false; |
4769 | } |
4770 | } else { |
4771 | return false; // do not permit '/' unless it's class name |
4772 | } |
4773 | break; |
4774 | case JVM_SIGNATURE_SPECIAL: |
4775 | case JVM_SIGNATURE_ENDSPECIAL: |
4776 | // do not permit '<' or '>' in method names |
4777 | if (type == ClassFileParser::LegalMethod) { |
4778 | return false; |
4779 | } |
4780 | } |
4781 | } |
4782 | return true; |
4783 | } |
4784 | |
4785 | // Take pointer to a UTF8 byte string (not NUL-terminated). |
4786 | // Skip over the longest part of the string that could |
4787 | // be taken as a fieldname. Allow non-trailing '/'s if slash_ok is true. |
4788 | // Return a pointer to just past the fieldname. |
4789 | // Return NULL if no fieldname at all was found, or in the case of slash_ok |
4790 | // being true, we saw consecutive slashes (meaning we were looking for a |
4791 | // qualified path but found something that was badly-formed). |
4792 | static const char* skip_over_field_name(const char* const name, |
4793 | bool slash_ok, |
4794 | unsigned int length) { |
4795 | const char* p; |
4796 | jboolean last_is_slash = false; |
4797 | jboolean not_first_ch = false; |
4798 | |
4799 | for (p = name; p != name + length; not_first_ch = true) { |
4800 | const char* old_p = p; |
4801 | jchar ch = *p; |
4802 | if (ch < 128) { |
4803 | p++; |
4804 | // quick check for ascii |
4805 | if ((ch >= 'a' && ch <= 'z') || |
4806 | (ch >= 'A' && ch <= 'Z') || |
4807 | (ch == '_' || ch == '$') || |
4808 | (not_first_ch && ch >= '0' && ch <= '9')) { |
4809 | last_is_slash = false; |
4810 | continue; |
4811 | } |
4812 | if (slash_ok && ch == JVM_SIGNATURE_SLASH) { |
4813 | if (last_is_slash) { |
4814 | return NULL__null; // Don't permit consecutive slashes |
4815 | } |
4816 | last_is_slash = true; |
4817 | continue; |
4818 | } |
4819 | } |
4820 | else { |
4821 | jint unicode_ch; |
4822 | char* tmp_p = UTF8::next_character(p, &unicode_ch); |
4823 | p = tmp_p; |
4824 | last_is_slash = false; |
4825 | // Check if ch is Java identifier start or is Java identifier part |
4826 | // 4672820: call java.lang.Character methods directly without generating separate tables. |
4827 | EXCEPTION_MARKExceptionMark __em; JavaThread* __the_thread__ = __em.thread( );; |
4828 | // return value |
4829 | JavaValue result(T_BOOLEAN); |
4830 | // Set up the arguments to isJavaIdentifierStart or isJavaIdentifierPart |
4831 | JavaCallArguments args; |
4832 | args.push_int(unicode_ch); |
4833 | |
4834 | if (not_first_ch) { |
4835 | // public static boolean isJavaIdentifierPart(char ch); |
4836 | JavaCalls::call_static(&result, |
4837 | vmClasses::Character_klass(), |
4838 | vmSymbols::isJavaIdentifierPart_name(), |
4839 | vmSymbols::int_bool_signature(), |
4840 | &args, |
4841 | THREAD__the_thread__); |
4842 | } else { |
4843 | // public static boolean isJavaIdentifierStart(char ch); |
4844 | JavaCalls::call_static(&result, |
4845 | vmClasses::Character_klass(), |
4846 | vmSymbols::isJavaIdentifierStart_name(), |
4847 | vmSymbols::int_bool_signature(), |
4848 | &args, |
4849 | THREAD__the_thread__); |
4850 | } |
4851 | if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { |
4852 | CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); |
4853 | return NULL__null; |
4854 | } |
4855 | if(result.get_jboolean()) { |
4856 | continue; |
4857 | } |
4858 | } |
4859 | return (not_first_ch) ? old_p : NULL__null; |
4860 | } |
4861 | return (not_first_ch && !last_is_slash) ? p : NULL__null; |
4862 | } |
4863 | |
4864 | // Take pointer to a UTF8 byte string (not NUL-terminated). |
4865 | // Skip over the longest part of the string that could |
4866 | // be taken as a field signature. Allow "void" if void_ok. |
4867 | // Return a pointer to just past the signature. |
4868 | // Return NULL if no legal signature is found. |
4869 | const char* ClassFileParser::skip_over_field_signature(const char* signature, |
4870 | bool void_ok, |
4871 | unsigned int length, |
4872 | TRAPSJavaThread* __the_thread__) const { |
4873 | unsigned int array_dim = 0; |
4874 | while (length > 0) { |
4875 | switch (signature[0]) { |
4876 | case JVM_SIGNATURE_VOID: if (!void_ok) { return NULL__null; } |
4877 | case JVM_SIGNATURE_BOOLEAN: |
4878 | case JVM_SIGNATURE_BYTE: |
4879 | case JVM_SIGNATURE_CHAR: |
4880 | case JVM_SIGNATURE_SHORT: |
4881 | case JVM_SIGNATURE_INT: |
4882 | case JVM_SIGNATURE_FLOAT: |
4883 | case JVM_SIGNATURE_LONG: |
4884 | case JVM_SIGNATURE_DOUBLE: |
4885 | return signature + 1; |
4886 | case JVM_SIGNATURE_CLASS: { |
4887 | if (_major_version < JAVA_1_5_VERSION49) { |
4888 | // Skip over the class name if one is there |
4889 | const char* const p = skip_over_field_name(signature + 1, true, --length); |
4890 | |
4891 | // The next character better be a semicolon |
4892 | if (p && (p - signature) > 1 && p[0] == JVM_SIGNATURE_ENDCLASS) { |
4893 | return p + 1; |
4894 | } |
4895 | } |
4896 | else { |
4897 | // Skip leading 'L' and ignore first appearance of ';' |
4898 | signature++; |
4899 | const char* c = (const char*) memchr(signature, JVM_SIGNATURE_ENDCLASS, length - 1); |
4900 | // Format check signature |
4901 | if (c != NULL__null) { |
4902 | int newlen = c - (char*) signature; |
4903 | bool legal = verify_unqualified_name(signature, newlen, LegalClass); |
4904 | if (!legal) { |
4905 | classfile_parse_error("Class name is empty or contains illegal character " |
4906 | "in descriptor in class file %s", |
4907 | THREAD__the_thread__); |
4908 | return NULL__null; |
4909 | } |
4910 | return signature + newlen + 1; |
4911 | } |
4912 | } |
4913 | return NULL__null; |
4914 | } |
4915 | case JVM_SIGNATURE_ARRAY: |
4916 | array_dim++; |
4917 | if (array_dim > 255) { |
4918 | // 4277370: array descriptor is valid only if it represents 255 or fewer dimensions. |
4919 | classfile_parse_error("Array type descriptor has more than 255 dimensions in class file %s", THREAD__the_thread__); |
4920 | return NULL__null; |
4921 | } |
4922 | // The rest of what's there better be a legal signature |
4923 | signature++; |
4924 | length--; |
4925 | void_ok = false; |
4926 | break; |
4927 | default: |
4928 | return NULL__null; |
4929 | } |
4930 | } |
4931 | return NULL__null; |
4932 | } |
4933 | |
4934 | // Checks if name is a legal class name. |
4935 | void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const { |
4936 | if (!_need_verify || _relax_verify) { return; } |
4937 | |
4938 | assert(name->refcount() > 0, "symbol must be kept alive")do { if (!(name->refcount() > 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4938, "assert(" "name->refcount() > 0" ") failed", "symbol must be kept alive" ); ::breakpoint(); } } while (0); |
4939 | char* bytes = (char*)name->bytes(); |
4940 | unsigned int length = name->utf8_length(); |
4941 | bool legal = false; |
4942 | |
4943 | if (length > 0) { |
4944 | const char* p; |
4945 | if (bytes[0] == JVM_SIGNATURE_ARRAY) { |
4946 | p = skip_over_field_signature(bytes, false, length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
4947 | legal = (p != NULL__null) && ((p - bytes) == (int)length); |
4948 | } else if (_major_version < JAVA_1_5_VERSION49) { |
4949 | if (bytes[0] != JVM_SIGNATURE_SPECIAL) { |
4950 | p = skip_over_field_name(bytes, true, length); |
4951 | legal = (p != NULL__null) && ((p - bytes) == (int)length); |
4952 | } |
4953 | } else { |
4954 | // 4900761: relax the constraints based on JSR202 spec |
4955 | // Class names may be drawn from the entire Unicode character set. |
4956 | // Identifiers between '/' must be unqualified names. |
4957 | // The utf8 string has been verified when parsing cpool entries. |
4958 | legal = verify_unqualified_name(bytes, length, LegalClass); |
4959 | } |
4960 | } |
4961 | if (!legal) { |
4962 | ResourceMark rm(THREAD__the_thread__); |
4963 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4963, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
4964 | Exceptions::fthrow( |
4965 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4965, |
4966 | vmSymbols::java_lang_ClassFormatError(), |
4967 | "Illegal class name \"%.*s\" in class file %s", length, bytes, |
4968 | _class_name->as_C_string() |
4969 | ); |
4970 | return; |
4971 | } |
4972 | } |
4973 | |
4974 | // Checks if name is a legal field name. |
4975 | void ClassFileParser::verify_legal_field_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const { |
4976 | if (!_need_verify || _relax_verify) { return; } |
4977 | |
4978 | char* bytes = (char*)name->bytes(); |
4979 | unsigned int length = name->utf8_length(); |
4980 | bool legal = false; |
4981 | |
4982 | if (length > 0) { |
4983 | if (_major_version < JAVA_1_5_VERSION49) { |
4984 | if (bytes[0] != JVM_SIGNATURE_SPECIAL) { |
4985 | const char* p = skip_over_field_name(bytes, false, length); |
4986 | legal = (p != NULL__null) && ((p - bytes) == (int)length); |
4987 | } |
4988 | } else { |
4989 | // 4881221: relax the constraints based on JSR202 spec |
4990 | legal = verify_unqualified_name(bytes, length, LegalField); |
4991 | } |
4992 | } |
4993 | |
4994 | if (!legal) { |
4995 | ResourceMark rm(THREAD__the_thread__); |
4996 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4996, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
4997 | Exceptions::fthrow( |
4998 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4998, |
4999 | vmSymbols::java_lang_ClassFormatError(), |
5000 | "Illegal field name \"%.*s\" in class %s", length, bytes, |
5001 | _class_name->as_C_string() |
5002 | ); |
5003 | return; |
5004 | } |
5005 | } |
5006 | |
5007 | // Checks if name is a legal method name. |
5008 | void ClassFileParser::verify_legal_method_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const { |
5009 | if (!_need_verify || _relax_verify) { return; } |
5010 | |
5011 | assert(name != NULL, "method name is null")do { if (!(name != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5011, "assert(" "name != __null" ") failed", "method name is null" ); ::breakpoint(); } } while (0); |
5012 | char* bytes = (char*)name->bytes(); |
5013 | unsigned int length = name->utf8_length(); |
5014 | bool legal = false; |
5015 | |
5016 | if (length > 0) { |
5017 | if (bytes[0] == JVM_SIGNATURE_SPECIAL) { |
5018 | if (name == vmSymbols::object_initializer_name() || name == vmSymbols::class_initializer_name()) { |
5019 | legal = true; |
5020 | } |
5021 | } else if (_major_version < JAVA_1_5_VERSION49) { |
5022 | const char* p; |
5023 | p = skip_over_field_name(bytes, false, length); |
5024 | legal = (p != NULL__null) && ((p - bytes) == (int)length); |
5025 | } else { |
5026 | // 4881221: relax the constraints based on JSR202 spec |
5027 | legal = verify_unqualified_name(bytes, length, LegalMethod); |
5028 | } |
5029 | } |
5030 | |
5031 | if (!legal) { |
5032 | ResourceMark rm(THREAD__the_thread__); |
5033 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5033, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5034 | Exceptions::fthrow( |
5035 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5035, |
5036 | vmSymbols::java_lang_ClassFormatError(), |
5037 | "Illegal method name \"%.*s\" in class %s", length, bytes, |
5038 | _class_name->as_C_string() |
5039 | ); |
5040 | return; |
5041 | } |
5042 | } |
5043 | |
5044 | |
5045 | // Checks if signature is a legal field signature. |
5046 | void ClassFileParser::verify_legal_field_signature(const Symbol* name, |
5047 | const Symbol* signature, |
5048 | TRAPSJavaThread* __the_thread__) const { |
5049 | if (!_need_verify) { return; } |
5050 | |
5051 | const char* const bytes = (const char* const)signature->bytes(); |
5052 | const unsigned int length = signature->utf8_length(); |
5053 | const char* const p = skip_over_field_signature(bytes, false, length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5054 | |
5055 | if (p == NULL__null || (p - bytes) != (int)length) { |
5056 | throwIllegalSignature("Field", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5057 | } |
5058 | } |
5059 | |
5060 | // Check that the signature is compatible with the method name. For example, |
5061 | // check that <init> has a void signature. |
5062 | void ClassFileParser::verify_legal_name_with_signature(const Symbol* name, |
5063 | const Symbol* signature, |
5064 | TRAPSJavaThread* __the_thread__) const { |
5065 | if (!_need_verify) { |
5066 | return; |
5067 | } |
5068 | |
5069 | // Class initializers cannot have args for class format version >= 51. |
5070 | if (name == vmSymbols::class_initializer_name() && |
5071 | signature != vmSymbols::void_method_signature() && |
5072 | _major_version >= JAVA_7_VERSION51) { |
5073 | throwIllegalSignature("Method", name, signature, THREAD__the_thread__); |
5074 | return; |
5075 | } |
5076 | |
5077 | int sig_length = signature->utf8_length(); |
5078 | if (name->utf8_length() > 0 && |
5079 | name->char_at(0) == JVM_SIGNATURE_SPECIAL && |
5080 | sig_length > 0 && |
5081 | signature->char_at(sig_length - 1) != JVM_SIGNATURE_VOID) { |
5082 | throwIllegalSignature("Method", name, signature, THREAD__the_thread__); |
5083 | } |
5084 | } |
5085 | |
5086 | // Checks if signature is a legal method signature. |
5087 | // Returns number of parameters |
5088 | int ClassFileParser::verify_legal_method_signature(const Symbol* name, |
5089 | const Symbol* signature, |
5090 | TRAPSJavaThread* __the_thread__) const { |
5091 | if (!_need_verify) { |
5092 | // make sure caller's args_size will be less than 0 even for non-static |
5093 | // method so it will be recomputed in compute_size_of_parameters(). |
5094 | return -2; |
5095 | } |
5096 | |
5097 | unsigned int args_size = 0; |
5098 | const char* p = (const char*)signature->bytes(); |
5099 | unsigned int length = signature->utf8_length(); |
5100 | const char* nextp; |
5101 | |
5102 | // The first character must be a '(' |
5103 | if ((length > 0) && (*p++ == JVM_SIGNATURE_FUNC)) { |
5104 | length--; |
5105 | // Skip over legal field signatures |
5106 | nextp = skip_over_field_signature(p, false, length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
5107 | while ((length > 0) && (nextp != NULL__null)) { |
5108 | args_size++; |
5109 | if (p[0] == 'J' || p[0] == 'D') { |
5110 | args_size++; |
5111 | } |
5112 | length -= nextp - p; |
5113 | p = nextp; |
5114 | nextp = skip_over_field_signature(p, false, length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
5115 | } |
5116 | // The first non-signature thing better be a ')' |
5117 | if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) { |
5118 | length--; |
5119 | // Now we better just have a return value |
5120 | nextp = skip_over_field_signature(p, true, length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
5121 | if (nextp && ((int)length == (nextp - p))) { |
5122 | return args_size; |
5123 | } |
5124 | } |
5125 | } |
5126 | // Report error |
5127 | throwIllegalSignature("Method", name, signature, THREAD__the_thread__); |
5128 | return 0; |
5129 | } |
5130 | |
5131 | int ClassFileParser::static_field_size() const { |
5132 | assert(_field_info != NULL, "invariant")do { if (!(_field_info != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5132, "assert(" "_field_info != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5133 | return _field_info->_static_field_size; |
5134 | } |
5135 | |
5136 | int ClassFileParser::total_oop_map_count() const { |
5137 | assert(_field_info != NULL, "invariant")do { if (!(_field_info != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5137, "assert(" "_field_info != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5138 | return _field_info->oop_map_blocks->_nonstatic_oop_map_count; |
5139 | } |
5140 | |
5141 | jint ClassFileParser::layout_size() const { |
5142 | assert(_field_info != NULL, "invariant")do { if (!(_field_info != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5142, "assert(" "_field_info != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5143 | return _field_info->_instance_size; |
5144 | } |
5145 | |
5146 | static void check_methods_for_intrinsics(const InstanceKlass* ik, |
5147 | const Array<Method*>* methods) { |
5148 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5148, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
5149 | assert(methods != NULL, "invariant")do { if (!(methods != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5149, "assert(" "methods != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5150 | |
5151 | // Set up Method*::intrinsic_id as soon as we know the names of methods. |
5152 | // (We used to do this lazily, but now we query it in Rewriter, |
5153 | // which is eagerly done for every method, so we might as well do it now, |
5154 | // when everything is fresh in memory.) |
5155 | const vmSymbolID klass_id = Method::klass_id_for_intrinsics(ik); |
5156 | |
5157 | if (klass_id != vmSymbolID::NO_SID) { |
5158 | for (int j = 0; j < methods->length(); ++j) { |
5159 | Method* method = methods->at(j); |
5160 | method->init_intrinsic_id(klass_id); |
5161 | |
5162 | if (CheckIntrinsics) { |
5163 | // Check if an intrinsic is defined for method 'method', |
5164 | // but the method is not annotated with @IntrinsicCandidate. |
5165 | if (method->intrinsic_id() != vmIntrinsics::_none && |
5166 | !method->intrinsic_candidate()) { |
5167 | tty->print("Compiler intrinsic is defined for method [%s], " |
5168 | "but the method is not annotated with @IntrinsicCandidate.%s", |
5169 | method->name_and_sig_as_C_string(), |
5170 | NOT_DEBUG(" Method will not be inlined.") DEBUG_ONLY(" Exiting.")" Exiting." |
5171 | ); |
5172 | tty->cr(); |
5173 | DEBUG_ONLY(vm_exit(1))vm_exit(1); |
5174 | } |
5175 | // Check is the method 'method' is annotated with @IntrinsicCandidate, |
5176 | // but there is no intrinsic available for it. |
5177 | if (method->intrinsic_candidate() && |
5178 | method->intrinsic_id() == vmIntrinsics::_none) { |
5179 | tty->print("Method [%s] is annotated with @IntrinsicCandidate, " |
5180 | "but no compiler intrinsic is defined for the method.%s", |
5181 | method->name_and_sig_as_C_string(), |
5182 | NOT_DEBUG("") DEBUG_ONLY(" Exiting.")" Exiting." |
5183 | ); |
5184 | tty->cr(); |
5185 | DEBUG_ONLY(vm_exit(1))vm_exit(1); |
5186 | } |
5187 | } |
5188 | } // end for |
5189 | |
5190 | #ifdef ASSERT1 |
5191 | if (CheckIntrinsics) { |
5192 | // Check for orphan methods in the current class. A method m |
5193 | // of a class C is orphan if an intrinsic is defined for method m, |
5194 | // but class C does not declare m. |
5195 | // The check is potentially expensive, therefore it is available |
5196 | // only in debug builds. |
5197 | |
5198 | for (auto id : EnumRange<vmIntrinsicID>{}) { |
5199 | if (vmIntrinsics::_compiledLambdaForm == id) { |
5200 | // The _compiledLamdbdaForm intrinsic is a special marker for bytecode |
5201 | // generated for the JVM from a LambdaForm and therefore no method |
5202 | // is defined for it. |
5203 | continue; |
5204 | } |
5205 | if (vmIntrinsics::_blackhole == id) { |
5206 | // The _blackhole intrinsic is a special marker. No explicit method |
5207 | // is defined for it. |
5208 | continue; |
5209 | } |
5210 | |
5211 | if (vmIntrinsics::class_for(id) == klass_id) { |
5212 | // Check if the current class contains a method with the same |
5213 | // name, flags, signature. |
5214 | bool match = false; |
5215 | for (int j = 0; j < methods->length(); ++j) { |
5216 | const Method* method = methods->at(j); |
5217 | if (method->intrinsic_id() == id) { |
5218 | match = true; |
5219 | break; |
5220 | } |
5221 | } |
5222 | |
5223 | if (!match) { |
5224 | char buf[1000]; |
5225 | tty->print("Compiler intrinsic is defined for method [%s], " |
5226 | "but the method is not available in class [%s].%s", |
5227 | vmIntrinsics::short_name_as_C_string(id, buf, sizeof(buf)), |
5228 | ik->name()->as_C_string(), |
5229 | NOT_DEBUG("") DEBUG_ONLY(" Exiting.")" Exiting." |
5230 | ); |
5231 | tty->cr(); |
5232 | DEBUG_ONLY(vm_exit(1))vm_exit(1); |
5233 | } |
5234 | } |
5235 | } // end for |
5236 | } // CheckIntrinsics |
5237 | #endif // ASSERT |
5238 | } |
5239 | } |
5240 | |
5241 | InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, |
5242 | const ClassInstanceInfo& cl_inst_info, |
5243 | TRAPSJavaThread* __the_thread__) { |
5244 | if (_klass != NULL__null) { |
5245 | return _klass; |
5246 | } |
5247 | |
5248 | InstanceKlass* const ik = |
5249 | InstanceKlass::allocate_instance_klass(*this, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
5250 | |
5251 | if (is_hidden()) { |
5252 | mangle_hidden_class_name(ik); |
5253 | } |
5254 | |
5255 | fill_instance_klass(ik, changed_by_loadhook, cl_inst_info, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
5256 | |
5257 | assert(_klass == ik, "invariant")do { if (!(_klass == ik)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5257, "assert(" "_klass == ik" ") failed", "invariant"); :: breakpoint(); } } while (0); |
5258 | |
5259 | return ik; |
5260 | } |
5261 | |
5262 | void ClassFileParser::fill_instance_klass(InstanceKlass* ik, |
5263 | bool changed_by_loadhook, |
5264 | const ClassInstanceInfo& cl_inst_info, |
5265 | TRAPSJavaThread* __the_thread__) { |
5266 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5266, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
5267 | |
5268 | // Set name and CLD before adding to CLD |
5269 | ik->set_class_loader_data(_loader_data); |
5270 | ik->set_name(_class_name); |
5271 | |
5272 | // Add all classes to our internal class loader list here, |
5273 | // including classes in the bootstrap (NULL) class loader. |
5274 | const bool publicize = !is_internal(); |
5275 | |
5276 | _loader_data->add_class(ik, publicize); |
5277 | |
5278 | set_klass_to_deallocate(ik); |
5279 | |
5280 | assert(_field_info != NULL, "invariant")do { if (!(_field_info != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5280, "assert(" "_field_info != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5281 | assert(ik->static_field_size() == _field_info->_static_field_size, "sanity")do { if (!(ik->static_field_size() == _field_info->_static_field_size )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5281, "assert(" "ik->static_field_size() == _field_info->_static_field_size" ") failed", "sanity"); ::breakpoint(); } } while (0); |
5282 | assert(ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count,do { if (!(ik->nonstatic_oop_map_count() == _field_info-> oop_map_blocks->_nonstatic_oop_map_count)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5283, "assert(" "ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count" ") failed", "sanity"); ::breakpoint(); } } while (0) |
5283 | "sanity")do { if (!(ik->nonstatic_oop_map_count() == _field_info-> oop_map_blocks->_nonstatic_oop_map_count)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5283, "assert(" "ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count" ") failed", "sanity"); ::breakpoint(); } } while (0); |
5284 | |
5285 | assert(ik->is_instance_klass(), "sanity")do { if (!(ik->is_instance_klass())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5285, "assert(" "ik->is_instance_klass()" ") failed", "sanity" ); ::breakpoint(); } } while (0); |
5286 | assert(ik->size_helper() == _field_info->_instance_size, "sanity")do { if (!(ik->size_helper() == _field_info->_instance_size )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5286, "assert(" "ik->size_helper() == _field_info->_instance_size" ") failed", "sanity"); ::breakpoint(); } } while (0); |
5287 | |
5288 | // Fill in information already parsed |
5289 | ik->set_should_verify_class(_need_verify); |
5290 | |
5291 | // Not yet: supers are done below to support the new subtype-checking fields |
5292 | ik->set_nonstatic_field_size(_field_info->_nonstatic_field_size); |
5293 | ik->set_has_nonstatic_fields(_field_info->_has_nonstatic_fields); |
5294 | assert(_fac != NULL, "invariant")do { if (!(_fac != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5294, "assert(" "_fac != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
5295 | ik->set_static_oop_field_count(_fac->count[STATIC_OOP]); |
5296 | |
5297 | // this transfers ownership of a lot of arrays from |
5298 | // the parser onto the InstanceKlass* |
5299 | apply_parsed_class_metadata(ik, _java_fields_count); |
5300 | |
5301 | // can only set dynamic nest-host after static nest information is set |
5302 | if (cl_inst_info.dynamic_nest_host() != NULL__null) { |
5303 | ik->set_nest_host(cl_inst_info.dynamic_nest_host()); |
5304 | } |
5305 | |
5306 | // note that is not safe to use the fields in the parser from this point on |
5307 | assert(NULL == _cp, "invariant")do { if (!(__null == _cp)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5307, "assert(" "__null == _cp" ") failed", "invariant"); :: breakpoint(); } } while (0); |
5308 | assert(NULL == _fields, "invariant")do { if (!(__null == _fields)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5308, "assert(" "__null == _fields" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5309 | assert(NULL == _methods, "invariant")do { if (!(__null == _methods)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5309, "assert(" "__null == _methods" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5310 | assert(NULL == _inner_classes, "invariant")do { if (!(__null == _inner_classes)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5310, "assert(" "__null == _inner_classes" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5311 | assert(NULL == _nest_members, "invariant")do { if (!(__null == _nest_members)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5311, "assert(" "__null == _nest_members" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5312 | assert(NULL == _combined_annotations, "invariant")do { if (!(__null == _combined_annotations)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5312, "assert(" "__null == _combined_annotations" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
5313 | assert(NULL == _record_components, "invariant")do { if (!(__null == _record_components)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5313, "assert(" "__null == _record_components" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5314 | assert(NULL == _permitted_subclasses, "invariant")do { if (!(__null == _permitted_subclasses)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5314, "assert(" "__null == _permitted_subclasses" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
5315 | |
5316 | if (_has_final_method) { |
5317 | ik->set_has_final_method(); |
5318 | } |
5319 | |
5320 | ik->copy_method_ordering(_method_ordering, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5321 | // The InstanceKlass::_methods_jmethod_ids cache |
5322 | // is managed on the assumption that the initial cache |
5323 | // size is equal to the number of methods in the class. If |
5324 | // that changes, then InstanceKlass::idnum_can_increment() |
5325 | // has to be changed accordingly. |
5326 | ik->set_initial_method_idnum(ik->methods()->length()); |
5327 | |
5328 | ik->set_this_class_index(_this_class_index); |
5329 | |
5330 | if (_is_hidden) { |
5331 | // _this_class_index is a CONSTANT_Class entry that refers to this |
5332 | // hidden class itself. If this class needs to refer to its own methods |
5333 | // or fields, it would use a CONSTANT_MethodRef, etc, which would reference |
5334 | // _this_class_index. However, because this class is hidden (it's |
5335 | // not stored in SystemDictionary), _this_class_index cannot be resolved |
5336 | // with ConstantPool::klass_at_impl, which does a SystemDictionary lookup. |
5337 | // Therefore, we must eagerly resolve _this_class_index now. |
5338 | ik->constants()->klass_at_put(_this_class_index, ik); |
5339 | } |
5340 | |
5341 | ik->set_minor_version(_minor_version); |
5342 | ik->set_major_version(_major_version); |
5343 | ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods); |
5344 | ik->set_declares_nonstatic_concrete_methods(_declares_nonstatic_concrete_methods); |
5345 | |
5346 | if (_is_hidden) { |
5347 | ik->set_is_hidden(); |
5348 | } |
5349 | |
5350 | // Set PackageEntry for this_klass |
5351 | oop cl = ik->class_loader(); |
5352 | Handle clh = Handle(THREAD__the_thread__, java_lang_ClassLoader::non_reflection_class_loader(cl)); |
5353 | ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh()); |
5354 | ik->set_package(cld, NULL__null, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5355 | |
5356 | const Array<Method*>* const methods = ik->methods(); |
5357 | assert(methods != NULL, "invariant")do { if (!(methods != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5357, "assert(" "methods != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5358 | const int methods_len = methods->length(); |
5359 | |
5360 | check_methods_for_intrinsics(ik, methods); |
5361 | |
5362 | // Fill in field values obtained by parse_classfile_attributes |
5363 | if (_parsed_annotations->has_any_annotations()) { |
5364 | _parsed_annotations->apply_to(ik); |
5365 | } |
5366 | |
5367 | apply_parsed_class_attributes(ik); |
5368 | |
5369 | // Miranda methods |
5370 | if ((_num_miranda_methods > 0) || |
5371 | // if this class introduced new miranda methods or |
5372 | (_super_klass != NULL__null && _super_klass->has_miranda_methods()) |
5373 | // super class exists and this class inherited miranda methods |
5374 | ) { |
5375 | ik->set_has_miranda_methods(); // then set a flag |
5376 | } |
5377 | |
5378 | // Fill in information needed to compute superclasses. |
5379 | ik->initialize_supers(const_cast<InstanceKlass*>(_super_klass), _transitive_interfaces, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5380 | ik->set_transitive_interfaces(_transitive_interfaces); |
5381 | ik->set_local_interfaces(_local_interfaces); |
5382 | _transitive_interfaces = NULL__null; |
5383 | _local_interfaces = NULL__null; |
5384 | |
5385 | // Initialize itable offset tables |
5386 | klassItable::setup_itable_offset_table(ik); |
5387 | |
5388 | // Compute transitive closure of interfaces this class implements |
5389 | // Do final class setup |
5390 | OopMapBlocksBuilder* oop_map_blocks = _field_info->oop_map_blocks; |
5391 | if (oop_map_blocks->_nonstatic_oop_map_count > 0) { |
5392 | oop_map_blocks->copy(ik->start_of_nonstatic_oop_maps()); |
5393 | } |
5394 | |
5395 | if (_has_contended_fields || _parsed_annotations->is_contended() || |
5396 | ( _super_klass != NULL__null && _super_klass->has_contended_annotations())) { |
5397 | ik->set_has_contended_annotations(true); |
5398 | } |
5399 | |
5400 | // Fill in has_finalizer, has_vanilla_constructor, and layout_helper |
5401 | set_precomputed_flags(ik); |
5402 | |
5403 | // check if this class can access its super class |
5404 | check_super_class_access(ik, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5405 | |
5406 | // check if this class can access its superinterfaces |
5407 | check_super_interface_access(ik, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5408 | |
5409 | // check if this class overrides any final method |
5410 | check_final_method_override(ik, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5411 | |
5412 | // reject static interface methods prior to Java 8 |
5413 | if (ik->is_interface() && _major_version < JAVA_8_VERSION52) { |
5414 | check_illegal_static_method(ik, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5415 | } |
5416 | |
5417 | // Obtain this_klass' module entry |
5418 | ModuleEntry* module_entry = ik->module(); |
5419 | assert(module_entry != NULL, "module_entry should always be set")do { if (!(module_entry != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5419, "assert(" "module_entry != __null" ") failed", "module_entry should always be set" ); ::breakpoint(); } } while (0); |
5420 | |
5421 | // Obtain java.lang.Module |
5422 | Handle module_handle(THREAD__the_thread__, module_entry->module()); |
5423 | |
5424 | // Allocate mirror and initialize static fields |
5425 | // The create_mirror() call will also call compute_modifiers() |
5426 | java_lang_Class::create_mirror(ik, |
5427 | Handle(THREAD__the_thread__, _loader_data->class_loader()), |
5428 | module_handle, |
5429 | _protection_domain, |
5430 | cl_inst_info.class_data(), |
5431 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5432 | |
5433 | assert(_all_mirandas != NULL, "invariant")do { if (!(_all_mirandas != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5433, "assert(" "_all_mirandas != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5434 | |
5435 | // Generate any default methods - default methods are public interface methods |
5436 | // that have a default implementation. This is new with Java 8. |
5437 | if (_has_nonstatic_concrete_methods) { |
5438 | DefaultMethods::generate_default_methods(ik, |
5439 | _all_mirandas, |
5440 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5441 | } |
5442 | |
5443 | // Add read edges to the unnamed modules of the bootstrap and app class loaders. |
5444 | if (changed_by_loadhook && !module_handle.is_null() && module_entry->is_named() && |
5445 | !module_entry->has_default_read_edges()) { |
5446 | if (!module_entry->set_has_default_read_edges()) { |
5447 | // We won a potential race |
5448 | JvmtiExport::add_default_read_edges(module_handle, THREAD__the_thread__); |
5449 | } |
5450 | } |
5451 | |
5452 | ClassLoadingService::notify_class_loaded(ik, false /* not shared class */); |
5453 | |
5454 | if (!is_internal()) { |
5455 | ik->print_class_load_logging(_loader_data, module_entry, _stream); |
5456 | |
5457 | if (ik->minor_version() == JAVA_PREVIEW_MINOR_VERSION65535 && |
5458 | ik->major_version() == JVM_CLASSFILE_MAJOR_VERSION63 && |
5459 | log_is_enabled(Info, class, preview)(LogImpl<(LogTag::_class), (LogTag::_preview), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) { |
5460 | ResourceMark rm; |
5461 | log_info(class, preview)(!(LogImpl<(LogTag::_class), (LogTag::_preview), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG )>::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_class), (LogTag::_preview), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Loading class %s that depends on preview features (class file version %d.65535)", |
5462 | ik->external_name(), JVM_CLASSFILE_MAJOR_VERSION63); |
5463 | } |
5464 | |
5465 | if (log_is_enabled(Debug, class, resolve)(LogImpl<(LogTag::_class), (LogTag::_resolve), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) { |
5466 | ResourceMark rm; |
5467 | // print out the superclass. |
5468 | const char * from = ik->external_name(); |
5469 | if (ik->java_super() != NULL__null) { |
5470 | log_debug(class, resolve)(!(LogImpl<(LogTag::_class), (LogTag::_resolve), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG )>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_class), (LogTag::_resolve), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("%s %s (super)", |
5471 | from, |
5472 | ik->java_super()->external_name()); |
5473 | } |
5474 | // print out each of the interface classes referred to by this class. |
5475 | const Array<InstanceKlass*>* const local_interfaces = ik->local_interfaces(); |
5476 | if (local_interfaces != NULL__null) { |
5477 | const int length = local_interfaces->length(); |
5478 | for (int i = 0; i < length; i++) { |
5479 | const InstanceKlass* const k = local_interfaces->at(i); |
5480 | const char * to = k->external_name(); |
5481 | log_debug(class, resolve)(!(LogImpl<(LogTag::_class), (LogTag::_resolve), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG )>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_class), (LogTag::_resolve), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("%s %s (interface)", from, to); |
5482 | } |
5483 | } |
5484 | } |
5485 | } |
5486 | |
5487 | JFR_ONLY(INIT_ID(ik);)JfrTraceId::assign(ik); |
5488 | |
5489 | // If we reach here, all is well. |
5490 | // Now remove the InstanceKlass* from the _klass_to_deallocate field |
5491 | // in order for it to not be destroyed in the ClassFileParser destructor. |
5492 | set_klass_to_deallocate(NULL__null); |
5493 | |
5494 | // it's official |
5495 | set_klass(ik); |
5496 | |
5497 | debug_only(ik->verify();)ik->verify(); |
5498 | } |
5499 | |
5500 | void ClassFileParser::update_class_name(Symbol* new_class_name) { |
5501 | // Decrement the refcount in the old name, since we're clobbering it. |
5502 | _class_name->decrement_refcount(); |
5503 | |
5504 | _class_name = new_class_name; |
5505 | // Increment the refcount of the new name. |
5506 | // Now the ClassFileParser owns this name and will decrement in |
5507 | // the destructor. |
5508 | _class_name->increment_refcount(); |
5509 | } |
5510 | |
5511 | static bool relax_format_check_for(ClassLoaderData* loader_data) { |
5512 | bool trusted = loader_data->is_boot_class_loader_data() || |
5513 | loader_data->is_platform_class_loader_data(); |
5514 | bool need_verify = |
5515 | // verifyAll |
5516 | (BytecodeVerificationLocal && BytecodeVerificationRemote) || |
5517 | // verifyRemote |
5518 | (!BytecodeVerificationLocal && BytecodeVerificationRemote && !trusted); |
5519 | return !need_verify; |
5520 | } |
5521 | |
5522 | ClassFileParser::ClassFileParser(ClassFileStream* stream, |
5523 | Symbol* name, |
5524 | ClassLoaderData* loader_data, |
5525 | const ClassLoadInfo* cl_info, |
5526 | Publicity pub_level, |
5527 | TRAPSJavaThread* __the_thread__) : |
5528 | _stream(stream), |
5529 | _class_name(NULL__null), |
5530 | _loader_data(loader_data), |
5531 | _is_hidden(cl_info->is_hidden()), |
5532 | _can_access_vm_annotations(cl_info->can_access_vm_annotations()), |
5533 | _orig_cp_size(0), |
5534 | _super_klass(), |
5535 | _cp(NULL__null), |
5536 | _fields(NULL__null), |
5537 | _methods(NULL__null), |
5538 | _inner_classes(NULL__null), |
5539 | _nest_members(NULL__null), |
5540 | _nest_host(0), |
5541 | _permitted_subclasses(NULL__null), |
5542 | _record_components(NULL__null), |
5543 | _local_interfaces(NULL__null), |
5544 | _transitive_interfaces(NULL__null), |
5545 | _combined_annotations(NULL__null), |
5546 | _class_annotations(NULL__null), |
5547 | _class_type_annotations(NULL__null), |
5548 | _fields_annotations(NULL__null), |
5549 | _fields_type_annotations(NULL__null), |
5550 | _klass(NULL__null), |
5551 | _klass_to_deallocate(NULL__null), |
5552 | _parsed_annotations(NULL__null), |
5553 | _fac(NULL__null), |
5554 | _field_info(NULL__null), |
5555 | _method_ordering(NULL__null), |
5556 | _all_mirandas(NULL__null), |
5557 | _vtable_size(0), |
5558 | _itable_size(0), |
5559 | _num_miranda_methods(0), |
5560 | _rt(REF_NONE), |
5561 | _protection_domain(cl_info->protection_domain()), |
5562 | _access_flags(), |
5563 | _pub_level(pub_level), |
5564 | _bad_constant_seen(0), |
5565 | _synthetic_flag(false), |
5566 | _sde_length(false), |
5567 | _sde_buffer(NULL__null), |
5568 | _sourcefile_index(0), |
5569 | _generic_signature_index(0), |
5570 | _major_version(0), |
5571 | _minor_version(0), |
5572 | _this_class_index(0), |
5573 | _super_class_index(0), |
5574 | _itfs_len(0), |
5575 | _java_fields_count(0), |
5576 | _need_verify(false), |
5577 | _relax_verify(false), |
5578 | _has_nonstatic_concrete_methods(false), |
5579 | _declares_nonstatic_concrete_methods(false), |
5580 | _has_final_method(false), |
5581 | _has_contended_fields(false), |
5582 | _has_finalizer(false), |
5583 | _has_empty_finalizer(false), |
5584 | _has_vanilla_constructor(false), |
5585 | _max_bootstrap_specifier_index(-1) { |
5586 | |
5587 | _class_name = name != NULL__null ? name : vmSymbols::unknown_class_name(); |
5588 | _class_name->increment_refcount(); |
5589 | |
5590 | assert(_loader_data != NULL, "invariant")do { if (!(_loader_data != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5590, "assert(" "_loader_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5591 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5591, "assert(" "stream != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
5592 | assert(_stream != NULL, "invariant")do { if (!(_stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5592, "assert(" "_stream != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5593 | assert(_stream->buffer() == _stream->current(), "invariant")do { if (!(_stream->buffer() == _stream->current())) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5593, "assert(" "_stream->buffer() == _stream->current()" ") failed", "invariant"); ::breakpoint(); } } while (0); |
5594 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5594, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5595 | assert(0 == _access_flags.as_int(), "invariant")do { if (!(0 == _access_flags.as_int())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5595, "assert(" "0 == _access_flags.as_int()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5596 | |
5597 | // Figure out whether we can skip format checking (matching classic VM behavior) |
5598 | if (DumpSharedSpaces) { |
5599 | // verify == true means it's a 'remote' class (i.e., non-boot class) |
5600 | // Verification decision is based on BytecodeVerificationRemote flag |
5601 | // for those classes. |
5602 | _need_verify = (stream->need_verify()) ? BytecodeVerificationRemote : |
5603 | BytecodeVerificationLocal; |
5604 | } |
5605 | else { |
5606 | _need_verify = Verifier::should_verify_for(_loader_data->class_loader(), |
5607 | stream->need_verify()); |
5608 | } |
5609 | |
5610 | // synch back verification state to stream |
5611 | stream->set_verify(_need_verify); |
5612 | |
5613 | // Check if verification needs to be relaxed for this class file |
5614 | // Do not restrict it to jdk1.0 or jdk1.1 to maintain backward compatibility (4982376) |
5615 | _relax_verify = relax_format_check_for(_loader_data); |
5616 | |
5617 | parse_stream(stream, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5618 | |
5619 | post_process_parsed_stream(stream, _cp, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5620 | } |
5621 | |
5622 | void ClassFileParser::clear_class_metadata() { |
5623 | // metadata created before the instance klass is created. Must be |
5624 | // deallocated if classfile parsing returns an error. |
5625 | _cp = NULL__null; |
5626 | _fields = NULL__null; |
5627 | _methods = NULL__null; |
5628 | _inner_classes = NULL__null; |
5629 | _nest_members = NULL__null; |
5630 | _permitted_subclasses = NULL__null; |
5631 | _combined_annotations = NULL__null; |
5632 | _class_annotations = _class_type_annotations = NULL__null; |
5633 | _fields_annotations = _fields_type_annotations = NULL__null; |
5634 | _record_components = NULL__null; |
5635 | } |
5636 | |
5637 | // Destructor to clean up |
5638 | ClassFileParser::~ClassFileParser() { |
5639 | _class_name->decrement_refcount(); |
5640 | |
5641 | if (_cp != NULL__null) { |
5642 | MetadataFactory::free_metadata(_loader_data, _cp); |
5643 | } |
5644 | if (_fields != NULL__null) { |
5645 | MetadataFactory::free_array<u2>(_loader_data, _fields); |
5646 | } |
5647 | |
5648 | if (_methods != NULL__null) { |
5649 | // Free methods |
5650 | InstanceKlass::deallocate_methods(_loader_data, _methods); |
5651 | } |
5652 | |
5653 | // beware of the Universe::empty_blah_array!! |
5654 | if (_inner_classes != NULL__null && _inner_classes != Universe::the_empty_short_array()) { |
5655 | MetadataFactory::free_array<u2>(_loader_data, _inner_classes); |
5656 | } |
5657 | |
5658 | if (_nest_members != NULL__null && _nest_members != Universe::the_empty_short_array()) { |
5659 | MetadataFactory::free_array<u2>(_loader_data, _nest_members); |
5660 | } |
5661 | |
5662 | if (_record_components != NULL__null) { |
5663 | InstanceKlass::deallocate_record_components(_loader_data, _record_components); |
5664 | } |
5665 | |
5666 | if (_permitted_subclasses != NULL__null && _permitted_subclasses != Universe::the_empty_short_array()) { |
5667 | MetadataFactory::free_array<u2>(_loader_data, _permitted_subclasses); |
5668 | } |
5669 | |
5670 | // Free interfaces |
5671 | InstanceKlass::deallocate_interfaces(_loader_data, _super_klass, |
5672 | _local_interfaces, _transitive_interfaces); |
5673 | |
5674 | if (_combined_annotations != NULL__null) { |
5675 | // After all annotations arrays have been created, they are installed into the |
5676 | // Annotations object that will be assigned to the InstanceKlass being created. |
5677 | |
5678 | // Deallocate the Annotations object and the installed annotations arrays. |
5679 | _combined_annotations->deallocate_contents(_loader_data); |
5680 | |
5681 | // If the _combined_annotations pointer is non-NULL, |
5682 | // then the other annotations fields should have been cleared. |
5683 | assert(_class_annotations == NULL, "Should have been cleared")do { if (!(_class_annotations == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5683, "assert(" "_class_annotations == __null" ") failed", "Should have been cleared" ); ::breakpoint(); } } while (0); |
5684 | assert(_class_type_annotations == NULL, "Should have been cleared")do { if (!(_class_type_annotations == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5684, "assert(" "_class_type_annotations == __null" ") failed" , "Should have been cleared"); ::breakpoint(); } } while (0); |
5685 | assert(_fields_annotations == NULL, "Should have been cleared")do { if (!(_fields_annotations == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5685, "assert(" "_fields_annotations == __null" ") failed", "Should have been cleared"); ::breakpoint(); } } while (0); |
5686 | assert(_fields_type_annotations == NULL, "Should have been cleared")do { if (!(_fields_type_annotations == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5686, "assert(" "_fields_type_annotations == __null" ") failed" , "Should have been cleared"); ::breakpoint(); } } while (0); |
5687 | } else { |
5688 | // If the annotations arrays were not installed into the Annotations object, |
5689 | // then they have to be deallocated explicitly. |
5690 | MetadataFactory::free_array<u1>(_loader_data, _class_annotations); |
5691 | MetadataFactory::free_array<u1>(_loader_data, _class_type_annotations); |
5692 | Annotations::free_contents(_loader_data, _fields_annotations); |
5693 | Annotations::free_contents(_loader_data, _fields_type_annotations); |
5694 | } |
5695 | |
5696 | clear_class_metadata(); |
5697 | _transitive_interfaces = NULL__null; |
5698 | _local_interfaces = NULL__null; |
5699 | |
5700 | // deallocate the klass if already created. Don't directly deallocate, but add |
5701 | // to the deallocate list so that the klass is removed from the CLD::_klasses list |
5702 | // at a safepoint. |
5703 | if (_klass_to_deallocate != NULL__null) { |
5704 | _loader_data->add_to_deallocate_list(_klass_to_deallocate); |
5705 | } |
5706 | } |
5707 | |
5708 | void ClassFileParser::parse_stream(const ClassFileStream* const stream, |
5709 | TRAPSJavaThread* __the_thread__) { |
5710 | |
5711 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5711, "assert(" "stream != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
5712 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5712, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5713 | |
5714 | // BEGIN STREAM PARSING |
5715 | stream->guarantee_more(8, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // magic, major, minor |
5716 | // Magic value |
5717 | const u4 magic = stream->get_u4_fast(); |
5718 | guarantee_property(magic == JAVA_CLASSFILE_MAGIC0xCAFEBABE, |
5719 | "Incompatible magic value %u in class file %s", |
5720 | magic, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5721 | |
5722 | // Version numbers |
5723 | _minor_version = stream->get_u2_fast(); |
5724 | _major_version = stream->get_u2_fast(); |
5725 | |
5726 | // Check version numbers - we check this even with verifier off |
5727 | verify_class_version(_major_version, _minor_version, _class_name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5728 | |
5729 | stream->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // length, first cp tag |
5730 | u2 cp_size = stream->get_u2_fast(); |
5731 | |
5732 | guarantee_property( |
5733 | cp_size >= 1, "Illegal constant pool size %u in class file %s", |
5734 | cp_size, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5735 | |
5736 | _orig_cp_size = cp_size; |
5737 | if (is_hidden()) { // Add a slot for hidden class name. |
5738 | cp_size++; |
5739 | } |
5740 | |
5741 | _cp = ConstantPool::allocate(_loader_data, |
5742 | cp_size, |
5743 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5744 | |
5745 | ConstantPool* const cp = _cp; |
5746 | |
5747 | parse_constant_pool(stream, cp, _orig_cp_size, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5748 | |
5749 | assert(cp_size == (const u2)cp->length(), "invariant")do { if (!(cp_size == (const u2)cp->length())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5749, "assert(" "cp_size == (const u2)cp->length()" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
5750 | |
5751 | // ACCESS FLAGS |
5752 | stream->guarantee_more(8, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // flags, this_class, super_class, infs_len |
5753 | |
5754 | // Access flags |
5755 | jint flags; |
5756 | // JVM_ACC_MODULE is defined in JDK-9 and later. |
5757 | if (_major_version >= JAVA_9_VERSION53) { |
5758 | flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | JVM_ACC_MODULE); |
5759 | } else { |
5760 | flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ); |
5761 | } |
5762 | |
5763 | if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION50) { |
5764 | // Set abstract bit for old class files for backward compatibility |
5765 | flags |= JVM_ACC_ABSTRACT; |
5766 | } |
5767 | |
5768 | verify_legal_class_modifiers(flags, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5769 | |
5770 | short bad_constant = class_bad_constant_seen(); |
5771 | if (bad_constant != 0) { |
5772 | // Do not throw CFE until after the access_flags are checked because if |
5773 | // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE. |
5774 | classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD__the_thread__); |
5775 | return; |
5776 | } |
5777 | |
5778 | _access_flags.set_flags(flags); |
5779 | |
5780 | // This class and superclass |
5781 | _this_class_index = stream->get_u2_fast(); |
5782 | check_property( |
5783 | valid_cp_range(_this_class_index, cp_size) && |
5784 | cp->tag_at(_this_class_index).is_unresolved_klass(), |
5785 | "Invalid this class index %u in constant pool in class file %s", |
5786 | _this_class_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5787 | |
5788 | Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index); |
5789 | assert(class_name_in_cp != NULL, "class_name can't be null")do { if (!(class_name_in_cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5789, "assert(" "class_name_in_cp != __null" ") failed", "class_name can't be null" ); ::breakpoint(); } } while (0); |
5790 | |
5791 | // Don't need to check whether this class name is legal or not. |
5792 | // It has been checked when constant pool is parsed. |
5793 | // However, make sure it is not an array type. |
5794 | if (_need_verify) { |
5795 | guarantee_property(class_name_in_cp->char_at(0) != JVM_SIGNATURE_ARRAY, |
5796 | "Bad class name in class file %s", |
5797 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5798 | } |
5799 | |
5800 | #ifdef ASSERT1 |
5801 | // Basic sanity checks |
5802 | if (_is_hidden) { |
5803 | assert(_class_name != vmSymbols::unknown_class_name(), "hidden classes should have a special name")do { if (!(_class_name != vmSymbols::unknown_class_name())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5803, "assert(" "_class_name != vmSymbols::unknown_class_name()" ") failed", "hidden classes should have a special name"); :: breakpoint(); } } while (0); |
5804 | } |
5805 | #endif |
5806 | |
5807 | // Update the _class_name as needed depending on whether this is a named, un-named, or hidden class. |
5808 | |
5809 | if (_is_hidden) { |
5810 | assert(_class_name != NULL, "Unexpected null _class_name")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5810, "assert(" "_class_name != __null" ") failed", "Unexpected null _class_name" ); ::breakpoint(); } } while (0); |
5811 | #ifdef ASSERT1 |
5812 | if (_need_verify) { |
5813 | verify_legal_class_name(_class_name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5814 | } |
5815 | #endif |
5816 | |
5817 | } else { |
5818 | // Check if name in class file matches given name |
5819 | if (_class_name != class_name_in_cp) { |
5820 | if (_class_name != vmSymbols::unknown_class_name()) { |
5821 | ResourceMark rm(THREAD__the_thread__); |
5822 | Exceptions::fthrow(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5822, |
5823 | vmSymbols::java_lang_NoClassDefFoundError(), |
5824 | "%s (wrong name: %s)", |
5825 | class_name_in_cp->as_C_string(), |
5826 | _class_name->as_C_string() |
5827 | ); |
5828 | return; |
5829 | } else { |
5830 | // The class name was not known by the caller so we set it from |
5831 | // the value in the CP. |
5832 | update_class_name(class_name_in_cp); |
5833 | } |
5834 | // else nothing to do: the expected class name matches what is in the CP |
5835 | } |
5836 | } |
5837 | |
5838 | // Verification prevents us from creating names with dots in them, this |
5839 | // asserts that that's the case. |
5840 | assert(is_internal_format(_class_name), "external class name format used internally")do { if (!(is_internal_format(_class_name))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5840, "assert(" "is_internal_format(_class_name)" ") failed" , "external class name format used internally"); ::breakpoint (); } } while (0); |
5841 | |
5842 | if (!is_internal()) { |
5843 | LogTarget(Debug, class, preorder)LogTargetImpl<LogLevel::Debug, (LogTag::_class), (LogTag:: _preorder), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG), (LogTag::__NO_TAG)> lt; |
5844 | if (lt.is_enabled()){ |
5845 | ResourceMark rm(THREAD__the_thread__); |
5846 | LogStream ls(lt); |
5847 | ls.print("%s", _class_name->as_klass_external_name()); |
5848 | if (stream->source() != NULL__null) { |
5849 | ls.print(" source: %s", stream->source()); |
5850 | } |
5851 | ls.cr(); |
5852 | } |
5853 | } |
5854 | |
5855 | // SUPERKLASS |
5856 | _super_class_index = stream->get_u2_fast(); |
5857 | _super_klass = parse_super_class(cp, |
5858 | _super_class_index, |
5859 | _need_verify, |
5860 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5861 | |
5862 | // Interfaces |
5863 | _itfs_len = stream->get_u2_fast(); |
5864 | parse_interfaces(stream, |
5865 | _itfs_len, |
5866 | cp, |
5867 | &_has_nonstatic_concrete_methods, |
5868 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5869 | |
5870 | assert(_local_interfaces != NULL, "invariant")do { if (!(_local_interfaces != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5870, "assert(" "_local_interfaces != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5871 | |
5872 | // Fields (offsets are filled in later) |
5873 | _fac = new FieldAllocationCount(); |
5874 | parse_fields(stream, |
5875 | _access_flags.is_interface(), |
5876 | _fac, |
5877 | cp, |
5878 | cp_size, |
5879 | &_java_fields_count, |
5880 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5881 | |
5882 | assert(_fields != NULL, "invariant")do { if (!(_fields != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5882, "assert(" "_fields != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5883 | |
5884 | // Methods |
5885 | AccessFlags promoted_flags; |
5886 | parse_methods(stream, |
5887 | _access_flags.is_interface(), |
5888 | &promoted_flags, |
5889 | &_has_final_method, |
5890 | &_declares_nonstatic_concrete_methods, |
5891 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5892 | |
5893 | assert(_methods != NULL, "invariant")do { if (!(_methods != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5893, "assert(" "_methods != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5894 | |
5895 | // promote flags from parse_methods() to the klass' flags |
5896 | _access_flags.add_promoted_flags(promoted_flags.as_int()); |
5897 | |
5898 | if (_declares_nonstatic_concrete_methods) { |
5899 | _has_nonstatic_concrete_methods = true; |
5900 | } |
5901 | |
5902 | // Additional attributes/annotations |
5903 | _parsed_annotations = new ClassAnnotationCollector(); |
5904 | parse_classfile_attributes(stream, cp, _parsed_annotations, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5905 | |
5906 | assert(_inner_classes != NULL, "invariant")do { if (!(_inner_classes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5906, "assert(" "_inner_classes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5907 | |
5908 | // Finalize the Annotations metadata object, |
5909 | // now that all annotation arrays have been created. |
5910 | create_combined_annotations(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5911 | |
5912 | // Make sure this is the end of class file stream |
5913 | guarantee_property(stream->at_eos(), |
5914 | "Extra bytes at the end of class file %s", |
5915 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5916 | |
5917 | // all bytes in stream read and parsed |
5918 | } |
5919 | |
5920 | void ClassFileParser::mangle_hidden_class_name(InstanceKlass* const ik) { |
5921 | ResourceMark rm; |
5922 | // Construct hidden name from _class_name, "+", and &ik. Note that we can't |
5923 | // use a '/' because that confuses finding the class's package. Also, can't |
5924 | // use an illegal char such as ';' because that causes serialization issues |
5925 | // and issues with hidden classes that create their own hidden classes. |
5926 | char addr_buf[20]; |
5927 | if (DumpSharedSpaces) { |
5928 | // We want stable names for the archived hidden classes (only for static |
5929 | // archive for now). Spaces under default_SharedBaseAddress() will be |
5930 | // occupied by the archive at run time, so we know that no dynamically |
5931 | // loaded InstanceKlass will be placed under there. |
5932 | static volatile size_t counter = 0; |
5933 | Atomic::cmpxchg(&counter, (size_t)0, Arguments::default_SharedBaseAddress()); // initialize it |
5934 | size_t new_id = Atomic::add(&counter, (size_t)1); |
5935 | jio_snprintf(addr_buf, 20, SIZE_FORMAT_HEX"0x%" "l" "x", new_id); |
5936 | } else { |
5937 | jio_snprintf(addr_buf, 20, INTPTR_FORMAT"0x%016" "l" "x", p2i(ik)); |
5938 | } |
5939 | size_t new_name_len = _class_name->utf8_length() + 2 + strlen(addr_buf); |
5940 | char* new_name = NEW_RESOURCE_ARRAY(char, new_name_len)(char*) resource_allocate_bytes((new_name_len) * sizeof(char) ); |
5941 | jio_snprintf(new_name, new_name_len, "%s+%s", |
5942 | _class_name->as_C_string(), addr_buf); |
5943 | update_class_name(SymbolTable::new_symbol(new_name)); |
5944 | |
5945 | // Add a Utf8 entry containing the hidden name. |
5946 | assert(_class_name != NULL, "Unexpected null _class_name")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5946, "assert(" "_class_name != __null" ") failed", "Unexpected null _class_name" ); ::breakpoint(); } } while (0); |
5947 | int hidden_index = _orig_cp_size; // this is an extra slot we added |
5948 | _cp->symbol_at_put(hidden_index, _class_name); |
5949 | |
5950 | // Update this_class_index's slot in the constant pool with the new Utf8 entry. |
5951 | // We have to update the resolved_klass_index and the name_index together |
5952 | // so extract the existing resolved_klass_index first. |
5953 | CPKlassSlot cp_klass_slot = _cp->klass_slot_at(_this_class_index); |
5954 | int resolved_klass_index = cp_klass_slot.resolved_klass_index(); |
5955 | _cp->unresolved_klass_at_put(_this_class_index, hidden_index, resolved_klass_index); |
5956 | assert(_cp->klass_slot_at(_this_class_index).name_index() == _orig_cp_size,do { if (!(_cp->klass_slot_at(_this_class_index).name_index () == _orig_cp_size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5957, "assert(" "_cp->klass_slot_at(_this_class_index).name_index() == _orig_cp_size" ") failed", "Bad name_index"); ::breakpoint(); } } while (0) |
5957 | "Bad name_index")do { if (!(_cp->klass_slot_at(_this_class_index).name_index () == _orig_cp_size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5957, "assert(" "_cp->klass_slot_at(_this_class_index).name_index() == _orig_cp_size" ") failed", "Bad name_index"); ::breakpoint(); } } while (0); |
5958 | } |
5959 | |
5960 | void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const stream, |
5961 | ConstantPool* cp, |
5962 | TRAPSJavaThread* __the_thread__) { |
5963 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5963, "assert(" "stream != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
5964 | assert(stream->at_eos(), "invariant")do { if (!(stream->at_eos())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5964, "assert(" "stream->at_eos()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5965 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5965, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
5966 | assert(_loader_data != NULL, "invariant")do { if (!(_loader_data != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5966, "assert(" "_loader_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
5967 | |
5968 | if (_class_name == vmSymbols::java_lang_Object()) { |
5969 | check_property(_local_interfaces == Universe::the_empty_instance_klass_array(), |
5970 | "java.lang.Object cannot implement an interface in class file %s", |
5971 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5972 | } |
5973 | // We check super class after class file is parsed and format is checked |
5974 | if (_super_class_index > 0 && NULL__null == _super_klass) { |
5975 | Symbol* const super_class_name = cp->klass_name_at(_super_class_index); |
5976 | if (_access_flags.is_interface()) { |
5977 | // Before attempting to resolve the superclass, check for class format |
5978 | // errors not checked yet. |
5979 | guarantee_property(super_class_name == vmSymbols::java_lang_Object(), |
5980 | "Interfaces must have java.lang.Object as superclass in class file %s", |
5981 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5982 | } |
5983 | Handle loader(THREAD__the_thread__, _loader_data->class_loader()); |
5984 | _super_klass = (const InstanceKlass*) |
5985 | SystemDictionary::resolve_super_or_fail(_class_name, |
5986 | super_class_name, |
5987 | loader, |
5988 | _protection_domain, |
5989 | true, |
5990 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
5991 | } |
5992 | |
5993 | if (_super_klass != NULL__null) { |
5994 | if (_super_klass->has_nonstatic_concrete_methods()) { |
5995 | _has_nonstatic_concrete_methods = true; |
5996 | } |
5997 | |
5998 | if (_super_klass->is_interface()) { |
5999 | classfile_icce_error("class %s has interface %s as super class", _super_klass, THREAD__the_thread__); |
6000 | return; |
6001 | } |
6002 | } |
6003 | |
6004 | // Compute the transitive list of all unique interfaces implemented by this class |
6005 | _transitive_interfaces = |
6006 | compute_transitive_interfaces(_super_klass, |
6007 | _local_interfaces, |
6008 | _loader_data, |
6009 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
6010 | |
6011 | assert(_transitive_interfaces != NULL, "invariant")do { if (!(_transitive_interfaces != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6011, "assert(" "_transitive_interfaces != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
6012 | |
6013 | // sort methods |
6014 | _method_ordering = sort_methods(_methods); |
6015 | |
6016 | _all_mirandas = new GrowableArray<Method*>(20); |
6017 | |
6018 | Handle loader(THREAD__the_thread__, _loader_data->class_loader()); |
6019 | klassVtable::compute_vtable_size_and_num_mirandas(&_vtable_size, |
6020 | &_num_miranda_methods, |
6021 | _all_mirandas, |
6022 | _super_klass, |
6023 | _methods, |
6024 | _access_flags, |
6025 | _major_version, |
6026 | loader, |
6027 | _class_name, |
6028 | _local_interfaces); |
6029 | |
6030 | // Size of Java itable (in words) |
6031 | _itable_size = _access_flags.is_interface() ? 0 : |
6032 | klassItable::compute_itable_size(_transitive_interfaces); |
6033 | |
6034 | assert(_fac != NULL, "invariant")do { if (!(_fac != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6034, "assert(" "_fac != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
6035 | assert(_parsed_annotations != NULL, "invariant")do { if (!(_parsed_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6035, "assert(" "_parsed_annotations != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
6036 | |
6037 | _field_info = new FieldLayoutInfo(); |
6038 | FieldLayoutBuilder lb(class_name(), super_klass(), _cp, _fields, |
6039 | _parsed_annotations->is_contended(), _field_info); |
6040 | lb.build_layout(); |
6041 | |
6042 | // Compute reference typ |
6043 | _rt = (NULL__null ==_super_klass) ? REF_NONE : _super_klass->reference_type(); |
6044 | |
6045 | } |
6046 | |
6047 | void ClassFileParser::set_klass(InstanceKlass* klass) { |
6048 | |
6049 | #ifdef ASSERT1 |
6050 | if (klass != NULL__null) { |
6051 | assert(NULL == _klass, "leaking?")do { if (!(__null == _klass)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6051, "assert(" "__null == _klass" ") failed", "leaking?"); ::breakpoint(); } } while (0); |
6052 | } |
6053 | #endif |
6054 | |
6055 | _klass = klass; |
6056 | } |
6057 | |
6058 | void ClassFileParser::set_klass_to_deallocate(InstanceKlass* klass) { |
6059 | |
6060 | #ifdef ASSERT1 |
6061 | if (klass != NULL__null) { |
6062 | assert(NULL == _klass_to_deallocate, "leaking?")do { if (!(__null == _klass_to_deallocate)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6062, "assert(" "__null == _klass_to_deallocate" ") failed" , "leaking?"); ::breakpoint(); } } while (0); |
6063 | } |
6064 | #endif |
6065 | |
6066 | _klass_to_deallocate = klass; |
6067 | } |
6068 | |
6069 | // Caller responsible for ResourceMark |
6070 | // clone stream with rewound position |
6071 | const ClassFileStream* ClassFileParser::clone_stream() const { |
6072 | assert(_stream != NULL, "invariant")do { if (!(_stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6072, "assert(" "_stream != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
6073 | |
6074 | return _stream->clone(); |
6075 | } |
6076 | // ---------------------------------------------------------------------------- |
6077 | // debugging |
6078 | |
6079 | #ifdef ASSERT1 |
6080 | |
6081 | // return true if class_name contains no '.' (internal format is '/') |
6082 | bool ClassFileParser::is_internal_format(Symbol* class_name) { |
6083 | if (class_name != NULL__null) { |
6084 | ResourceMark rm; |
6085 | char* name = class_name->as_C_string(); |
6086 | return strchr(name, JVM_SIGNATURE_DOT) == NULL__null; |
6087 | } else { |
6088 | return true; |
6089 | } |
6090 | } |
6091 | |
6092 | #endif |