hotspot/src/share/vm/oops/instanceKlass.cpp
changeset 36508 5f9eee6b383b
parent 36300 5b47f168b948
child 36812 4f96f15e4a46
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1972,8 +1972,9 @@
 }
 
 void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
+  instanceKlassHandle ik(THREAD, this);
+  ik->set_package(loader_data, CHECK);
   Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
-  instanceKlassHandle ik(THREAD, this);
 
   Array<Method*>* methods = ik->methods();
   int num_methods = methods->length();
@@ -2178,26 +2179,135 @@
   return dest;
 }
 
-// different verisons of is_same_class_package
+const jbyte* InstanceKlass::package_from_name(const Symbol* name, int& length) {
+  ResourceMark rm;
+  length = 0;
+  if (name == NULL) {
+    return NULL;
+  } else {
+    const jbyte* base_name = name->base();
+    const jbyte* last_slash = UTF8::strrchr(base_name, name->utf8_length(), '/');
+
+    if (last_slash == NULL) {
+      // No package name
+      return NULL;
+    } else {
+      // Skip over '['s
+      if (*base_name == '[') {
+        do {
+          base_name++;
+        } while (*base_name == '[');
+        if (*base_name != 'L') {
+          // Fully qualified class names should not contain a 'L'.
+          // Set length to -1 to indicate that the package name
+          // could not be obtained due to an error condition.
+          // In this situtation, is_same_class_package returns false.
+          length = -1;
+          return NULL;
+        }
+      }
+
+      // Found the package name, look it up in the symbol table.
+      length = last_slash - base_name;
+      assert(length > 0, "Bad length for package name");
+      return base_name;
+    }
+  }
+}
+
+ModuleEntry* InstanceKlass::module() const {
+  if (!in_unnamed_package()) {
+    return _package_entry->module();
+  }
+  const Klass* host = host_klass();
+  if (host == NULL) {
+    return class_loader_data()->modules()->unnamed_module();
+  }
+  return host->class_loader_data()->modules()->unnamed_module();
+}
+
+void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) {
+  int length = 0;
+  const jbyte* base_name = package_from_name(name(), length);
+
+  if (base_name != NULL && loader_data != NULL) {
+    TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)base_name, length, CHECK);
+
+    // Find in class loader's package entry table.
+    _package_entry = loader_data->packages()->lookup_only(pkg_name);
+
+    // If the package name is not found in the loader's package
+    // entry table, it is an indication that the package has not
+    // been defined. Consider it defined within the unnamed module.
+    if (_package_entry == NULL) {
+      ResourceMark rm;
+
+      if (!ModuleEntryTable::javabase_defined()) {
+        // Before java.base is defined during bootstrapping, define all packages in
+        // the java.base module.  If a non-java.base package is erroneously placed
+        // in the java.base module it will be caught later when java.base
+        // is defined by ModuleEntryTable::verify_javabase_packages check.
+        assert(ModuleEntryTable::javabase_module() != NULL, "java.base module is NULL");
+        _package_entry = loader_data->packages()->lookup(pkg_name, ModuleEntryTable::javabase_module());
+      } else {
+        assert(loader_data->modules()->unnamed_module() != NULL, "unnamed module is NULL");
+        _package_entry = loader_data->packages()->lookup(pkg_name,
+                                                         loader_data->modules()->unnamed_module());
+      }
+
+      // A package should have been successfully created
+      assert(_package_entry != NULL, "Package entry for class %s not found, loader %s",
+             name()->as_C_string(), loader_data->loader_name());
+    }
+
+    if (log_is_enabled(Debug, modules)) {
+      ResourceMark rm;
+      ModuleEntry* m = _package_entry->module();
+      log_trace(modules)("Setting package: class: %s, package: %s, loader: %s, module: %s",
+                         external_name(),
+                         pkg_name->as_C_string(),
+                         loader_data->loader_name(),
+                         (m->is_named() ? m->name()->as_C_string() : UNNAMED_MODULE));
+    }
+  } else {
+    ResourceMark rm;
+    log_trace(modules)("Setting package: class: %s, package: unnamed, loader: %s, module: %s",
+                       external_name(),
+                       (loader_data != NULL) ? loader_data->loader_name() : "NULL",
+                       UNNAMED_MODULE);
+  }
+}
+
+
+// different versions of is_same_class_package
+
 bool InstanceKlass::is_same_class_package(const Klass* class2) const {
-  const Klass* const class1 = (const Klass* const)this;
-  oop classloader1 = InstanceKlass::cast(class1)->class_loader();
-  const Symbol* const classname1 = class1->name();
-
+  oop classloader1 = this->class_loader();
+  PackageEntry* classpkg1 = this->package();
   if (class2->is_objArray_klass()) {
     class2 = ObjArrayKlass::cast(class2)->bottom_klass();
   }
+
   oop classloader2;
+  PackageEntry* classpkg2;
   if (class2->is_instance_klass()) {
-    classloader2 = InstanceKlass::cast(class2)->class_loader();
+    classloader2 = class2->class_loader();
+    classpkg2 = InstanceKlass::cast(class2)->package();
   } else {
     assert(class2->is_typeArray_klass(), "should be type array");
     classloader2 = NULL;
+    classpkg2 = NULL;
   }
-  const Symbol* classname2 = class2->name();
-
-  return InstanceKlass::is_same_class_package(classloader1, classname1,
-                                              classloader2, classname2);
+
+  // Same package is determined by comparing class loader
+  // and package entries. Both must be the same. This rule
+  // applies even to classes that are defined in the unnamed
+  // package, they still must have the same class loader.
+  if ((classloader1 == classloader2) && (classpkg1 == classpkg2)) {
+    return true;
+  }
+
+  return false;
 }
 
 bool InstanceKlass::is_same_class_package(oop other_class_loader,
@@ -2225,43 +2335,24 @@
     // The Symbol*'s are in UTF8 encoding. Since we only need to check explicitly
     // for ASCII characters ('/', 'L', '['), we can keep them in UTF8 encoding.
     // Otherwise, we just compare jbyte values between the strings.
-    const jbyte *name1 = class_name1->base();
-    const jbyte *name2 = class_name2->base();
-
-    const jbyte *last_slash1 = UTF8::strrchr(name1, class_name1->utf8_length(), '/');
-    const jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
-
-    if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
+    int length1 = 0;
+    int length2 = 0;
+    const jbyte *name1 = package_from_name(class_name1, length1);
+    const jbyte *name2 = package_from_name(class_name2, length2);
+
+    if ((length1 < 0) || (length2 < 0)) {
+      // error occurred parsing package name.
+      return false;
+    }
+
+    if ((name1 == NULL) || (name2 == NULL)) {
       // One of the two doesn't have a package.  Only return true
       // if the other one also doesn't have a package.
-      return last_slash1 == last_slash2;
-    } else {
-      // Skip over '['s
-      if (*name1 == '[') {
-        do {
-          name1++;
-        } while (*name1 == '[');
-        if (*name1 != 'L') {
-          // Something is terribly wrong.  Shouldn't be here.
-          return false;
-        }
-      }
-      if (*name2 == '[') {
-        do {
-          name2++;
-        } while (*name2 == '[');
-        if (*name2 != 'L') {
-          // Something is terribly wrong.  Shouldn't be here.
-          return false;
-        }
-      }
-
-      // Check that package part is identical
-      int length1 = last_slash1 - name1;
-      int length2 = last_slash2 - name2;
-
-      return UTF8::equal(name1, length1, name2, length2);
+      return name1 == name2;
     }
+
+    // Check that package part is identical
+    return UTF8::equal(name1, length1, name2, length2);
   }
 }
 
@@ -2300,7 +2391,7 @@
   if (!class2->is_instance_klass())  return false;
 
   // must be in same package before we try anything else
-  if (!class1->is_same_class_package(class2->class_loader(), class2->name()))
+  if (!class1->is_same_class_package(class2))
     return false;
 
   // As long as there is an outer1.getEnclosingClass,
@@ -2908,6 +2999,7 @@
 
 void InstanceKlass::print_loading_log(LogLevel::type type,
                                       ClassLoaderData* loader_data,
+                                      const char* module_name,
                                       const ClassFileStream* cfs) const {
   ResourceMark rm;
   outputStream* log;
@@ -2928,7 +3020,11 @@
   // Source
   if (cfs != NULL) {
     if (cfs->source() != NULL) {
-      log->print(" source: %s", cfs->source());
+      if (module_name != NULL) {
+        log->print(" source: jrt:/%s", module_name);
+      } else {
+        log->print(" source: %s", cfs->source());
+      }
     } else if (loader_data == ClassLoaderData::the_null_class_loader_data()) {
       Thread* THREAD = Thread::current();
       Klass* caller =