8027237: New tests on ReservedSpace/VirtualSpace classes
authormgerdin
Fri, 08 Nov 2013 16:48:21 +0100
changeset 21554 20b1821f4fbd
parent 21522 bf65f0da83ea
child 21555 2f66a8ee6265
8027237: New tests on ReservedSpace/VirtualSpace classes Summary: Three tests added: 1) test stressing VirtualSpace by resizing it constantly 2) test running unit tests in several threads 3) test checking protected area in ReservedHeapSpace class Reviewed-by: stefank, zgu Contributed-by: aleksey.timofeev@oracle.com
hotspot/src/share/vm/prims/whitebox.cpp
hotspot/test/runtime/memory/ReadFromNoaccessArea.java
hotspot/test/runtime/memory/RunUnitTestsConcurrently.java
hotspot/test/runtime/memory/StressVirtualSpaceResize.java
hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Sat Nov 02 20:56:18 2013 +0100
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Fri Nov 08 16:48:21 2013 +0100
@@ -53,6 +53,8 @@
 #include "compiler/compileBroker.hpp"
 #include "runtime/compilationPolicy.hpp"
 
+#define SIZE_T_MAX_VALUE ((size_t) -1)
+
 bool WhiteBox::_used = false;
 
 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
@@ -109,6 +111,112 @@
 }
 WB_END
 
+#ifndef PRODUCT
+// Forward declaration
+void TestReservedSpace_test();
+void TestReserveMemorySpecial_test();
+void TestVirtualSpace_test();
+void TestMetaspaceAux_test();
+#endif
+
+WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o))
+#ifndef PRODUCT
+  TestReservedSpace_test();
+  TestReserveMemorySpecial_test();
+  TestVirtualSpace_test();
+  TestMetaspaceAux_test();
+#endif
+WB_END
+
+WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
+  size_t granularity = os::vm_allocation_granularity();
+  ReservedHeapSpace rhs(100 * granularity, granularity, false, NULL);
+  VirtualSpace vs;
+  vs.initialize(rhs, 50 * granularity);
+
+  //Check if constraints are complied
+  if (!( UseCompressedOops && rhs.base() != NULL &&
+         Universe::narrow_oop_base() != NULL &&
+         Universe::narrow_oop_use_implicit_null_checks() )) {
+    tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
+                  "\tUseCompressedOops is %d\n"
+                  "\trhs.base() is "PTR_FORMAT"\n"
+                  "\tUniverse::narrow_oop_base() is "PTR_FORMAT"\n"
+                  "\tUniverse::narrow_oop_use_implicit_null_checks() is %d",
+                  UseCompressedOops,
+                  rhs.base(),
+                  Universe::narrow_oop_base(),
+                  Universe::narrow_oop_use_implicit_null_checks());
+    return;
+  }
+  tty->print_cr("Reading from no access area... ");
+  tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
+                *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
+WB_END
+
+static jint wb_stress_virtual_space_resize(size_t reserved_space_size,
+                                           size_t magnitude, size_t iterations) {
+  size_t granularity = os::vm_allocation_granularity();
+  ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false, NULL);
+  VirtualSpace vs;
+  if (!vs.initialize(rhs, 0)) {
+    tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
+    return 3;
+  }
+
+  long seed = os::random();
+  tty->print_cr("Random seed is %ld", seed);
+  os::init_random(seed);
+
+  for (size_t i = 0; i < iterations; i++) {
+
+    // Whether we will shrink or grow
+    bool shrink = os::random() % 2L == 0;
+
+    // Get random delta to resize virtual space
+    size_t delta = (size_t)os::random() % magnitude;
+
+    // If we are about to shrink virtual space below zero, then expand instead
+    if (shrink && vs.committed_size() < delta) {
+      shrink = false;
+    }
+
+    // Resizing by delta
+    if (shrink) {
+      vs.shrink_by(delta);
+    } else {
+      // If expanding fails expand_by will silently return false
+      vs.expand_by(delta, true);
+    }
+  }
+  return 0;
+}
+
+WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
+        jlong reserved_space_size, jlong magnitude, jlong iterations))
+  tty->print_cr("reservedSpaceSize="JLONG_FORMAT", magnitude="JLONG_FORMAT", "
+                "iterations="JLONG_FORMAT"\n", reserved_space_size, magnitude,
+                iterations);
+  if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
+    tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
+    return 1;
+  }
+
+  // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
+  // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
+  if (sizeof(size_t) < sizeof(jlong)) {
+    jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
+    if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
+        || iterations > size_t_max_value) {
+      tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
+      return 2;
+    }
+  }
+
+  return wb_stress_virtual_space_resize((size_t) reserved_space_size,
+                                        (size_t) magnitude, (size_t) iterations);
+WB_END
+
 #if INCLUDE_ALL_GCS
 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
   G1CollectedHeap* g1 = G1CollectedHeap::heap();
@@ -445,6 +553,9 @@
   {CC"getCompressedOopsMaxHeapSize", CC"()J",
       (void*)&WB_GetCompressedOopsMaxHeapSize},
   {CC"printHeapSizes",     CC"()V",                   (void*)&WB_PrintHeapSizes    },
