8201556: Disallow reading oops in ClassLoaderData if unloading

Move class_loader oop to an OopHandle, and assert that holder is alive when getting class_loader.

Reviewed-by: kbarrett, adinn
This commit is contained in:
Coleen Phillimore 2018-04-18 18:43:04 -04:00
parent 702ac597ad
commit ddfd4c33c6
22 changed files with 121 additions and 47 deletions

View File

@ -54,6 +54,7 @@
#include "classfile/metadataOnStackMark.hpp" #include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp" #include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp" #include "classfile/packageEntry.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"
#include "logging/logStream.hpp" #include "logging/logStream.hpp"
@ -102,8 +103,25 @@ void ClassLoaderData::init_null_class_loader_data() {
} }
} }
// JFR and logging support so that the name and klass are available after the
// class_loader oop is no longer alive, during unloading.
void ClassLoaderData::initialize_name_and_klass(Handle class_loader) {
_class_loader_klass = class_loader->klass();
oop class_loader_name = java_lang_ClassLoader::name(class_loader());
if (class_loader_name != NULL) {
Thread* THREAD = Thread::current();
ResourceMark rm(THREAD);
const char* class_loader_instance_name =
java_lang_String::as_utf8_string(class_loader_name);
if (class_loader_instance_name != NULL && class_loader_instance_name[0] != '\0') {
// Can't throw InternalError and SymbolTable doesn't throw OOM anymore.
_class_loader_name = SymbolTable::new_symbol(class_loader_instance_name, CATCH);
}
}
}
ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) : ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) :
_class_loader(h_class_loader()),
_is_anonymous(is_anonymous), _is_anonymous(is_anonymous),
// An anonymous class loader data doesn't have anything to keep // An anonymous class loader data doesn't have anything to keep
// it from being unloaded during parsing of the anonymous class. // it from being unloaded during parsing of the anonymous class.
@ -114,9 +132,14 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) :
_claimed(0), _modified_oops(true), _accumulated_modified_oops(false), _claimed(0), _modified_oops(true), _accumulated_modified_oops(false),
_jmethod_ids(NULL), _handles(), _deallocate_list(NULL), _jmethod_ids(NULL), _handles(), _deallocate_list(NULL),
_next(NULL), _next(NULL),
_class_loader_klass(NULL), _class_loader_name(NULL),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true, _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) { Monitor::_safepoint_check_never)) {
if (!h_class_loader.is_null()) {
_class_loader = _handles.add(h_class_loader());
}
if (!is_anonymous) { if (!is_anonymous) {
// The holder is initialized later for anonymous classes, and before calling anything // The holder is initialized later for anonymous classes, and before calling anything
// that call class_loader(). // that call class_loader().
@ -269,7 +292,6 @@ void ClassLoaderData::oops_do(OopClosure* f, bool must_claim, bool clear_mod_oop
clear_modified_oops(); clear_modified_oops();
} }
f->do_oop(&_class_loader);
_handles.oops_do(f); _handles.oops_do(f);
} }
@ -631,7 +653,7 @@ oop ClassLoaderData::holder_phantom() const {
// Unloading support // Unloading support
bool ClassLoaderData::is_alive() const { bool ClassLoaderData::is_alive() const {
bool alive = keep_alive() // null class loader and incomplete anonymous klasses. bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
|| (_holder.peek() != NULL); // not cleaned by weak reference processing || (_holder.peek() != NULL); // and not cleaned by the GC weak handle processing.
return alive; return alive;
} }
@ -887,13 +909,23 @@ ClassLoaderData* ClassLoaderData::anonymous_class_loader_data(Handle loader) {
} }
const char* ClassLoaderData::loader_name() const { const char* ClassLoaderData::loader_name() const {
if (is_unloading()) {
if (_class_loader_klass == NULL) {
return "<bootloader>";
} else if (_class_loader_name != NULL) {
return _class_loader_name->as_C_string();
} else {
return _class_loader_klass->name()->as_C_string();
}
} else {
// Handles null class loader // Handles null class loader
return SystemDictionary::loader_name(class_loader()); return SystemDictionary::loader_name(class_loader());
} }
}
void ClassLoaderData::print_value_on(outputStream* out) const { void ClassLoaderData::print_value_on(outputStream* out) const {
if (class_loader() != NULL) { if (!is_unloading() && class_loader() != NULL) {
out->print("loader data: " INTPTR_FORMAT " for instance ", p2i(this)); out->print("loader data: " INTPTR_FORMAT " for instance ", p2i(this));
class_loader()->print_value_on(out); // includes loader_name() and address of class loader instance class_loader()->print_value_on(out); // includes loader_name() and address of class loader instance
} else { } else {
@ -908,7 +940,7 @@ void ClassLoaderData::print_value_on(outputStream* out) const {
#ifndef PRODUCT #ifndef PRODUCT
void ClassLoaderData::print_on(outputStream* out) const { void ClassLoaderData::print_on(outputStream* out) const {
out->print("ClassLoaderData CLD: " PTR_FORMAT ", loader: " PTR_FORMAT ", loader_klass: %s {", out->print("ClassLoaderData CLD: " PTR_FORMAT ", loader: " PTR_FORMAT ", loader_klass: %s {",
p2i(this), p2i((void *)class_loader()), loader_name()); p2i(this), p2i(_class_loader.ptr_raw()), loader_name());
if (is_anonymous()) out->print(" anonymous"); if (is_anonymous()) out->print(" anonymous");
if (claimed()) out->print(" claimed"); if (claimed()) out->print(" claimed");
if (is_unloading()) out->print(" unloading"); if (is_unloading()) out->print(" unloading");
@ -962,10 +994,10 @@ bool ClassLoaderDataGraph::_metaspace_oom = false;
// Add a new class loader data node to the list. Assign the newly created // Add a new class loader data node to the list. Assign the newly created
// ClassLoaderData into the java/lang/ClassLoader object as a hidden field // ClassLoaderData into the java/lang/ClassLoader object as a hidden field
ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) { ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_anonymous) {
NoSafepointVerifier no_safepoints; // we mustn't GC until we've installed the NoSafepointVerifier no_safepoints; // we mustn't GC until we've installed the
// ClassLoaderData in the graph since the CLD // ClassLoaderData in the graph since the CLD
// contains unhandled oops // contains oops in _handles that must be walked.
ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous); ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous);
@ -1002,6 +1034,16 @@ ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) {
} while (true); } while (true);
} }
ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) {
ClassLoaderData* loader_data = add_to_graph(loader, is_anonymous);
// Initialize name and class after the loader data is added to the CLDG
// because adding the Symbol for the name might safepoint.
if (loader.not_null()) {
loader_data->initialize_name_and_klass(loader);
}
return loader_data;
}
void ClassLoaderDataGraph::oops_do(OopClosure* f, bool must_claim) { void ClassLoaderDataGraph::oops_do(OopClosure* f, bool must_claim) {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->oops_do(f, must_claim); cld->oops_do(f, must_claim);

View File

@ -28,7 +28,6 @@
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "memory/memRegion.hpp" #include "memory/memRegion.hpp"
#include "memory/metaspace.hpp" #include "memory/metaspace.hpp"
#include "memory/metaspaceCounters.hpp"
#include "oops/oopHandle.hpp" #include "oops/oopHandle.hpp"
#include "oops/weakHandle.hpp" #include "oops/weakHandle.hpp"
#include "runtime/mutex.hpp" #include "runtime/mutex.hpp"
@ -84,6 +83,7 @@ class ClassLoaderDataGraph : public AllStatic {
static volatile size_t _num_instance_classes; static volatile size_t _num_instance_classes;
static volatile size_t _num_array_classes; static volatile size_t _num_array_classes;
static ClassLoaderData* add_to_graph(Handle class_loader, bool anonymous);
static ClassLoaderData* add(Handle class_loader, bool anonymous); static ClassLoaderData* add(Handle class_loader, bool anonymous);
static void post_class_unload_events(); static void post_class_unload_events();
public: public:
@ -220,8 +220,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
static ClassLoaderData * _the_null_class_loader_data; static ClassLoaderData * _the_null_class_loader_data;
ClassLoaderWeakHandle _holder; // The oop that determines lifetime of this class loader WeakHandle<vm_class_loader_data> _holder; // The oop that determines lifetime of this class loader
oop _class_loader; // The instance of java/lang/ClassLoader associated with OopHandle _class_loader; // The instance of java/lang/ClassLoader associated with
// this ClassLoaderData // this ClassLoaderData
ClassLoaderMetaspace * volatile _metaspace; // Meta-space where meta-data defined by the ClassLoaderMetaspace * volatile _metaspace; // Meta-space where meta-data defined by the
@ -234,7 +234,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
bool _modified_oops; // Card Table Equivalent (YC/CMS support) bool _modified_oops; // Card Table Equivalent (YC/CMS support)
bool _accumulated_modified_oops; // Mod Union Equivalent (CMS support) bool _accumulated_modified_oops; // Mod Union Equivalent (CMS support)
s2 _keep_alive; // if this CLD is kept alive without a keep_alive_object(). s2 _keep_alive; // if this CLD is kept alive.
// Used for anonymous classes and the boot class // Used for anonymous classes and the boot class
// loader. _keep_alive does not need to be volatile or // loader. _keep_alive does not need to be volatile or
// atomic since there is one unique CLD per anonymous class. // atomic since there is one unique CLD per anonymous class.
@ -265,6 +265,9 @@ class ClassLoaderData : public CHeapObj<mtClass> {
// Support for walking class loader data objects // Support for walking class loader data objects
ClassLoaderData* _next; /// Next loader_datas created ClassLoaderData* _next; /// Next loader_datas created
// JFR support
Klass* _class_loader_klass;
Symbol* _class_loader_name;
TRACE_DEFINE_TRACE_ID_FIELD; TRACE_DEFINE_TRACE_ID_FIELD;
void set_next(ClassLoaderData* next) { _next = next; } void set_next(ClassLoaderData* next) { _next = next; }
@ -305,6 +308,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
MetaWord* allocate(size_t size); MetaWord* allocate(size_t size);
Dictionary* create_dictionary(); Dictionary* create_dictionary();
void initialize_name_and_klass(Handle class_loader);
public: public:
// GC interface. // GC interface.
void clear_claimed() { _claimed = 0; } void clear_claimed() { _claimed = 0; }
@ -340,9 +345,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
// Returns true if this class loader data is for the boot class loader. // Returns true if this class loader data is for the boot class loader.
// (Note that the class loader data may be anonymous.) // (Note that the class loader data may be anonymous.)
bool is_boot_class_loader_data() const { inline bool is_boot_class_loader_data() const;
return class_loader() == NULL;
}
bool is_builtin_class_loader_data() const; bool is_builtin_class_loader_data() const;
bool is_permanent_class_loader_data() const; bool is_permanent_class_loader_data() const;
@ -351,10 +354,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
// method will allocate a Metaspace if needed. // method will allocate a Metaspace if needed.
ClassLoaderMetaspace* metaspace_non_null(); ClassLoaderMetaspace* metaspace_non_null();
oop class_loader() const { return _class_loader; } inline oop class_loader() const;
// The object the GC is using to keep this ClassLoaderData alive.
oop keep_alive_object() const;
// Returns true if this class loader data is for a loader going away. // Returns true if this class loader data is for a loader going away.
bool is_unloading() const { bool is_unloading() const {
@ -363,7 +363,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
} }
// Used to refcount an anonymous class's CLD in order to // Used to refcount an anonymous class's CLD in order to
// indicate their aliveness without a keep_alive_object(). // indicate their aliveness.
void inc_keep_alive(); void inc_keep_alive();
void dec_keep_alive(); void dec_keep_alive();
@ -407,6 +407,9 @@ class ClassLoaderData : public CHeapObj<mtClass> {
static ClassLoaderData* class_loader_data_or_null(oop loader); static ClassLoaderData* class_loader_data_or_null(oop loader);
static ClassLoaderData* anonymous_class_loader_data(Handle loader); static ClassLoaderData* anonymous_class_loader_data(Handle loader);
Klass* class_loader_klass() const { return _class_loader_klass; }
Symbol* class_loader_name() const { return _class_loader_name; }
TRACE_DEFINE_TRACE_ID_METHODS; TRACE_DEFINE_TRACE_ID_METHODS;
}; };

View File

@ -28,6 +28,18 @@
#include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.hpp"
#include "classfile/javaClasses.hpp" #include "classfile/javaClasses.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "oops/oopHandle.inline.hpp"
#include "oops/weakHandle.inline.hpp"
inline oop ClassLoaderData::class_loader() const {
assert(!_unloading, "This oop is not available to unloading class loader data");
assert(_holder.is_null() || _holder.peek() != NULL , "This class loader data holder must be alive");
return _class_loader.resolve();
}
inline bool ClassLoaderData::is_boot_class_loader_data() const {
return class_loader() == NULL;
}
inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) { inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
if (loader == NULL) { if (loader == NULL) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 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
@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderStats.hpp" #include "classfile/classLoaderStats.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"

View File

@ -24,7 +24,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "jni.h" #include "jni.h"
#include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp" #include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp" #include "classfile/moduleEntry.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 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
@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/placeholders.hpp" #include "classfile/placeholders.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"

View File

@ -357,6 +357,14 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK
return pd; return pd;
} }
bool SystemDictionaryShared::is_sharing_possible(ClassLoaderData* loader_data) {
oop class_loader = loader_data->class_loader();
return (class_loader == NULL ||
(UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader) ||
SystemDictionary::is_platform_class_loader(class_loader)))
);
}
// Currently AppCDS only archives classes from the run-time image, the // Currently AppCDS only archives classes from the run-time image, the
// -Xbootclasspath/a path, the class path, and the module path. // -Xbootclasspath/a path, the class path, and the module path.
// //

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 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
@ -300,13 +300,7 @@ public:
} }
// Check if sharing is supported for the class loader. // Check if sharing is supported for the class loader.
static bool is_sharing_possible(ClassLoaderData* loader_data) { static bool is_sharing_possible(ClassLoaderData* loader_data);
oop class_loader = loader_data->class_loader();
return (class_loader == NULL ||
(UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader) ||
SystemDictionary::is_platform_class_loader(class_loader)))
);
}
static bool is_shared_class_visible_for_classloader(InstanceKlass* ik, static bool is_shared_class_visible_for_classloader(InstanceKlass* ik,
Handle class_loader, Handle class_loader,
const char* pkg_string, const char* pkg_string,

View File

@ -27,6 +27,7 @@
#include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1MonitoringSupport.hpp"
#include "gc/g1/g1Policy.hpp" #include "gc/g1/g1Policy.hpp"
#include "gc/shared/hSpaceCounters.hpp" #include "gc/shared/hSpaceCounters.hpp"
#include "memory/metaspaceCounters.hpp"
G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm, G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
const char* name, const char* name,

View File

@ -41,6 +41,7 @@
#include "gc/shared/gcLocker.hpp" #include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcWhen.hpp" #include "gc/shared/gcWhen.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"
#include "memory/metaspaceCounters.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/java.hpp" #include "runtime/java.hpp"

View File

@ -49,6 +49,7 @@
#include "gc/shared/weakProcessor.hpp" #include "gc/shared/weakProcessor.hpp"
#include "gc/shared/workgroup.hpp" #include "gc/shared/workgroup.hpp"
#include "memory/filemap.hpp" #include "memory/filemap.hpp"
#include "memory/metaspaceCounters.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "runtime/biasedLocking.hpp" #include "runtime/biasedLocking.hpp"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 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
@ -23,7 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp"
#include "classfile/moduleEntry.hpp" #include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectedHeap.hpp"

View File

@ -46,6 +46,7 @@
#include "memory/filemap.hpp" #include "memory/filemap.hpp"
#include "memory/metadataFactory.hpp" #include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp" #include "memory/metaspaceClosure.hpp"
#include "memory/metaspaceCounters.hpp"
#include "memory/metaspaceShared.hpp" #include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"

View File

@ -28,6 +28,7 @@
#include "classfile/classFileParser.hpp" #include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp" #include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp" #include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp" #include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp" #include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"

View File

@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/dictionary.hpp" #include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp" #include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"

View File

@ -46,7 +46,7 @@ public:
inline oop resolve() const; inline oop resolve() const;
// Used only for removing handle. // Used only for removing handle.
oop* ptr_raw() { return _obj; } oop* ptr_raw() const { return _obj; }
}; };
#endif // SHARE_VM_OOPS_OOPHANDLE_HPP #endif // SHARE_VM_OOPS_OOPHANDLE_HPP

