--- old/src/hotspot/share/classfile/classLoaderData.cpp 2018-01-30 13:31:21.087603614 -0500 +++ new/src/hotspot/share/classfile/classLoaderData.cpp 2018-01-30 13:31:20.890697805 -0500 @@ -329,9 +329,11 @@ 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 class loader datas are the same or + // 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 (from_cld == to_cld || to_cld->is_permanent_class_loader_data()) { return; } @@ -341,24 +343,16 @@ to = k->java_mirror(); } else { to = to_cld->class_loader(); + oop from = from_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 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); - } + assert(from != to || from_cld->is_anonymous(), "sanity check"); + // Just return if this dependency is from 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 +698,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. --- old/src/hotspot/share/classfile/classLoaderData.hpp 2018-01-30 13:31:21.590518545 -0500 +++ new/src/hotspot/share/classfile/classLoaderData.hpp 2018-01-30 13:31:21.397243349 -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 @@ -346,6 +346,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.