+  {CC"runMemoryUnitTests", CC"()V",                   (void*)&WB_RunMemoryUnitTests},
+  {CC"readFromNoaccessArea",CC"()V",                  (void*)&WB_ReadFromNoaccessArea},
+  {CC"stressVirtualSpaceResize",CC"(JJJ)I",           (void*)&WB_StressVirtualSpaceResize},
 #if INCLUDE_ALL_GCS
   {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
   {CC"g1IsHumongous",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/memory/ReadFromNoaccessArea.java	Fri Nov 08 16:48:21 2013 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test that touching noaccess area in class ReservedHeapSpace results in SIGSEGV/ACCESS_VIOLATION
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ReadFromNoaccessArea
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main ReadFromNoaccessArea
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class ReadFromNoaccessArea {
+
+  public static void main(String args[]) throws Exception {
+    if (!Platform.is64bit()) {
+      System.out.println("ReadFromNoaccessArea tests is useful only on 64bit architecture. Passing silently.");
+      return;
+    }
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+          "-Xbootclasspath/a:.",
+          "-XX:+UnlockDiagnosticVMOptions",
+          "-XX:+WhiteBoxAPI",
+          "-XX:+UseCompressedOops",
+          "-XX:HeapBaseMinAddress=33G",
+          DummyClassWithMainTryingToReadFromNoaccessArea.class.getName());
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    System.out.println("******* Printing stdout for analysis in case of failure *******");
+    System.out.println(output.getStdout());
+    System.out.println("******* Printing stderr for analysis in case of failure *******");
+    System.out.println(output.getStderr());
+    System.out.println("***************************************************************");
+    if (output.getStdout() != null && output.getStdout().contains("WB_ReadFromNoaccessArea method is useless")) {
+      // Test conditions broken. There is no protected page in ReservedHeapSpace in these circumstances. Silently passing test.
+      return;
+    }
+    if (Platform.isWindows()) {
+      output.shouldContain("EXCEPTION_ACCESS_VIOLATION");
+    } else if (Platform.isOSX()) {
+      output.shouldContain("SIGBUS");
+    } else {
+      output.shouldContain("SIGSEGV");
+    }
+  }
+
+  public static class DummyClassWithMainTryingToReadFromNoaccessArea {
+
+    // This method calls whitebox method reading from noaccess area
+    public static void main(String args[]) throws Exception {
+      WhiteBox.getWhiteBox().readFromNoaccessArea();
+      throw new Exception("Call of readFromNoaccessArea succeeded! This is wrong. Crash expected. Test failed.");
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java	Fri Nov 08 16:48:21 2013 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test launches unit tests inside vm concurrently
+ * @library /testlibrary /testlibrary/whitebox
+ * @build RunUnitTestsConcurrently
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI RunUnitTestsConcurrently 30 15000
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class RunUnitTestsConcurrently {
+
+  private static WhiteBox wb;
+  private static long timeout;
+  private static long timeStamp;
+
+  public static class Worker implements Runnable {
+    @Override
+    public void run() {
+      while (System.currentTimeMillis() - timeStamp < timeout) {
+        WhiteBox.getWhiteBox().runMemoryUnitTests();
+      }
+    }
+  }
+
+  public static void main(String[] args) throws InterruptedException {
+    if (!Platform.isDebugBuild() || !Platform.is64bit()) {
+      return;
+    }
+    wb = WhiteBox.getWhiteBox();
+    System.out.println("Starting threads");
+
+    int threads = Integer.valueOf(args[0]);
+    timeout = Long.valueOf(args[1]);
+
+    timeStamp = System.currentTimeMillis();
+
+    Thread[] threadsArray = new Thread[threads];
+    for (int i = 0; i < threads; i++) {
+      threadsArray[i] = new Thread(new Worker());
+      threadsArray[i].start();
+    }
+    for (int i = 0; i < threads; i++) {
+      threadsArray[i].join();
+    }
+
+    System.out.println("Quitting test.");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/memory/StressVirtualSpaceResize.java	Fri Nov 08 16:48:21 2013 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Stress test that expands/shrinks VirtualSpace
+ * @library /testlibrary /testlibrary/whitebox
+ * @build StressVirtualSpaceResize
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI StressVirtualSpaceResize
+ */
+
+import sun.hotspot.WhiteBox;
+
+public class StressVirtualSpaceResize {
+
+  public static void main(String args[]) throws Exception {
+    if (WhiteBox.getWhiteBox().stressVirtualSpaceResize(1000, 0xffffL, 0xffffL) != 0)
+      throw new RuntimeException("Whitebox method stressVirtualSpaceResize returned non zero exit code");
+  }
+}
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Sat Nov 02 20:56:18 2013 +0100
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Fri Nov 08 16:48:21 2013 +0100
@@ -144,4 +144,10 @@
 
   // force Full GC
   public native void fullGC();
+
+  // Tests on ReservedSpace/VirtualSpace classes
+  public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations);
+  public native void runMemoryUnitTests();
+  public native void readFromNoaccessArea();
+
 }