| File: | jdk/src/hotspot/share/classfile/classFileParser.cpp |
| Warning: | line 1863, column 17 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(); |
Value stored to 'cp_size' during its initialization is never read | |
| 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(); |
| 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 |