8297499: Parallel: Missing iteration over klass when marking objArrays/objArrayOops during Full GC

Co-authored-by: Stefan Johansson <sjohanss@openjdk.org>
Reviewed-by: sjohanss, tschatzl
This commit is contained in:
Albert Mingkun Yang 2022-11-28 11:57:18 +00:00
parent b80f5af698
commit 6a856bc3f6
2 changed files with 52 additions and 12 deletions

View File

@ -164,10 +164,12 @@ inline void ParCompactionManager::update_contents(oop obj) {
inline void ParCompactionManager::follow_contents(oop obj) {
assert(PSParallelCompact::mark_bitmap()->is_marked(obj), "should be marked");
PCIterateMarkAndPushClosure cl(this, PSParallelCompact::ref_processor());
if (obj->is_objArray()) {
cl.do_klass(obj->klass());
follow_array(objArrayOop(obj), 0);
} else {
PCIterateMarkAndPushClosure cl(this, PSParallelCompact::ref_processor());
obj->oop_iterate(&cl);
}
}

View File

@ -35,29 +35,33 @@
import jdk.test.whitebox.WhiteBox;
import jdk.test.lib.classloader.ClassUnloadCommon;
import java.lang.reflect.Array;
/**
* Test that verifies that classes are unloaded when they are no longer reachable.
* Test that verifies that liveness of classes is correctly tracked.
*
* The test creates a class loader, uses the loader to load a class and creates an instance
* of that class. The it nulls out all the references to the instance, class and class loader
* and tries to trigger class unloading. Then it verifies that the class is no longer
* loaded by the VM.
* The test creates a class loader, uses the loader to load a class and creates
* an instance related to that class.
* 1. Then, it nulls out references to the class loader, triggers class
* unloading and verifies the class is *not* unloaded.
* 2. Next, it nulls out references to the instance, triggers class unloading
* and verifies the class is unloaded.
*/
public class UnloadTest {
private static String className = "test.Empty";
public static void main(String... args) throws Exception {
run();
test_unload_instance_klass();
test_unload_obj_array_klass();
}
private static void run() throws Exception {
private static void test_unload_instance_klass() throws Exception {
final String className = "test.Empty";
final WhiteBox wb = WhiteBox.getWhiteBox();
ClassUnloadCommon.failIf(wb.isClassAlive(className), "is not expected to be alive yet");
ClassLoader cl = ClassUnloadCommon.newClassLoader();
Class<?> c = cl.loadClass(className);
Object o = c.newInstance();
Object o = cl.loadClass(className).newInstance();
ClassUnloadCommon.failIf(!wb.isClassAlive(className), "should be live here");
@ -65,8 +69,42 @@ public class UnloadTest {
int loadedRefcount = wb.getSymbolRefcount(loaderName);
System.out.println("Refcount of symbol " + loaderName + " is " + loadedRefcount);
cl = null; c = null; o = null;
cl = null;
ClassUnloadCommon.triggerUnloading();
ClassUnloadCommon.failIf(!wb.isClassAlive(className), "should still be live");
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");
}
private static void test_unload_obj_array_klass() throws Exception {
final WhiteBox wb = WhiteBox.getWhiteBox();
ClassLoader cl = ClassUnloadCommon.newClassLoader();
Object o = Array.newInstance(cl.loadClass("test.Empty"), 1);
final String className = o.getClass().getName();
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;
ClassUnloadCommon.triggerUnloading();
ClassUnloadCommon.failIf(!wb.isClassAlive(className), "should still be live");
o = null;
ClassUnloadCommon.triggerUnloading();
ClassUnloadCommon.failIf(wb.isClassAlive(className), "should have been unloaded");
int unloadedRefcount = wb.getSymbolRefcount(loaderName);