< prev index next >

src/hotspot/share/classfile/classFileParser.cpp

Print this page

        

*** 124,135 **** #define JAVA_12_VERSION 56 #define JAVA_13_VERSION 57 void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { ! assert((bad_constant == JVM_CONSTANT_Module || ! bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION, "Unexpected bad constant pool entry"); if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant; } void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream, --- 124,134 ---- #define JAVA_12_VERSION 56 #define JAVA_13_VERSION 57 void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { ! assert((bad_constant == 19 || bad_constant == 20) && _major_version >= JAVA_9_VERSION, "Unexpected bad constant pool entry"); if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant; } void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
*** 342,353 **** } else { cp->symbol_at_put(index, result); } break; } ! case JVM_CONSTANT_Module: ! case JVM_CONSTANT_Package: { // Record that an error occurred in these two cases but keep parsing so // that ACC_Module can be checked for in the access_flags. Need to // throw NoClassDefFoundError in that case. if (_major_version >= JAVA_9_VERSION) { cfs->guarantee_more(3, CHECK); --- 341,352 ---- } else { cp->symbol_at_put(index, result); } break; } ! case 19: ! case 20: { // Record that an error occurred in these two cases but keep parsing so // that ACC_Module can be checked for in the access_flags. Need to // throw NoClassDefFoundError in that case. if (_major_version >= JAVA_9_VERSION) { cfs->guarantee_more(3, CHECK);
*** 1088,1098 **** : _location(location), _annotations_present(0) { assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, ""); } // If this annotation name has an ID, report it (or _none). ! ID annotation_index(const ClassLoaderData* loader_data, const Symbol* name); // Set the annotation name: void set_annotation(ID id) { assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); _annotations_present |= nth_bit((int)id); } --- 1087,1097 ---- : _location(location), _annotations_present(0) { assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, ""); } // If this annotation name has an ID, report it (or _none). ! ID annotation_index(const ClassLoaderData* loader_data, const Symbol* name, const bool can_access_vm_annotations); // Set the annotation name: void set_annotation(ID id) { assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); _annotations_present |= nth_bit((int)id); }
*** 1221,1230 **** --- 1220,1230 ---- // Sift through annotations, looking for those significant to the VM: static void parse_annotations(const ConstantPool* const cp, const u1* buffer, int limit, AnnotationCollector* coll, ClassLoaderData* loader_data, + const bool can_access_vm_annotations, TRAPS) { assert(cp != NULL, "invariant"); assert(buffer != NULL, "invariant"); assert(coll != NULL, "invariant");
*** 1266,1276 **** member = check_symbol_at(cp, member_index); if (member == NULL) break; // invalid member name } // Here is where parsing particular annotations will take place. ! AnnotationCollector::ID id = coll->annotation_index(loader_data, aname); if (AnnotationCollector::_unknown == id) continue; coll->set_annotation(id); if (AnnotationCollector::_jdk_internal_vm_annotation_Contended == id) { // @Contended can optionally specify the contention group. --- 1266,1276 ---- member = check_symbol_at(cp, member_index); if (member == NULL) break; // invalid member name } // Here is where parsing particular annotations will take place. ! AnnotationCollector::ID id = coll->annotation_index(loader_data, aname, can_access_vm_annotations); if (AnnotationCollector::_unknown == id) continue; coll->set_annotation(id); if (AnnotationCollector::_jdk_internal_vm_annotation_Contended == id) { // @Contended can optionally specify the contention group.
*** 1392,1401 **** --- 1392,1402 ---- parse_annotations(cp, runtime_visible_annotations, runtime_visible_annotations_length, parsed_annotations, _loader_data, + _can_access_vm_annotations, CHECK); cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { if (runtime_invisible_annotations_exists) { classfile_parse_error(
*** 2051,2066 **** name->as_C_string(), _class_name->as_C_string(), sig->as_C_string()); } AnnotationCollector::ID AnnotationCollector::annotation_index(const ClassLoaderData* loader_data, ! const Symbol* name) { const vmSymbols::SID sid = vmSymbols::find_sid(name); // Privileged code can use all annotations. Other code silently drops some. const bool privileged = loader_data->is_the_null_class_loader_data() || loader_data->is_platform_class_loader_data() || ! loader_data->is_unsafe_anonymous(); switch (sid) { case vmSymbols::VM_SYMBOL_ENUM_NAME(reflect_CallerSensitive_signature): { if (_location != _in_method) break; // only allow for methods if (!privileged) break; // only allow in privileged code return _method_CallerSensitive; --- 2052,2069 ---- name->as_C_string(), _class_name->as_C_string(), sig->as_C_string()); } AnnotationCollector::ID AnnotationCollector::annotation_index(const ClassLoaderData* loader_data, ! const Symbol* name, ! const bool can_access_vm_annotations) { const vmSymbols::SID sid = vmSymbols::find_sid(name); // Privileged code can use all annotations. Other code silently drops some. const bool privileged = loader_data->is_the_null_class_loader_data() || loader_data->is_platform_class_loader_data() || ! loader_data->is_shortlived() || ! can_access_vm_annotations; switch (sid) { case vmSymbols::VM_SYMBOL_ENUM_NAME(reflect_CallerSensitive_signature): { if (_location != _in_method) break; // only allow for methods if (!privileged) break; // only allow in privileged code return _method_CallerSensitive;
*** 2675,2684 **** --- 2678,2688 ---- parse_annotations(cp, runtime_visible_annotations, runtime_visible_annotations_length, &parsed_annotations, _loader_data, + _can_access_vm_annotations, CHECK_NULL); cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { if (runtime_invisible_annotations_exists) { classfile_parse_error(
*** 3437,3446 **** --- 3441,3451 ---- parse_annotations(cp, runtime_visible_annotations, runtime_visible_annotations_length, parsed_annotations, _loader_data, + _can_access_vm_annotations, CHECK); cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (tag == vmSymbols::tag_runtime_invisible_annotations()) { if (runtime_invisible_annotations_exists) { classfile_parse_error(
*** 5423,5441 **** } // CheckIntrinsics #endif // ASSERT } } ! InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, TRAPS) { if (_klass != NULL) { return _klass; } InstanceKlass* const ik = InstanceKlass::allocate_instance_klass(*this, CHECK_NULL); ! fill_instance_klass(ik, changed_by_loadhook, CHECK_NULL); assert(_klass == ik, "invariant"); if (ik->should_store_fingerprint()) { --- 5428,5449 ---- } // CheckIntrinsics #endif // ASSERT } } ! InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, ! InstanceKlass* dynamic_nest_host, ! Handle classData, ! TRAPS) { if (_klass != NULL) { return _klass; } InstanceKlass* const ik = InstanceKlass::allocate_instance_klass(*this, CHECK_NULL); ! fill_instance_klass(ik, changed_by_loadhook, dynamic_nest_host, classData, CHECK_NULL); assert(_klass == ik, "invariant"); if (ik->should_store_fingerprint()) {
*** 5457,5467 **** } return ik; } ! void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loadhook, TRAPS) { assert(ik != NULL, "invariant"); // Set name and CLD before adding to CLD ik->set_class_loader_data(_loader_data); ik->set_name(_class_name); --- 5465,5479 ---- } return ik; } ! void ClassFileParser::fill_instance_klass(InstanceKlass* ik, ! bool changed_by_loadhook, ! InstanceKlass* dynamic_nest_host, ! Handle classData, ! TRAPS) { assert(ik != NULL, "invariant"); // Set name and CLD before adding to CLD ik->set_class_loader_data(_loader_data); ik->set_name(_class_name);
*** 5493,5502 **** --- 5505,5519 ---- // this transfers ownership of a lot of arrays from // the parser onto the InstanceKlass* apply_parsed_class_metadata(ik, _java_fields_count, CHECK); + // can only set dynamic nest-host after static nest information is set + if (dynamic_nest_host != NULL) { + ik->set_nest_host(dynamic_nest_host, CHECK); + } + // note that is not safe to use the fields in the parser from this point on assert(NULL == _cp, "invariant"); assert(NULL == _fields, "invariant"); assert(NULL == _methods, "invariant"); assert(NULL == _inner_classes, "invariant");
*** 5516,5530 **** // has to be changed accordingly. ik->set_initial_method_idnum(ik->methods()->length()); ik->set_this_class_index(_this_class_index); ! if (is_unsafe_anonymous()) { // _this_class_index is a CONSTANT_Class entry that refers to this ! // anonymous class itself. If this class needs to refer to its own methods or ! // fields, it would use a CONSTANT_MethodRef, etc, which would reference ! // _this_class_index. However, because this class is anonymous (it's // not stored in SystemDictionary), _this_class_index cannot be resolved // with ConstantPool::klass_at_impl, which does a SystemDictionary lookup. // Therefore, we must eagerly resolve _this_class_index now. ik->constants()->klass_at_put(_this_class_index, ik); } --- 5533,5547 ---- // has to be changed accordingly. ik->set_initial_method_idnum(ik->methods()->length()); ik->set_this_class_index(_this_class_index); ! if (_is_nonfindable || is_unsafe_anonymous()) { // _this_class_index is a CONSTANT_Class entry that refers to this ! // nonfindable or anonymous class itself. If this class needs to refer to its own ! // methods or fields, it would use a CONSTANT_MethodRef, etc, which would reference ! // _this_class_index. However, because this class is nonfindable or anonymous (it's // not stored in SystemDictionary), _this_class_index cannot be resolved // with ConstantPool::klass_at_impl, which does a SystemDictionary lookup. // Therefore, we must eagerly resolve _this_class_index now. ik->constants()->klass_at_put(_this_class_index, ik); }
*** 5542,5551 **** --- 5559,5572 ---- // Set PackageEntry for this_klass oop cl = ik->class_loader(); Handle clh = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(cl)); ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh()); ik->set_package(cld, CHECK); + // Obtain this_klass' module entry + ModuleEntry* module_entry = ik->module(); + assert(module_entry != NULL, "module_entry should always be set"); + const Array<Method*>* const methods = ik->methods(); assert(methods != NULL, "invariant"); const int methods_len = methods->length();
*** 5597,5619 **** // reject static interface methods prior to Java 8 if (ik->is_interface() && _major_version < JAVA_8_VERSION) { check_illegal_static_method(ik, CHECK); } - // Obtain this_klass' module entry - ModuleEntry* module_entry = ik->module(); - assert(module_entry != NULL, "module_entry should always be set"); - // Obtain java.lang.Module Handle module_handle(THREAD, module_entry->module()); // Allocate mirror and initialize static fields // The create_mirror() call will also call compute_modifiers() java_lang_Class::create_mirror(ik, Handle(THREAD, _loader_data->class_loader()), module_handle, _protection_domain, CHECK); assert(_all_mirandas != NULL, "invariant"); // Generate any default methods - default methods are public interface methods --- 5618,5637 ---- // reject static interface methods prior to Java 8 if (ik->is_interface() && _major_version < JAVA_8_VERSION) { check_illegal_static_method(ik, CHECK); } // Obtain java.lang.Module Handle module_handle(THREAD, module_entry->module()); // Allocate mirror and initialize static fields // The create_mirror() call will also call compute_modifiers() java_lang_Class::create_mirror(ik, Handle(THREAD, _loader_data->class_loader()), module_handle, _protection_domain, + classData, CHECK); assert(_all_mirandas != NULL, "invariant"); // Generate any default methods - default methods are public interface methods
*** 5683,5704 **** set_klass(ik); debug_only(ik->verify();) } - void ClassFileParser::update_class_name(Symbol* new_class_name) { - // Decrement the refcount in the old name, since we're clobbering it. - _class_name->decrement_refcount(); - - _class_name = new_class_name; - // Increment the refcount of the new name. - // Now the ClassFileParser owns this name and will decrement in - // the destructor. - _class_name->increment_refcount(); - } - - // For an unsafe anonymous class that is in the unnamed package, move it to its host class's // package by prepending its host class's package name to its class name and setting // its _class_name field. void ClassFileParser::prepend_host_package_name(const InstanceKlass* unsafe_anonymous_host, TRAPS) { ResourceMark rm(THREAD); --- 5701,5710 ----
*** 5763,5780 **** Symbol* name, ClassLoaderData* loader_data, Handle protection_domain, const InstanceKlass* unsafe_anonymous_host, GrowableArray<Handle>* cp_patches, Publicity pub_level, TRAPS) : _stream(stream), - _requested_name(name), _class_name(NULL), _loader_data(loader_data), _unsafe_anonymous_host(unsafe_anonymous_host), _cp_patches(cp_patches), _num_patched_klasses(0), _max_num_patched_klasses(0), _orig_cp_size(0), _first_patched_klass_resolved_index(0), _super_klass(), --- 5769,5789 ---- Symbol* name, ClassLoaderData* loader_data, Handle protection_domain, const InstanceKlass* unsafe_anonymous_host, GrowableArray<Handle>* cp_patches, + const bool is_nonfindable, + const bool can_access_vm_annotations, Publicity pub_level, TRAPS) : _stream(stream), _class_name(NULL), _loader_data(loader_data), _unsafe_anonymous_host(unsafe_anonymous_host), _cp_patches(cp_patches), + _is_nonfindable(is_nonfindable), + _can_access_vm_annotations(can_access_vm_annotations), _num_patched_klasses(0), _max_num_patched_klasses(0), _orig_cp_size(0), _first_patched_klass_resolved_index(0), _super_klass(),
*** 5974,5986 **** // Version numbers _minor_version = stream->get_u2_fast(); _major_version = stream->get_u2_fast(); ! if (DumpSharedSpaces && _major_version < JAVA_6_VERSION) { ResourceMark rm; ! warning("Pre JDK 6 class not supported by CDS: %u.%u %s", _major_version, _minor_version, _class_name->as_C_string()); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_UnsupportedClassVersionError(), "Unsupported major.minor version for dump time %u.%u", --- 5983,5995 ---- // Version numbers _minor_version = stream->get_u2_fast(); _major_version = stream->get_u2_fast(); ! if (DumpSharedSpaces && _major_version < JAVA_1_5_VERSION) { ResourceMark rm; ! warning("Pre JDK 1.5 class not supported by CDS: %u.%u %s", _major_version, _minor_version, _class_name->as_C_string()); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_UnsupportedClassVersionError(), "Unsupported major.minor version for dump time %u.%u",
*** 5997,6010 **** guarantee_property( cp_size >= 1, "Illegal constant pool size %u in class file %s", cp_size, CHECK); _orig_cp_size = cp_size; ! if (int(cp_size) + _max_num_patched_klasses > 0xffff) { ! THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes"); } - cp_size += _max_num_patched_klasses; _cp = ConstantPool::allocate(_loader_data, cp_size, CHECK); --- 6006,6024 ---- guarantee_property( cp_size >= 1, "Illegal constant pool size %u in class file %s", cp_size, CHECK); _orig_cp_size = cp_size; ! if (is_nonfindable()) { // Add a slot for nonfindable class name. ! assert(_max_num_patched_klasses == 0, "Sanity check"); ! cp_size++; ! } else { ! if (int(cp_size) + _max_num_patched_klasses > 0xffff) { ! THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes"); ! } ! cp_size += _max_num_patched_klasses; } _cp = ConstantPool::allocate(_loader_data, cp_size, CHECK);
*** 6051,6090 **** _this_class_index, CHECK); Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index); assert(class_name_in_cp != NULL, "class_name can't be null"); - // Update _class_name to reflect the name in the constant pool - update_class_name(class_name_in_cp); - // Don't need to check whether this class name is legal or not. // It has been checked when constant pool is parsed. // However, make sure it is not an array type. if (_need_verify) { ! guarantee_property(_class_name->char_at(0) != JVM_SIGNATURE_ARRAY, "Bad class name in class file %s", CHECK); } ! // Checks if name in class file matches requested name ! if (_requested_name != NULL && _requested_name != _class_name) { ! ResourceMark rm(THREAD); ! Exceptions::fthrow( ! THREAD_AND_LOCATION, ! vmSymbols::java_lang_NoClassDefFoundError(), ! "%s (wrong name: %s)", ! _class_name->as_C_string(), ! _requested_name != NULL ? _requested_name->as_C_string() : "NoName" ! ); ! return; } ! // if this is an anonymous class fix up its name if it's in the unnamed // package. Otherwise, throw IAE if it is in a different package than // its host class. ! if (_unsafe_anonymous_host != NULL) { fix_unsafe_anonymous_class_name(CHECK); } // Verification prevents us from creating names with dots in them, this // asserts that that's the case. assert(is_internal_format(_class_name), "external class name format used internally"); --- 6065,6154 ---- _this_class_index, CHECK); Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index); assert(class_name_in_cp != NULL, "class_name can't be null"); // Don't need to check whether this class name is legal or not. // It has been checked when constant pool is parsed. // However, make sure it is not an array type. if (_need_verify) { ! guarantee_property(class_name_in_cp->char_at(0) != JVM_SIGNATURE_ARRAY, "Bad class name in class file %s", CHECK); } ! #ifdef ASSERT ! // Basic sanity checks ! assert(!(_is_nonfindable && (_unsafe_anonymous_host != NULL)), "mutually exclusive variants"); ! ! if (_unsafe_anonymous_host != NULL) { ! assert(_class_name == vmSymbols::unknown_class_name(), "A named anonymous class???"); ! } ! if (_is_nonfindable) { ! assert(_class_name != vmSymbols::unknown_class_name(), "non-findable classes should have a special name"); } + #endif + + // Update the _class_name as needed depending on whether this is a named, + // un-named, nonfindable or unsafe-anonymous class. + + if (_is_nonfindable) { + _class_name->increment_refcount(); + + // Add a Utf8 entry containing the nonfindable name. + assert(_class_name != NULL, "Unexpected null _class_name"); + int nonfindable_name_index = _orig_cp_size; // this is an extra slot we added + cp->symbol_at_put(nonfindable_name_index, _class_name); ! if (_need_verify) { ! // Since this name was not in the original constant pool, it didn't get ! // checked during constantpool parsing. So, check it here. ! verify_legal_class_name(_class_name, CHECK); ! } ! ! // Update this_class_index's slot in the constant pool with the new Utf8 entry. ! // We have to update the resolved_klass_index and the name_index together ! // so extract the existing resolved_klass_index first. ! CPKlassSlot cp_klass_slot = cp->klass_slot_at(_this_class_index); ! int resolved_klass_index = cp_klass_slot.resolved_klass_index(); ! cp->unresolved_klass_at_put(_this_class_index, nonfindable_name_index, resolved_klass_index); ! assert(cp->klass_slot_at(_this_class_index).name_index() == _orig_cp_size, ! "Bad name_index"); ! ! // NOTE: !_is_nonfindable does not imply "findable" as it could be an old-style ! // "non-findable" unsafe-anonymous class ! ! // If this is an anonymous class fix up its name if it is in the unnamed // package. Otherwise, throw IAE if it is in a different package than // its host class. ! } else if (_unsafe_anonymous_host != NULL) { ! Symbol* old_class_name = _class_name; ! _class_name = class_name_in_cp; ! _class_name->increment_refcount(); fix_unsafe_anonymous_class_name(CHECK); + old_class_name->decrement_refcount(); + + } else { + // Check if name in class file matches given name + if (_class_name != class_name_in_cp) { + if (_class_name != vmSymbols::unknown_class_name()) { + ResourceMark rm(THREAD); + Exceptions::fthrow(THREAD_AND_LOCATION, + vmSymbols::java_lang_NoClassDefFoundError(), + "%s (wrong name: %s)", + class_name_in_cp->as_C_string(), + _class_name->as_C_string() + ); + return; + } else { + // The class name was not known by the caller so we set it from + // the value in the CP. + _class_name = class_name_in_cp; + _class_name->increment_refcount(); + } + // else nothing to do: the expected class name matches what is in the CP + } } // Verification prevents us from creating names with dots in them, this // asserts that that's the case. assert(is_internal_format(_class_name), "external class name format used internally");
*** 6105,6117 **** if (DumpLoadedClassList != NULL && stream->source() != NULL && classlist_file->is_open()) { if (!ClassLoader::has_jrt_entry()) { warning("DumpLoadedClassList and CDS are not supported in exploded build"); DumpLoadedClassList = NULL; } else if (SystemDictionaryShared::is_sharing_possible(_loader_data) && _unsafe_anonymous_host == NULL) { // Only dump the classes that can be stored into CDS archive. ! // Unsafe anonymous classes such as generated LambdaForm classes are also not included. oop class_loader = _loader_data->class_loader(); ResourceMark rm(THREAD); bool skip = false; if (class_loader == NULL || SystemDictionary::is_platform_class_loader(class_loader)) { // For the boot and platform class loaders, skip classes that are not found in the --- 6169,6182 ---- if (DumpLoadedClassList != NULL && stream->source() != NULL && classlist_file->is_open()) { if (!ClassLoader::has_jrt_entry()) { warning("DumpLoadedClassList and CDS are not supported in exploded build"); DumpLoadedClassList = NULL; } else if (SystemDictionaryShared::is_sharing_possible(_loader_data) && + !_is_nonfindable && _unsafe_anonymous_host == NULL) { // Only dump the classes that can be stored into CDS archive. ! // Nonfindable and unsafe anonymous classes such as generated LambdaForm classes are also not included. oop class_loader = _loader_data->class_loader(); ResourceMark rm(THREAD); bool skip = false; if (class_loader == NULL || SystemDictionary::is_platform_class_loader(class_loader)) { // For the boot and platform class loaders, skip classes that are not found in the
< prev index next >