8203174: [Graal] JDI tests fail with Unexpected exception: com.sun.jdi.ObjectCollectedException
Reviewed-by: sspitsyn, cjplummer
--- a/test/hotspot/jtreg/ProblemList-graal.txt Thu Nov 15 09:45:18 2018 +0100
+++ b/test/hotspot/jtreg/ProblemList-graal.txt Thu Nov 15 09:56:49 2018 -0800
@@ -107,16 +107,6 @@
vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007/TestDescription.java 8195600 generic-all
-vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001/TestDescription.java 8203174 generic-all
-vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002/TestDescription.java 8203174 generic-all
-vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003/TestDescription.java 8203174 generic-all
-vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java 8203174 generic-all
-vmTestbase/nsk/jdi/ReferenceType/instances/instances003/instances003.java 8203174 generic-all
-vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents002/TestDescription.java 8203174 generic-all
-vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java 8203174 generic-all
-vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java 8203174 generic-all
-vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java 8203174 generic-all
-
vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/TestDescription.java 8195627 generic-all
vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028/TestDescription.java 8195627 generic-all
vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/TestDescription.java 8195627 generic-all
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001.java Thu Nov 15 09:45:18 2018 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001.java Thu Nov 15 09:56:49 2018 -0800
@@ -148,9 +148,23 @@
log1(" TESTING BEGINS");
for (int i = 0; ; i++) {
- pipe.println("newcheck");
+ pipe.println("newcheck");
+
+ // There are potentially other non-test Java threads allocating objects and triggering
+ // GC's so we need to suspend the target VM to avoid the objects created in the test
+ // from being accidentally GC'ed. However, we need the target VM temporary resumed
+ // while reading its response. Below we resume the target VM (if required) and suspend
+ // it only after pipe.readln() returns.
+
+ // On the first iteration the target VM is not suspended yet.
+ if (i > 0) {
+ debuggee.resume();
+ }
line = pipe.readln();
+ // Suspending target VM to prevent other non-test Java threads from triggering GCs.
+ debuggee.suspend();
+
if (line.equals("checkend")) {
log2(" : returned string is 'checkend'");
break ;
@@ -359,6 +373,7 @@
//-------------------------------------------------- test summary section
//------------------------------------------------- standard end section
+ debuggee.resume();
pipe.println("quit");
log2("waiting for the debuggee to finish ...");
debuggee.waitFor();
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002.java Thu Nov 15 09:45:18 2018 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002.java Thu Nov 15 09:56:49 2018 -0800
@@ -145,9 +145,23 @@
log1(" TESTING BEGINS");
for (int i = 0; ; i++) {
- pipe.println("newcheck");
+ pipe.println("newcheck");
+
+ // There are potentially other non-test Java threads allocating objects and triggering
+ // GC's so we need to suspend the target VM to avoid the objects created in the test
+ // from being accidentally GC'ed. However, we need the target VM temporary resumed
+ // while reading its response. Below we resume the target VM (if required) and suspend
+ // it only after pipe.readln() returns.
+
+ // On the first iteration the target VM is not suspended yet.
+ if (i > 0) {
+ debuggee.resume();
+ }
line = pipe.readln();
+ // Suspending target VM to prevent other non-test Java threads from triggering GCs.
+ debuggee.suspend();
+
if (line.equals("checkend")) {
log2(" : returned string is 'checkend'");
break ;
@@ -232,6 +246,7 @@
//-------------------------------------------------- test summary section
//------------------------------------------------- standard end section
+ debuggee.resume();
pipe.println("quit");
log2("waiting for the debuggee to finish ...");
debuggee.waitFor();
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003.java Thu Nov 15 09:45:18 2018 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003.java Thu Nov 15 09:56:49 2018 -0800
@@ -144,9 +144,23 @@
log1(" TESTING BEGINS");
for (int i = 0; ; i++) {
- pipe.println("newcheck");
+ pipe.println("newcheck");
+
+ // There are potentially other non-test Java threads allocating objects and triggering
+ // GC's so we need to suspend the target VM to avoid the objects created in the test
+ // from being accidentally GC'ed. However, we need the target VM temporary resumed
+ // while reading its response. Below we resume the target VM (if required) and suspend
+ // it only after pipe.readln() returns.
+
+ // On the first iteration the target VM is not suspended yet.
+ if (i > 0) {
+ debuggee.resume();
+ }
line = pipe.readln();
+ // Suspending target VM to prevent other non-test Java threads from triggering GCs.
+ debuggee.suspend();
+
if (line.equals("checkend")) {
log2(" : returned string is 'checkend'");
break ;
@@ -228,7 +242,7 @@
//-------------------------------------------------- test summary section
//------------------------------------------------- standard end section
-
+ debuggee.resume();
pipe.println("quit");
log2("waiting for the debuggee to finish ...");
debuggee.waitFor();
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java Thu Nov 15 09:45:18 2018 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java Thu Nov 15 09:56:49 2018 -0800
@@ -109,8 +109,22 @@
log.complain("Unexpected reference type: " + referenceType.getClass().getName() + ", expected is ArrayType");
return;
}
+ // There are potentially other non-test Java threads allocating objects and triggering GC's.
+ debuggee.suspend();
- baseInstances = referenceType.instances(0).size();
+ List<ObjectReference> baseReferences = new LinkedList<>();
+ // We need to call disableCollection() on each object returned by referenceType.instances()
+ // to deal with the case when GC was triggered before the suspend. Otherwise, these objects can
+ // be potentially collected.
+ for (ObjectReference objRef : referenceType.instances(0)) {
+ try {
+ objRef.disableCollection();
+ baseReferences.add(objRef);
+ } catch (ObjectCollectedException e) {
+ // skip this reference
+ }
+ }
+ baseInstances = baseReferences.size();
int createInstanceCount = 100;
int arraySize = 1;
@@ -129,8 +143,15 @@
checkDebugeeAnswer_instances(className, createInstanceCount + baseInstances);
- for (ArrayReference arrayReference : objectReferences)
+ for (ArrayReference arrayReference : objectReferences) {
arrayReference.enableCollection();
+ }
+
+ for (ObjectReference baseRef : baseReferences) {
+ baseRef.enableCollection();
+ }
+
+ debuggee.resume();
}
// test method ClassType.newInstance
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances003/instances003.java Thu Nov 15 09:45:18 2018 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances003/instances003.java Thu Nov 15 09:56:49 2018 -0800
@@ -62,6 +62,7 @@
import java.io.PrintStream;
import java.util.*;
+import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
@@ -122,9 +123,10 @@
// create temporary strong references to prevent the weakly referred instances being GCed
// during the time between creating them and disabling collection on them
+ boolean useTempStrongReference = needTempStongReference(referrerType);
pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + className + ":" + createInstanceCount +
- ":" + referrerCount + ":" + referrerType +
- (referrerType.equals(ObjectInstancesManager.WEAK_REFERENCE) ? "|" + ObjectInstancesManager.STRONG_REFERENCE : ""));
+ ":" + referrerCount + ":" + referrerType +
+ (useTempStrongReference ? "|" + ObjectInstancesManager.STRONG_REFERENCE : ""));
// Note! This test is broken, in the sense that it incorrectly assumes
// that no GC can happen before it walks the heap. In practice, it seems
@@ -135,14 +137,24 @@
checkDebugeeAnswer_instanceCounts(className, createInstanceCount, objectsToFilter);
ReferenceType referenceType = debuggee.classByName(className);
- List<ObjectReference> instances = HeapwalkingDebugger.filterObjectReferrence(objectsToFilter, referenceType.instances(0));
+ List<ObjectReference> allInstances = HeapwalkingDebugger.filterObjectReferrence(objectsToFilter, referenceType.instances(0));
- for (ObjectReference or : instances) {
- or.disableCollection();
+ // There are potentially other non-test Java threads allocating objects and triggering GC's.
+ // We need to call disableCollection() on each object returned by referenceType.instances()
+ // to deal with the case when GC was triggered. Otherwise, these objects can
+ // be potentially collected.
+ List<ObjectReference> instances = new LinkedList<>();
+ for (ObjectReference objRef : allInstances) {
+ try {
+ objRef.disableCollection();
+ instances.add(objRef);
+ } catch (ObjectCollectedException ex) {
+ // skip this references
+ }
}
// remove the temporary strong references so the weak references can be properly tested
- if (referrerType.equals(ObjectInstancesManager.WEAK_REFERENCE)) {
+ if (useTempStrongReference) {
pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_REFERRERS + ":" + className + ":" + referrerCount + ":" + ObjectInstancesManager.STRONG_REFERENCE);
if (!isDebuggeeReady()) {
return;
@@ -157,6 +169,7 @@
instances.get(i).enableCollection();
}
+
pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + className + ":" + createInstanceCount);
if (!isDebuggeeReady())
@@ -183,4 +196,13 @@
testClass(className, referenceType);
}
}
+
+
+ private static boolean needTempStongReference(String referenceType) {
+ return ObjectInstancesManager.WEAK_REFERENCE.equals(referenceType) ||
+ ObjectInstancesManager.JNI_WEAK_REFERENCE.equals(referenceType) ||
+ ObjectInstancesManager.PHANTOM_REFERENCE.equals(referenceType) ||
+ ObjectInstancesManager.SOFT_REFERENCE.equals(referenceType);
+
+ }
}
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/HeapwalkingDebuggee.java Thu Nov 15 09:45:18 2018 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/HeapwalkingDebuggee.java Thu Nov 15 09:56:49 2018 -0800
@@ -197,6 +197,21 @@
if (className.equals("byte[]"))
return false;
+ if (className.equals("boolean[]"))
+ return false;
+
+ if (className.equals("float[]"))
+ return false;
+
+ if (className.equals("long[]"))
+ return false;
+
+ if (className.equals("int[]"))
+ return false;
+
+ if (className.equals("double[]"))
+ return false;
+
if (className.equals("java.lang.Thread")) {
if (otherThreadPresent)
return false;