View File

@ -51,8 +51,8 @@ template <WeakHandleType T>
void WeakHandle<T>::release() const { void WeakHandle<T>::release() const {
// Only release if the pointer to the object has been created. // Only release if the pointer to the object has been created.
if (_obj != NULL) { if (_obj != NULL) {
// Clear the WeakHandle. For class loader data race, the handle may not have // Clear the WeakHandle. For race in creating ClassLoaderData, we can release this
// been previously cleared by GC. // WeakHandle before it is cleared by GC.
RootAccess<ON_PHANTOM_OOP_REF>::oop_store(_obj, (oop)NULL); RootAccess<ON_PHANTOM_OOP_REF>::oop_store(_obj, (oop)NULL);
get_storage()->release(_obj); get_storage()->release(_obj);
} }

View File

@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectedHeap.hpp"
#include "memory/universe.hpp" #include "memory/universe.hpp"

View File

@ -543,7 +543,7 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
/*******************/ \ /*******************/ \
/* ClassLoaderData */ \ /* ClassLoaderData */ \
/*******************/ \ /*******************/ \
nonstatic_field(ClassLoaderData, _class_loader, oop) \ nonstatic_field(ClassLoaderData, _class_loader, OopHandle) \
nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \ nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \
volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \ volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \
nonstatic_field(ClassLoaderData, _is_anonymous, bool) \ nonstatic_field(ClassLoaderData, _is_anonymous, bool) \

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 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
@ -53,7 +53,7 @@
len = name->utf8_length(); \ len = name->utf8_length(); \
} \ } \
HOTSPOT_CLASS_##type( /* type = unloaded, loaded */ \ HOTSPOT_CLASS_##type( /* type = unloaded, loaded */ \
data, len, (void*)(clss)->class_loader(), (shared)); \ data, len, (void*)(clss)->class_loader_data(), (shared)); \
} }
#else // ndef DTRACE_ENABLED #else // ndef DTRACE_ENABLED

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 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
@ -25,7 +25,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "trace/traceStream.hpp" #include "trace/traceStream.hpp"
#if INCLUDE_TRACE #if INCLUDE_TRACE
#include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.inline.hpp" #include "classfile/javaClasses.inline.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "oops/klass.hpp" #include "oops/klass.hpp"

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
@ -42,14 +42,14 @@ public class ClassLoaderData extends VMObject {
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ClassLoaderData"); Type type = db.lookupType("ClassLoaderData");
classLoaderField = type.getOopField("_class_loader"); classLoaderField = type.getAddressField("_class_loader");
nextField = type.getAddressField("_next"); nextField = type.getAddressField("_next");
klassesField = new MetadataField(type.getAddressField("_klasses"), 0); klassesField = new MetadataField(type.getAddressField("_klasses"), 0);
isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0); isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
dictionaryField = type.getAddressField("_dictionary"); dictionaryField = type.getAddressField("_dictionary");
} }
private static sun.jvm.hotspot.types.OopField classLoaderField; private static AddressField classLoaderField;
private static AddressField nextField; private static AddressField nextField;
private static MetadataField klassesField; private static MetadataField klassesField;
private static CIntField isAnonymousField; private static CIntField isAnonymousField;
@ -72,7 +72,13 @@ public class ClassLoaderData extends VMObject {
} }
public Oop getClassLoader() { public Oop getClassLoader() {
return VM.getVM().getObjectHeap().newOop(classLoaderField.getValue(getAddress())); Address handle = classLoaderField.getValue(getAddress());
if (handle != null) {
// Load through the handle
OopHandle refs = handle.getOopHandleAt(0);
return (Instance)VM.getVM().getObjectHeap().newOop(refs);
}
return null;
} }
public boolean getIsAnonymous() { public boolean getIsAnonymous() {