8190359: Reduce the number of recorded klass dependencies
Summary: Skip recording dependencies to non-anonymous classes loaded by builtin class loaders.
Reviewed-by: iklam, coleenp, lfoltan
--- a/src/hotspot/share/classfile/classLoaderData.cpp Fri Feb 02 09:34:11 2018 -0500
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Fri Feb 02 10:37:48 2018 -0500
@@ -329,36 +329,36 @@
ClassLoaderData * const from_cld = this;
ClassLoaderData * const to_cld = k->class_loader_data();
- // Dependency to the null class loader data doesn't need to be recorded
- // because the null class loader data never goes away.
- if (to_cld->is_the_null_class_loader_data()) {
+ // Do not need to record dependency if the dependency is to a class whose
+ // class loader data is never freed. (i.e. the dependency's class loader
+ // is one of the three builtin class loaders and the dependency is not
+ // anonymous.)
+ if (to_cld->is_permanent_class_loader_data()) {
return;
}
oop to;
if (to_cld->is_anonymous()) {
+ // Just return if an anonymous class is attempting to record a dependency
+ // to itself. (Note that every anonymous class has its own unique class
+ // loader data.)
+ if (to_cld == from_cld) {
+ return;
+ }
// Anonymous class dependencies are through the mirror.
to = k->java_mirror();
} else {
to = to_cld->class_loader();
-
- // If from_cld is anonymous, even if it's class_loader is a parent of 'to'
- // we still have to add it. The class_loader won't keep from_cld alive.
- if (!from_cld->is_anonymous()) {
- // Check that this dependency isn't from the same or parent class_loader
- oop from = from_cld->class_loader();
+ oop from = from_cld->class_loader();
- oop curr = from;
- while (curr != NULL) {
- if (curr == to) {
- return; // this class loader is in the parent list, no need to add it.
- }
- curr = java_lang_ClassLoader::parent(curr);
- }
+ // Just return if this dependency is to a class with the same or a parent
+ // class_loader.
+ if (from == to || java_lang_ClassLoader::isAncestor(from, to)) {
+ return; // this class loader is in the parent list, no need to add it.
}
}
- // It's a dependency we won't find through GC, add it. This is relatively rare
+ // It's a dependency we won't find through GC, add it. This is relatively rare.
// Must handle over GC point.
Handle dependency(THREAD, to);
from_cld->_dependencies.add(dependency, CHECK);
@@ -704,14 +704,23 @@
}
// Returns true if this class loader data is one of the 3 builtin
-// (boot, application/system or platform) class loaders. Note, the
-// builtin loaders are not freed by a GC.
+// (boot, application/system or platform) class loaders. Note that
+// if the class loader data is for an anonymous class then it may get
+// freed by a GC even if its class loader is one of the 3 builtin
+// loaders.
bool ClassLoaderData::is_builtin_class_loader_data() const {
return (is_the_null_class_loader_data() ||
SystemDictionary::is_system_class_loader(class_loader()) ||
SystemDictionary::is_platform_class_loader(class_loader()));
}
+// Returns true if this class loader data is a class loader data
+// that is not ever freed by a GC. It must be one of the builtin
+// class loaders and not anonymous.
+bool ClassLoaderData::is_permanent_class_loader_data() const {
+ return is_builtin_class_loader_data() && !is_anonymous();
+}
+
Metaspace* ClassLoaderData::metaspace_non_null() {
// If the metaspace has not been allocated, create a new one. Might want
// to create smaller arena for Reflection class loaders also.
--- a/src/hotspot/share/classfile/classLoaderData.hpp Fri Feb 02 09:34:11 2018 -0500
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Fri Feb 02 10:37:48 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -345,6 +345,7 @@
bool is_system_class_loader_data() const;
bool is_platform_class_loader_data() const;
bool is_builtin_class_loader_data() const;
+ bool is_permanent_class_loader_data() const;
// The Metaspace is created lazily so may be NULL. This
// method will allocate a Metaspace if needed.