mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-17 01:24:33 +02:00
8298084: Memory leak in Method::build_profiling_method_data
Co-authored-by: Justin King <jcking@openjdk.org> Reviewed-by: kbarrett, eosterlund, dholmes, jcking, thartmann
This commit is contained in:
parent
d453190300
commit
04b8d0cf5c
6 changed files with 38 additions and 18 deletions
|
@ -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.
|
* 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
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
#include "oops/array.inline.hpp"
|
#include "oops/array.inline.hpp"
|
||||||
#include "utilities/exceptions.hpp"
|
#include "utilities/exceptions.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
class MetadataFactory : AllStatic {
|
class MetadataFactory : AllStatic {
|
||||||
public:
|
public:
|
||||||
|
@ -61,14 +62,21 @@ class MetadataFactory : AllStatic {
|
||||||
|
|
||||||
// Deallocation method for metadata
|
// Deallocation method for metadata
|
||||||
template <class T>
|
template <class T>
|
||||||
static void free_metadata(ClassLoaderData* loader_data, T md) {
|
static void free_metadata(ClassLoaderData* loader_data, T* md) {
|
||||||
if (md != NULL) {
|
if (md != NULL) {
|
||||||
assert(loader_data != NULL, "shouldn't pass null");
|
assert(loader_data != NULL, "shouldn't pass null");
|
||||||
int size = md->size();
|
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->on_stack(), "can't deallocate things on stack");
|
||||||
assert(!md->is_shared(), "cannot deallocate if in shared spaces");
|
assert(!md->is_shared(), "cannot deallocate if in shared spaces");
|
||||||
md->deallocate_contents(loader_data);
|
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());
|
loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, md->is_klass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -595,10 +595,10 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
||||||
|
|
||||||
// Release C heap allocated data that this points to, which includes
|
// Release C heap allocated data that this points to, which includes
|
||||||
// reference counting symbol names.
|
// reference counting symbol names.
|
||||||
// Can't release the constant pool here because the constant pool can be
|
// Can't release the constant pool or MethodData C heap data here because the constant
|
||||||
// deallocated separately from the InstanceKlass for default methods and
|
// pool can be deallocated separately from the InstanceKlass for default methods and
|
||||||
// redefine classes.
|
// redefine classes. MethodData can also be released separately.
|
||||||
release_C_heap_structures(/* release_constant_pool */ false);
|
release_C_heap_structures(/* release_sub_metadata */ false);
|
||||||
|
|
||||||
deallocate_methods(loader_data, methods());
|
deallocate_methods(loader_data, methods());
|
||||||
set_methods(NULL);
|
set_methods(NULL);
|
||||||
|
@ -2650,13 +2650,15 @@ static void method_release_C_heap_structures(Method* m) {
|
||||||
m->release_C_heap_structures();
|
m->release_C_heap_structures();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called also by InstanceKlass::deallocate_contents, with false for release_constant_pool.
|
// Called also by InstanceKlass::deallocate_contents, with false for release_sub_metadata.
|
||||||
void InstanceKlass::release_C_heap_structures(bool release_constant_pool) {
|
void InstanceKlass::release_C_heap_structures(bool release_sub_metadata) {
|
||||||
// Clean up C heap
|
// Clean up C heap
|
||||||
Klass::release_C_heap_structures();
|
Klass::release_C_heap_structures();
|
||||||
|
|
||||||
// Deallocate and call destructors for MDO mutexes
|
// 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
|
// Destroy the init_monitor
|
||||||
delete _init_monitor;
|
delete _init_monitor;
|
||||||
|
@ -2696,7 +2698,7 @@ void InstanceKlass::release_C_heap_structures(bool release_constant_pool) {
|
||||||
|
|
||||||
FREE_C_HEAP_ARRAY(char, _source_debug_extension);
|
FREE_C_HEAP_ARRAY(char, _source_debug_extension);
|
||||||
|
|
||||||
if (release_constant_pool) {
|
if (release_sub_metadata) {
|
||||||
constants()->release_C_heap_structures();
|
constants()->release_C_heap_structures();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1012,7 +1012,7 @@ public:
|
||||||
// callbacks for actions during class unloading
|
// callbacks for actions during class unloading
|
||||||
static void unload_class(InstanceKlass* ik);
|
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
|
// Naming
|
||||||
const char* signature_name() const;
|
const char* signature_name() const;
|
||||||
|
|
|
@ -141,10 +141,9 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) {
|
||||||
|
|
||||||
void Method::release_C_heap_structures() {
|
void Method::release_C_heap_structures() {
|
||||||
if (method_data()) {
|
if (method_data()) {
|
||||||
#if INCLUDE_JVMCI
|
method_data()->release_C_heap_structures();
|
||||||
FailedSpeculation::free_failed_speculations(method_data()->get_failed_speculations_address());
|
|
||||||
#endif
|
// Destroy MethodData embedded lock
|
||||||
// Destroy MethodData
|
|
||||||
method_data()->~MethodData();
|
method_data()->~MethodData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1821,3 +1821,13 @@ void MethodData::clean_weak_method_links() {
|
||||||
clean_extra_data(&cl);
|
clean_extra_data(&cl);
|
||||||
verify_extra_data_clean(&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
|
||||||
|
}
|
||||||
|
|
|
@ -2449,8 +2449,9 @@ public:
|
||||||
virtual void metaspace_pointers_do(MetaspaceClosure* iter);
|
virtual void metaspace_pointers_do(MetaspaceClosure* iter);
|
||||||
virtual MetaspaceObj::Type type() const { return MethodDataType; }
|
virtual MetaspaceObj::Type type() const { return MethodDataType; }
|
||||||
|
|
||||||
// Deallocation support - no metaspace pointer fields to deallocate
|
// Deallocation support
|
||||||
void deallocate_contents(ClassLoaderData* loader_data) {}
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
|
void release_C_heap_structures();
|
||||||
|
|
||||||
// GC support
|
// GC support
|
||||||
void set_size(int object_size_in_bytes) { _size = object_size_in_bytes; }
|
void set_size(int object_size_in_bytes) { _size = object_size_in_bytes; }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue