Skip to content
This repository has been archived by the owner on Apr 24, 2023. It is now read-only.

Commit

Permalink
8298084: Memory leak in Method::build_profiling_method_data
Browse files Browse the repository at this point in the history
Co-authored-by: Justin King <jcking@openjdk.org>
Reviewed-by: kbarrett, eosterlund, dholmes, jcking, thartmann
  • Loading branch information
coleenp and jcking committed Dec 13, 2022
1 parent d453190 commit 04b8d0c
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 18 deletions.
14 changes: 11 additions & 3 deletions src/hotspot/share/memory/metadataFactory.hpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, 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
Expand Down Expand Up @@ -30,6 +30,7 @@
#include "oops/array.inline.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/globalDefinitions.hpp"
#include <type_traits>

class MetadataFactory : AllStatic {
public:
Expand Down Expand Up @@ -61,14 +62,21 @@ class MetadataFactory : AllStatic {

// Deallocation method for metadata
template <class T>
static void free_metadata(ClassLoaderData* loader_data, T md) {
static void free_metadata(ClassLoaderData* loader_data, T* md) {
if (md != NULL) {
assert(loader_data != NULL, "shouldn't pass null");
int size = md->size();
// Call metadata's deallocate function which will call deallocate fields
// Call metadata's deallocate function which will deallocate fields and release_C_heap_structures
assert(!md->on_stack(), "can't deallocate things on stack");
assert(!md->is_shared(), "cannot deallocate if in shared spaces");
md->deallocate_contents(loader_data);
// Call the destructor. This is currently used for MethodData which has a member
// that needs to be destructed to release resources. Most Metadata derived classes have noop
// destructors and/or cleanup using deallocate_contents.
// T is a potentially const or volatile qualified pointer. Remove any const
// or volatile so we can call the destructor of the type T points to.
using U = std::remove_cv_t<T>;
md->~U();
loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, md->is_klass());
}
}
Expand Down
18 changes: 10 additions & 8 deletions src/hotspot/share/oops/instanceKlass.cpp
Expand Up @@ -595,10 +595,10 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {

// Release C heap allocated data that this points to, which includes
// reference counting symbol names.
// Can't release the constant pool here because the constant pool can be
// deallocated separately from the InstanceKlass for default methods and
// redefine classes.
release_C_heap_structures(/* release_constant_pool */ false);
// Can't release the constant pool or MethodData C heap data here because the constant
// pool can be deallocated separately from the InstanceKlass for default methods and
// redefine classes. MethodData can also be released separately.
release_C_heap_structures(/* release_sub_metadata */ false);

deallocate_methods(loader_data, methods());
set_methods(NULL);
Expand Down Expand Up @@ -2650,13 +2650,15 @@ static void method_release_C_heap_structures(Method* m) {
m->release_C_heap_structures();
}

// Called also by InstanceKlass::deallocate_contents, with false for release_constant_pool.
void InstanceKlass::release_C_heap_structures(bool release_constant_pool) {
// Called also by InstanceKlass::deallocate_contents, with false for release_sub_metadata.
void InstanceKlass::release_C_heap_structures(bool release_sub_metadata) {
// Clean up C heap
Klass::release_C_heap_structures();

// Deallocate and call destructors for MDO mutexes
methods_do(method_release_C_heap_structures);
if (release_sub_metadata) {
methods_do(method_release_C_heap_structures);
}

// Destroy the init_monitor
delete _init_monitor;
Expand Down Expand Up @@ -2696,7 +2698,7 @@ void InstanceKlass::release_C_heap_structures(bool release_constant_pool) {

FREE_C_HEAP_ARRAY(char, _source_debug_extension);

if (release_constant_pool) {
if (release_sub_metadata) {
constants()->release_C_heap_structures();
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/oops/instanceKlass.hpp
Expand Up @@ -1012,7 +1012,7 @@ class InstanceKlass: public Klass {
// callbacks for actions during class unloading
static void unload_class(InstanceKlass* ik);

virtual void release_C_heap_structures(bool release_constant_pool = true);
virtual void release_C_heap_structures(bool release_sub_metadata = true);

// Naming
const char* signature_name() const;
Expand Down
7 changes: 3 additions & 4 deletions src/hotspot/share/oops/method.cpp
Expand Up @@ -141,10 +141,9 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) {

void Method::release_C_heap_structures() {
if (method_data()) {
#if INCLUDE_JVMCI
FailedSpeculation::free_failed_speculations(method_data()->get_failed_speculations_address());
#endif
// Destroy MethodData
method_data()->release_C_heap_structures();

// Destroy MethodData embedded lock
method_data()->~MethodData();
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/hotspot/share/oops/methodData.cpp
Expand Up @@ -1821,3 +1821,13 @@ void MethodData::clean_weak_method_links() {
clean_extra_data(&cl);
verify_extra_data_clean(&cl);
}

void MethodData::deallocate_contents(ClassLoaderData* loader_data) {
release_C_heap_structures();
}

void MethodData::release_C_heap_structures() {
#if INCLUDE_JVMCI
FailedSpeculation::free_failed_speculations(get_failed_speculations_address());
#endif
}
5 changes: 3 additions & 2 deletions src/hotspot/share/oops/methodData.hpp
Expand Up @@ -2449,8 +2449,9 @@ class MethodData : public Metadata {
virtual void metaspace_pointers_do(MetaspaceClosure* iter);
virtual MetaspaceObj::Type type() const { return MethodDataType; }

// Deallocation support - no metaspace pointer fields to deallocate
void deallocate_contents(ClassLoaderData* loader_data) {}
// Deallocation support
void deallocate_contents(ClassLoaderData* loader_data);
void release_C_heap_structures();

// GC support
void set_size(int object_size_in_bytes) { _size = object_size_in_bytes; }
Expand Down

1 comment on commit 04b8d0c

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.