diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp
index 5ed593b0d2f..c480f8a09ac 100644
--- a/src/hotspot/share/prims/whitebox.cpp
+++ b/src/hotspot/share/prims/whitebox.cpp
@@ -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     },
diff --git a/src/hotspot/share/prims/whitebox.hpp b/src/hotspot/share/prims/whitebox.hpp
index a88f8d21843..c5072b97d4f 100644
--- a/src/hotspot/share/prims/whitebox.hpp
+++ b/src/hotspot/share/prims/whitebox.hpp
@@ -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
diff --git a/src/hotspot/share/runtime/synchronizer.hpp b/src/hotspot/share/runtime/synchronizer.hpp
index 7406af678e0..493303df661 100644
--- a/src/hotspot/share/runtime/synchronizer.hpp
+++ b/src/hotspot/share/runtime/synchronizer.hpp
@@ -69,6 +69,7 @@ public:
 class ObjectSynchronizer : AllStatic {
   friend class VMStructs;
   friend class ObjectMonitorDeflationLogging;
+  friend class WhiteBox;
 
  public:
   typedef enum {
diff --git a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java
index 47cb5613171..19dd90015bf 100644
--- a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java
+++ b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java
@@ -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");
         }
     }
 }
diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java
index 3b930aec16f..1bc309e2aec 100644
--- a/test/lib/jdk/test/whitebox/WhiteBox.java
+++ b/test/lib/jdk/test/whitebox/WhiteBox.java
@@ -119,6 +119,8 @@ public class WhiteBox {
     return isMonitorInflated0(obj);
   }
 
+  public native long getInUseMonitorCount();
+
   public native int getLockStackCapacity();
 
   public native boolean supportsRecursiveLightweightLocking();