8335397: Improve reliability of TestRecursiveMonitorChurn.java

Reviewed-by: coleenp, rkennke, dholmes
This commit is contained in:
Axel Boldt-Christmas 2024-07-04 08:21:18 +00:00
parent 38a578d547
commit b20e8c8e85
5 changed files with 47 additions and 50 deletions

View File

@ -1115,6 +1115,10 @@ bool WhiteBox::compile_method(Method* method, int comp_level, int bci, JavaThrea
return false;
}
size_t WhiteBox::get_in_use_monitor_count() {
return ObjectSynchronizer::_in_use_list.count();
}
WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
@ -1850,6 +1854,10 @@ WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
return (jboolean) obj_oop->mark().has_monitor();
WB_END
WB_ENTRY(jlong, WB_getInUseMonitorCount(JNIEnv* env, jobject wb))
return (jlong) WhiteBox::get_in_use_monitor_count();
WB_END
WB_ENTRY(jint, WB_getLockStackCapacity(JNIEnv* env))
return (jint) LockStack::CAPACITY;
WB_END
@ -2844,6 +2852,7 @@ static JNINativeMethod methods[] = {
(void*)&WB_AddModuleExportsToAll },
{CC"deflateIdleMonitors", CC"()Z", (void*)&WB_DeflateIdleMonitors },
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
{CC"getInUseMonitorCount", CC"()J", (void*)&WB_getInUseMonitorCount },
{CC"getLockStackCapacity", CC"()I", (void*)&WB_getLockStackCapacity },
{CC"supportsRecursiveLightweightLocking", CC"()Z", (void*)&WB_supportsRecursiveLightweightLocking },
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },

View File

@ -68,6 +68,7 @@ class WhiteBox : public AllStatic {
JNINativeMethod* method_array, int method_count);
static void register_extended(JNIEnv* env, jclass wbclass, JavaThread* thread);
static bool compile_method(Method* method, int comp_level, int bci, JavaThread* THREAD);
static size_t get_in_use_monitor_count();
#ifdef LINUX
static bool validate_cgroup(const char* proc_cgroups, const char* proc_self_cgroup, const char* proc_self_mountinfo, u1* cg_flags);
#endif

View File

@ -69,6 +69,7 @@ public:
class ObjectSynchronizer : AllStatic {
friend class VMStructs;
friend class ObjectMonitorDeflationLogging;
friend class WhiteBox;
public:
typedef enum {

View File

@ -21,19 +21,21 @@
* questions.
*/
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* @test
* @summary Tests that recursive locking doesn't cause excessive native memory usage
* @library /test/lib
* @run driver TestRecursiveMonitorChurn
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -Xmx100M -XX:AsyncDeflationInterval=0 -XX:GuaranteedAsyncDeflationInterval=0
* -Xlog:monitorinflation=trace
* TestRecursiveMonitorChurn
*/
import jdk.test.whitebox.WhiteBox;
import jtreg.SkippedException;
public class TestRecursiveMonitorChurn {
static class Monitor {
public static volatile int i, j;
@ -46,50 +48,32 @@ public class TestRecursiveMonitorChurn {
}
}
static final WhiteBox WB = WhiteBox.getWhiteBox();
static final int LM_MONITOR = 0;
static final int COUNT = 100000;
public static volatile Monitor monitor;
public static void main(String[] args) throws IOException {
if (args.length == 1 && args[0].equals("test")) {
// The actual test, in a forked JVM.
for (int i = 0; i < 100000; i++) {
monitor = new Monitor();
monitor.doSomething();
public static void main(String[] args) {
if (WB.getIntVMFlag("LockingMode") == LM_MONITOR) {
throw new SkippedException("LM_MONITOR always inflates. Invalid test.");
}
final long pre_monitor_count = WB.getInUseMonitorCount();
System.out.println(" Precount = " + pre_monitor_count);
for (int i = 0; i < COUNT; i++) {
monitor = new Monitor();
monitor.doSomething();
}
System.out.println("i + j = " + (Monitor.i + Monitor.j));
final long post_monitor_count = WB.getInUseMonitorCount();
System.out.println("Postcount = " + post_monitor_count);
if (pre_monitor_count != post_monitor_count) {
final long monitor_count_change = post_monitor_count - pre_monitor_count;
System.out.println("Unexpected change in monitor count: " + monitor_count_change);
if (monitor_count_change < 0) {
throw new RuntimeException("Unexpected Deflation");
}
System.out.println("i + j = " + (Monitor.i + Monitor.j));
} else {
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions",
"-Xmx100M", "-XX:AsyncDeflationInterval=0", "-XX:GuaranteedAsyncDeflationInterval=0",
"-XX:NativeMemoryTracking=summary", "-XX:+PrintNMTStatistics",
"TestRecursiveMonitorChurn",
"test");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.reportDiagnosticSummary();
output.shouldHaveExitValue(0);
// We want to see, in the final NMT printout, a committed object monitor size that is reasonably low.
// Like this:
// - Object Monitors (reserved=208, committed=208)
// (malloc=208 #1) (at peak)
//
// Without recursive locking support, this would look more like this:
// - Object Monitors (reserved=20800624, committed=20800624)
// (malloc=20800624 #100003) (at peak)
Pattern pat = Pattern.compile("- *Object Monitors.*reserved=(\\d+), committed=(\\d+).*");
for (String line : output.asLines()) {
Matcher m = pat.matcher(line);
if (m.matches()) {
long reserved = Long.parseLong(m.group(1));
long committed = Long.parseLong(m.group(2));
System.out.println(">>>>> " + line + ": " + reserved + " - " + committed);
if (committed > 1000) {
throw new RuntimeException("Allocated too many monitors");
}
return;
}
}
throw new RuntimeException("Did not find expected NMT output");
throw new RuntimeException("Unexpected Inflation");
}
}
}

View File

@ -119,6 +119,8 @@ public class WhiteBox {
return isMonitorInflated0(obj);
}
public native long getInUseMonitorCount();
public native int getLockStackCapacity();
public native boolean supportsRecursiveLightweightLocking();