8190359: Reduce the number of recorded klass dependencies

Skip recording dependencies to non-anonymous classes loaded by builtin class loaders.

Reviewed-by: iklam, coleenp, lfoltan
This commit is contained in:
Harold Seigel 2018-02-02 10:37:48 -05:00
parent 191a1f80a1
commit 83bb2205e8
2 changed files with 30 additions and 20 deletions

View file

@ -329,36 +329,36 @@ void ClassLoaderData::record_dependency(const Klass* k, TRAPS) {
ClassLoaderData * const from_cld = this; ClassLoaderData * const from_cld = this;
ClassLoaderData * const to_cld = k->class_loader_data(); ClassLoaderData * const to_cld = k->class_loader_data();
// Dependency to the null class loader data doesn't need to be recorded // Do not need to record dependency if the dependency is to a class whose
// because the null class loader data never goes away. // class loader data is never freed. (i.e. the dependency's class loader
if (to_cld->is_the_null_class_loader_data()) { // is one of the three builtin class loaders and the dependency is not
// anonymous.)
if (to_cld->is_permanent_class_loader_data()) {
return; return;
} }
oop to; oop to;
if (to_cld->is_anonymous()) { 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. // Anonymous class dependencies are through the mirror.
to = k->java_mirror(); to = k->java_mirror();
} else { } else {
to = to_cld->class_loader(); 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; // Just return if this dependency is to a class with the same or a parent
while (curr != NULL) { // class_loader.
if (curr == to) { if (from == to || java_lang_ClassLoader::isAncestor(from, to)) {
return; // this class loader is in the parent list, no need to add it. return; // this class loader is in the parent list, no need to add it.
} }
curr = java_lang_ClassLoader::parent(curr);
}
}
} }
// 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. // Must handle over GC point.
Handle dependency(THREAD, to); Handle dependency(THREAD, to);
from_cld->_dependencies.add(dependency, CHECK); from_cld->_dependencies.add(dependency, CHECK);
@ -704,14 +704,23 @@ bool ClassLoaderData::is_platform_class_loader_data() const {
} }
// Returns true if this class loader data is one of the 3 builtin // Returns true if this class loader data is one of the 3 builtin
// (boot, application/system or platform) class loaders. Note, the // (boot, application/system or platform) class loaders. Note that
// builtin loaders are not freed by a GC. // 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 { bool ClassLoaderData::is_builtin_class_loader_data() const {
return (is_the_null_class_loader_data() || return (is_the_null_class_loader_data() ||
SystemDictionary::is_system_class_loader(class_loader()) || SystemDictionary::is_system_class_loader(class_loader()) ||
SystemDictionary::is_platform_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() { Metaspace* ClassLoaderData::metaspace_non_null() {
// If the metaspace has not been allocated, create a new one. Might want // If the metaspace has not been allocated, create a new one. Might want
// to create smaller arena for Reflection class loaders also. // to create smaller arena for Reflection class loaders also.

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -345,6 +345,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
bool is_system_class_loader_data() const; bool is_system_class_loader_data() const;
bool is_platform_class_loader_data() const; bool is_platform_class_loader_data() const;
bool is_builtin_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 // The Metaspace is created lazily so may be NULL. This
// method will allocate a Metaspace if needed. // method will allocate a Metaspace if needed.