8201556: Disallow reading oops in ClassLoaderData if unloading
Summary: Move class_loader oop to an OopHandle, and assert that holder is alive when getting class_loader.
Reviewed-by: kbarrett, adinn
--- a/src/hotspot/share/classfile/classLoaderData.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -54,6 +54,7 @@
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
+#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
@@ -102,8 +103,25 @@
}
}
+// 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) :
- _class_loader(h_class_loader()),
_is_anonymous(is_anonymous),
// An anonymous class loader data doesn't have anything to keep
// it from being unloaded during parsing of the anonymous class.
@@ -114,9 +132,14 @@
_claimed(0), _modified_oops(true), _accumulated_modified_oops(false),
_jmethod_ids(NULL), _handles(), _deallocate_list(NULL),
_next(NULL),
+ _class_loader_klass(NULL), _class_loader_name(NULL),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
+ if (!h_class_loader.is_null()) {
+ _class_loader = _handles.add(h_class_loader());
+ }
+
if (!is_anonymous) {
// The holder is initialized later for anonymous classes, and before calling anything
// that call class_loader().
@@ -269,7 +292,6 @@
clear_modified_oops();
}
- f->do_oop(&_class_loader);
_handles.oops_do(f);
}
@@ -556,7 +578,7 @@
if (lt.is_enabled()) {
ResourceMark rm;
LogStream ls(lt);
- ls.print("unload ");
+ ls.print("unload");
print_value_on(&ls);
ls.cr();
}
@@ -631,7 +653,7 @@
// Unloading support
bool ClassLoaderData::is_alive() const {
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;
}
@@ -887,13 +909,23 @@
}
const char* ClassLoaderData::loader_name() const {
- // Handles null class loader
- return SystemDictionary::loader_name(class_loader());
+ 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
+ return SystemDictionary::loader_name(class_loader());
+ }
}
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));
class_loader()->print_value_on(out); // includes loader_name() and address of class loader instance
} else {
@@ -908,7 +940,7 @@
#ifndef PRODUCT
void ClassLoaderData::print_on(outputStream* out) const {
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 (claimed()) out->print(" claimed");
if (is_unloading()) out->print(" unloading");
@@ -962,10 +994,10 @@
// 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* 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
// 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);
@@ -1002,6 +1034,16 @@
} 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) {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->oops_do(f, must_claim);
--- a/src/hotspot/share/classfile/classLoaderData.hpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Wed Apr 18 18:43:04 2018 -0400
@@ -28,7 +28,6 @@
#include "memory/allocation.hpp"
#include "memory/memRegion.hpp"
#include "memory/metaspace.hpp"
-#include "memory/metaspaceCounters.hpp"
#include "oops/oopHandle.hpp"
#include "oops/weakHandle.hpp"
#include "runtime/mutex.hpp"
@@ -84,6 +83,7 @@
static volatile size_t _num_instance_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 void post_class_unload_events();
public:
@@ -220,8 +220,8 @@
static ClassLoaderData * _the_null_class_loader_data;
- ClassLoaderWeakHandle _holder; // The oop that determines lifetime of this class loader
- oop _class_loader; // The instance of java/lang/ClassLoader associated with
+ WeakHandle<vm_class_loader_data> _holder; // The oop that determines lifetime of this class loader
+ OopHandle _class_loader; // The instance of java/lang/ClassLoader associated with
// this ClassLoaderData
ClassLoaderMetaspace * volatile _metaspace; // Meta-space where meta-data defined by the
@@ -234,7 +234,7 @@
bool _modified_oops; // Card Table Equivalent (YC/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
// loader. _keep_alive does not need to be volatile or
// atomic since there is one unique CLD per anonymous class.
@@ -265,6 +265,9 @@
// Support for walking class loader data objects
ClassLoaderData* _next; /// Next loader_datas created
+ // JFR support
+ Klass* _class_loader_klass;
+ Symbol* _class_loader_name;
TRACE_DEFINE_TRACE_ID_FIELD;
void set_next(ClassLoaderData* next) { _next = next; }
@@ -305,6 +308,8 @@
MetaWord* allocate(size_t size);
Dictionary* create_dictionary();
+
+ void initialize_name_and_klass(Handle class_loader);
public:
// GC interface.
void clear_claimed() { _claimed = 0; }
@@ -340,9 +345,7 @@
// Returns true if this class loader data is for the boot class loader.
// (Note that the class loader data may be anonymous.)
- bool is_boot_class_loader_data() const {
- return class_loader() == NULL;
- }
+ inline bool is_boot_class_loader_data() const;
bool is_builtin_class_loader_data() const;
bool is_permanent_class_loader_data() const;
@@ -351,10 +354,7 @@
// method will allocate a Metaspace if needed.
ClassLoaderMetaspace* metaspace_non_null();
- oop class_loader() const { return _class_loader; }
-
- // The object the GC is using to keep this ClassLoaderData alive.
- oop keep_alive_object() const;
+ inline oop class_loader() const;
// Returns true if this class loader data is for a loader going away.
bool is_unloading() const {
@@ -363,7 +363,7 @@
}
// 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 dec_keep_alive();
@@ -407,6 +407,9 @@
static ClassLoaderData* class_loader_data_or_null(oop 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;
};
--- a/src/hotspot/share/classfile/classLoaderData.inline.hpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.inline.hpp Wed Apr 18 18:43:04 2018 -0400
@@ -28,6 +28,18 @@
#include "classfile/classLoaderData.hpp"
#include "classfile/javaClasses.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) {
if (loader == NULL) {
--- a/src/hotspot/share/classfile/classLoaderStats.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderStats.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderStats.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/classfile/moduleEntry.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/moduleEntry.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "jni.h"
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
#include "logging/log.hpp"
--- a/src/hotspot/share/classfile/placeholders.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/placeholders.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/placeholders.hpp"
#include "classfile/systemDictionary.hpp"
#include "oops/oop.inline.hpp"
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -357,6 +357,14 @@
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
// -Xbootclasspath/a path, the class path, and the module path.
//
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp Wed Apr 18 18:43:04 2018 -0400
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -300,13 +300,7 @@
}
// Check if sharing is supported for the class loader.
- 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_sharing_possible(ClassLoaderData* loader_data);
static bool is_shared_class_visible_for_classloader(InstanceKlass* ik,
Handle class_loader,
const char* pkg_string,
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -27,6 +27,7 @@
#include "gc/g1/g1MonitoringSupport.hpp"
#include "gc/g1/g1Policy.hpp"
#include "gc/shared/hSpaceCounters.hpp"
+#include "memory/metaspaceCounters.hpp"
G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
const char* name,
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -41,6 +41,7 @@
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcWhen.hpp"
#include "logging/log.hpp"
+#include "memory/metaspaceCounters.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -49,6 +49,7 @@
#include "gc/shared/weakProcessor.hpp"
#include "gc/shared/workgroup.hpp"
#include "memory/filemap.hpp"
+#include "memory/metaspaceCounters.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/biasedLocking.hpp"
--- a/src/hotspot/share/memory/heapInspection.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/memory/heapInspection.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp"
--- a/src/hotspot/share/memory/universe.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/memory/universe.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -46,6 +46,7 @@
#include "memory/filemap.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
+#include "memory/metaspaceCounters.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
--- a/src/hotspot/share/oops/instanceKlass.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -28,6 +28,7 @@
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp"
--- a/src/hotspot/share/oops/klass.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/oops/klass.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
--- a/src/hotspot/share/oops/oopHandle.hpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/oops/oopHandle.hpp Wed Apr 18 18:43:04 2018 -0400
@@ -46,7 +46,7 @@
inline oop resolve() const;
// Used only for removing handle.
- oop* ptr_raw() { return _obj; }
+ oop* ptr_raw() const { return _obj; }
};
#endif // SHARE_VM_OOPS_OOPHANDLE_HPP
--- a/src/hotspot/share/oops/weakHandle.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/oops/weakHandle.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -51,8 +51,8 @@
void WeakHandle<T>::release() const {
// Only release if the pointer to the object has been created.
if (_obj != NULL) {
- // Clear the WeakHandle. For class loader data race, the handle may not have
- // been previously cleared by GC.
+ // Clear the WeakHandle. For race in creating ClassLoaderData, we can release this
+ // WeakHandle before it is cleared by GC.
RootAccess<ON_PHANTOM_OOP_REF>::oop_store(_obj, (oop)NULL);
get_storage()->release(_obj);
}
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "memory/universe.hpp"
--- a/src/hotspot/share/runtime/vmStructs.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/runtime/vmStructs.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -543,7 +543,7 @@
/*******************/ \
/* ClassLoaderData */ \
/*******************/ \
- nonstatic_field(ClassLoaderData, _class_loader, oop) \
+ nonstatic_field(ClassLoaderData, _class_loader, OopHandle) \
nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \
volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \
nonstatic_field(ClassLoaderData, _is_anonymous, bool) \
--- a/src/hotspot/share/services/classLoadingService.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/services/classLoadingService.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@
len = name->utf8_length(); \
} \
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
--- a/src/hotspot/share/trace/traceStream.cpp Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/trace/traceStream.cpp Wed Apr 18 18:43:04 2018 -0400
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
#include "precompiled.hpp"
#include "trace/traceStream.hpp"
#if INCLUDE_TRACE
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/klass.hpp"
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Wed Apr 18 10:30:57 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Wed Apr 18 18:43:04 2018 -0400
@@ -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
@@ -42,14 +42,14 @@
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ClassLoaderData");
- classLoaderField = type.getOopField("_class_loader");
+ classLoaderField = type.getAddressField("_class_loader");
nextField = type.getAddressField("_next");
klassesField = new MetadataField(type.getAddressField("_klasses"), 0);
isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
dictionaryField = type.getAddressField("_dictionary");
}
- private static sun.jvm.hotspot.types.OopField classLoaderField;
+ private static AddressField classLoaderField;
private static AddressField nextField;
private static MetadataField klassesField;
private static CIntField isAnonymousField;
@@ -72,7 +72,13 @@
}
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() {