mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-11 00:13:09 +00:00
8210559: ClassLoaderData Symbols can leak
Unrefcount the symbol names when the CLD is destroyed Reviewed-by: lfoltan, jiangli, iklam
This commit is contained in:
parent
b16e5584ab
commit
bad4a92e55
@ -769,6 +769,14 @@ ClassLoaderData::~ClassLoaderData() {
|
||||
if (_deallocate_list != NULL) {
|
||||
delete _deallocate_list;
|
||||
}
|
||||
|
||||
// Decrement refcounts of Symbols if created.
|
||||
if (_name != NULL) {
|
||||
_name->decrement_refcount();
|
||||
}
|
||||
if (_name_and_id != NULL) {
|
||||
_name_and_id->decrement_refcount();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if this class loader data is for the app class loader
|
||||
|
||||
@ -178,6 +178,15 @@ WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
|
||||
return closure.found();
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jint, WB_GetSymbolRefcount(JNIEnv* env, jobject unused, jstring name))
|
||||
oop h_name = JNIHandles::resolve(name);
|
||||
if (h_name == NULL) return false;
|
||||
Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_0);
|
||||
TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
|
||||
return (jint)sym->refcount();
|
||||
WB_END
|
||||
|
||||
|
||||
WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
|
||||
#if INCLUDE_JVMTI
|
||||
ResourceMark rm;
|
||||
@ -1982,7 +1991,6 @@ WB_ENTRY(jint, WB_ProtectionDomainRemovedCount(JNIEnv* env, jobject o))
|
||||
return (jint) SystemDictionary::pd_cache_table()->removed_entries_count();
|
||||
WB_END
|
||||
|
||||
|
||||
#define CC (char*)
|
||||
|
||||
static JNINativeMethod methods[] = {
|
||||
@ -1996,6 +2004,7 @@ static JNINativeMethod methods[] = {
|
||||
{CC"getHeapSpaceAlignment", CC"()J", (void*)&WB_GetHeapSpaceAlignment},
|
||||
{CC"getHeapAlignment", CC"()J", (void*)&WB_GetHeapAlignment},
|
||||
{CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
|
||||
{CC"getSymbolRefcount", CC"(Ljava/lang/String;)I", (void*)&WB_GetSymbolRefcount },
|
||||
{CC"parseCommandLine0",
|
||||
CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
|
||||
(void*) &WB_ParseCommandLine
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test UnloadTest
|
||||
* @bug 8210559
|
||||
* @requires vm.opt.final.ClassUnloading
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /runtime/testlibrary /test/lib
|
||||
@ -30,7 +31,7 @@
|
||||
* @build sun.hotspot.WhiteBox test.Empty
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI UnloadTest
|
||||
* @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xlog:class+unload=debug UnloadTest
|
||||
*/
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
@ -60,8 +61,16 @@ public class UnloadTest {
|
||||
|
||||
ClassUnloadCommon.failIf(!wb.isClassAlive(className), "should be live here");
|
||||
|
||||
String loaderName = cl.getName();
|
||||
int loadedRefcount = wb.getSymbolRefcount(loaderName);
|
||||
System.out.println("Refcount of symbol " + loaderName + " is " + loadedRefcount);
|
||||
|
||||
cl = null; c = null; o = null;
|
||||
ClassUnloadCommon.triggerUnloading();
|
||||
ClassUnloadCommon.failIf(wb.isClassAlive(className), "should have been unloaded");
|
||||
|
||||
int unloadedRefcount = wb.getSymbolRefcount(loaderName);
|
||||
System.out.println("Refcount of symbol " + loaderName + " is " + unloadedRefcount);
|
||||
ClassUnloadCommon.failIf(unloadedRefcount != (loadedRefcount - 1), "Refcount must be decremented");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -73,7 +73,7 @@ public class ClassUnloadCommon {
|
||||
.map(Paths::get)
|
||||
.map(ClassUnloadCommon::toURL)
|
||||
.toArray(URL[]::new);
|
||||
return new URLClassLoader(urls) {
|
||||
return new URLClassLoader("ClassUnloadCommonClassLoader", urls, new ClassUnloadCommon().getClass().getClassLoader()) {
|
||||
@Override
|
||||
public Class<?> loadClass(String cn, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
|
||||
@ -103,6 +103,7 @@ public class WhiteBox {
|
||||
return isClassAlive0(name.replace('.', '/'));
|
||||
}
|
||||
private native boolean isClassAlive0(String name);
|
||||
public native int getSymbolRefcount(String name);
|
||||
|
||||
private native boolean isMonitorInflated0(Object obj);
|
||||
public boolean isMonitorInflated(Object obj) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user