< prev index next >

src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp

Print this page
rev 58565 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: duke
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2018 SAP SE. 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
  * under the terms of the GNU General Public License version 2 only, as

@@ -127,11 +127,11 @@
 
 };
 
 class LoaderTreeNode : public ResourceObj {
 
-  // We walk the CLDG and, for each CLD which is non-unsafe_anonymous, add
+  // We walk the CLDG and, for each CLD which is findable, add
   // a tree node.
   // To add a node we need its parent node; if the parent node does not yet
   // exist - because we have not yet encountered the CLD for the parent loader -
   // we add a preliminary empty LoaderTreeNode for it. This preliminary node
   // just contains the loader oop and nothing else. Once we encounter the CLD of

@@ -147,10 +147,13 @@
   int _num_classes;
 
   LoadedClassInfo* _anon_classes;
   int _num_anon_classes;
 
+  LoadedClassInfo* _hidden_weak_classes;
+  int _num_hidden_weak_classes;
+
   // In default view, similar tree nodes (same loader class, same name or no name)
   // are folded into each other to make the output more readable.
   // _num_folded contains the number of nodes which have been folded into this
   // one.
   int _num_folded;

@@ -175,10 +178,11 @@
     // e.g. "+--- jdk.internal.reflect.DelegatingClassLoader"
     st->print("+%.*s", BranchTracker::twig_len, "----------");
     if (_cld->is_the_null_class_loader_data()) {
       st->print(" <bootstrap>");
     } else {
+      assert(!_cld->has_class_mirror_holder(), "_cld must be the primary cld");
       if (loader_name != NULL) {
         st->print(" \"%s\",", loader_name->as_C_string());
       }
       st->print(" %s", loader_klass != NULL ? loader_klass->external_name() : "??");
       if (_num_folded > 0) {

@@ -218,11 +222,11 @@
       }
 
       if (print_classes) {
         if (_classes != NULL) {
           for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) {
-            // Non-unsafe anonymous classes should live in the primary CLD of its loader
+            // Weak-hidden and unsafe anonymous classes should not live in the primary CLD of their loaders.
             assert(lci->_cld == _cld, "must be");
 
             branchtracker.print(st);
             if (lci == _classes) { // first iteration
               st->print("%*s ", indentation, "Classes:");

@@ -256,20 +260,49 @@
               st->print("%*s ", indentation, "Unsafe Anonymous Classes:");
             } else {
               st->print("%*s ", indentation, "");
             }
             st->print("%s", lci->_klass->external_name());
-            // For unsafe anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD.
+            // For unsafe anonymous classes, also print CLD if verbose. Should
+            // be a different one than the primary CLD.
+            assert(lci->_cld != _cld, "must be");
+            if (verbose) {
+              st->print("  (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld));
+            }
+            st->cr();
+          }
+          branchtracker.print(st);
+          st->print("%*s ", indentation, "");
+          st->print_cr("(%u unsafe anonymous class%s)", _num_anon_classes,
+                       (_num_anon_classes == 1) ? "" : "es");
+
+          // Empty line
+          branchtracker.print(st);
+          st->cr();
+        }
+
+        if (_hidden_weak_classes != NULL) {
+          for (LoadedClassInfo* lci = _hidden_weak_classes; lci; lci = lci->_next) {
+            branchtracker.print(st);
+            if (lci == _hidden_weak_classes) { // first iteration
+              st->print("%*s ", indentation, "Weak Hidden Classes:");
+            } else {
+              st->print("%*s ", indentation, "");
+            }
+            st->print("%s", lci->_klass->external_name());
+            // For weak hidden classes, also print CLD if verbose. Should be a
+            // different one than the primary CLD.
             assert(lci->_cld != _cld, "must be");
             if (verbose) {
               st->print("  (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld));
             }
             st->cr();
           }
           branchtracker.print(st);
           st->print("%*s ", indentation, "");
-          st->print_cr("(%u unsafe anonymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es");
+          st->print_cr("(%u weak hidden class%s)", _num_hidden_weak_classes,
+                       (_num_hidden_weak_classes == 1) ? "" : "es");
 
           // Empty line
           branchtracker.print(st);
           st->cr();
         }

@@ -299,10 +332,11 @@
 public:
 
   LoaderTreeNode(const oop loader_oop)
     : _loader_oop(loader_oop), _cld(NULL), _child(NULL), _next(NULL),
       _classes(NULL), _num_classes(0), _anon_classes(NULL), _num_anon_classes(0),
+      _hidden_weak_classes(NULL), _num_hidden_weak_classes(0),
       _num_folded(0)
     {}
 
   void set_cld(const ClassLoaderData* cld) {
     _cld = cld;

@@ -317,19 +351,29 @@
     assert(info->_next == NULL, "must be");
     info->_next = _next;
     _next = info;
   }
 
-  void add_classes(LoadedClassInfo* first_class, int num_classes, bool is_unsafe_anonymous) {
-    LoadedClassInfo** p_list_to_add_to = is_unsafe_anonymous ? &_anon_classes : &_classes;
+  void add_classes(LoadedClassInfo* first_class, int num_classes, bool has_class_mirror_holder) {
+    LoadedClassInfo** p_list_to_add_to;
+    bool is_hidden = first_class->_klass->is_hidden();
+    if (has_class_mirror_holder) {
+      p_list_to_add_to = is_hidden ? &_hidden_weak_classes : &_anon_classes;
+    } else {
+      p_list_to_add_to = &_classes;
+    }
     // Search tail.
     while ((*p_list_to_add_to) != NULL) {
       p_list_to_add_to = &(*p_list_to_add_to)->_next;
     }
     *p_list_to_add_to = first_class;
-    if (is_unsafe_anonymous) {
+    if (has_class_mirror_holder) {
+      if (is_hidden) {
+        _num_hidden_weak_classes += num_classes;
+      } else {
       _num_anon_classes += num_classes;
+      }
     } else {
       _num_classes += num_classes;
     }
   }
 

@@ -419,11 +463,11 @@
   static void fill_in_classes(LoaderTreeNode* info, const ClassLoaderData* cld) {
     assert(info != NULL && cld != NULL, "must be");
     LoadedClassCollectClosure lccc(cld);
     const_cast<ClassLoaderData*>(cld)->classes_do(&lccc);
     if (lccc._num_classes > 0) {
-      info->add_classes(lccc._list, lccc._num_classes, cld->is_unsafe_anonymous());
+      info->add_classes(lccc._list, lccc._num_classes, cld->has_class_mirror_holder());
     }
   }
 
   LoaderTreeNode* find_node_or_add_empty_node(oop loader_oop) {
 

@@ -479,11 +523,11 @@
 
     LoaderTreeNode* info = find_node_or_add_empty_node(loader_oop);
     assert(info != NULL, "must be");
 
     // Update CLD in node, but only if this is the primary CLD for this loader.
-    if (cld->is_unsafe_anonymous() == false) {
+    if (cld->has_class_mirror_holder() == false) {
       assert(info->cld() == NULL, "there should be only one primary CLD per loader");
       info->set_cld(cld);
     }
 
     // Add classes.
< prev index next >