< prev index next >

src/hotspot/share/classfile/classFileParser.cpp

Print this page

        

@@ -1087,11 +1087,11 @@
     : _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);
+  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);
   }

@@ -1220,10 +1220,11 @@
 // 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");

@@ -1265,11 +1266,11 @@
       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);
+    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.

@@ -1391,10 +1392,11 @@
         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(

@@ -2050,16 +2052,18 @@
       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 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_unsafe_anonymous();
+                          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;

@@ -2674,10 +2678,11 @@
         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(

@@ -3436,10 +3441,11 @@
         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(

@@ -5422,19 +5428,22 @@
     } // CheckIntrinsics
 #endif // ASSERT
   }
 }
 
-InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, TRAPS) {
+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, CHECK_NULL);
+  fill_instance_klass(ik, changed_by_loadhook, dynamic_nest_host, classData, CHECK_NULL);
 
   assert(_klass == ik, "invariant");
 
 
   if (ik->should_store_fingerprint()) {

@@ -5456,11 +5465,15 @@
   }
 
   return ik;
 }
 
-void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loadhook, TRAPS) {
+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);

@@ -5492,10 +5505,15 @@
 
   // 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");

@@ -5515,15 +5533,15 @@
   // 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()) {
+  if (_is_nonfindable || 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
+    // 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);
   }

@@ -5541,10 +5559,14 @@
   // 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();
 

@@ -5596,23 +5618,20 @@
   // 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,
+                                 classData,
                                  CHECK);
 
   assert(_all_mirandas != NULL, "invariant");
 
   // Generate any default methods - default methods are public interface methods

@@ -5682,22 +5701,10 @@
   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);

@@ -5762,18 +5769,21 @@
                                  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),
-  _requested_name(name),
   _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(),

@@ -5996,14 +6006,19 @@
   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");
+  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_size += _max_num_patched_klasses;
 
   _cp = ConstantPool::allocate(_loader_data,
                                cp_size,
                                CHECK);
 

@@ -6050,40 +6065,90 @@
     _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,
+    guarantee_property(class_name_in_cp->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;
+#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 this is an anonymous class fix up its name if it's in the unnamed
+    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.
-  if (_unsafe_anonymous_host != NULL) {
+  } 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");

@@ -6104,13 +6169,14 @@
     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.
-        // Unsafe anonymous classes such as generated LambdaForm classes are also not included.
+        // 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 >