8054823: Add size_t as a valid VM flag type
authorstefank
Mon, 11 Aug 2014 14:03:06 +0200
changeset 25959 6c11a6272b60
parent 25958 8dc85547d6d6
child 25960 729cd80956ae
child 26150 6186fcfeb5ae
child 26152 2e5e15618d8e
8054823: Add size_t as a valid VM flag type Reviewed-by: kvn, vlivanov, sla
hotspot/src/share/vm/prims/whitebox.cpp
hotspot/src/share/vm/runtime/arguments.cpp
hotspot/src/share/vm/runtime/globals.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/globals_extension.hpp
hotspot/src/share/vm/services/attachListener.cpp
hotspot/src/share/vm/services/management.cpp
hotspot/src/share/vm/utilities/bitMap.cpp
hotspot/test/gc/arguments/TestArrayAllocatorMallocLimit.java
hotspot/test/serviceability/attach/AttachSetGetFlag.java
hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Mon Aug 11 14:03:06 2014 +0200
@@ -597,6 +597,15 @@
   return NULL;
 WB_END
 
+WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
+  uintx result;
+  if (GetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAt)) {
+    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+    return longBox(thread, env, result);
+  }
+  return NULL;
+WB_END
+
 WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
   double result;
   if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
@@ -637,6 +646,11 @@
   SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
 WB_END
 
+WB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
+  size_t result = value;
+  SetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAtPut);
+WB_END
+
 WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
   double result = value;
   SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
@@ -880,6 +894,7 @@
   {CC"setIntxVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
   {CC"setUintxVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
   {CC"setUint64VMFlag",    CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
+  {CC"setSizeTVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag},
   {CC"setDoubleVMFlag",    CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
   {CC"setStringVMFlag",    CC"(Ljava/lang/String;Ljava/lang/String;)V",
                                                       (void*)&WB_SetStringVMFlag},
@@ -891,6 +906,8 @@
                                                       (void*)&WB_GetUintxVMFlag},
   {CC"getUint64VMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Long;",
                                                       (void*)&WB_GetUint64VMFlag},
+  {CC"getSizeTVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
+                                                      (void*)&WB_GetSizeTVMFlag},
   {CC"getDoubleVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Double;",
                                                       (void*)&WB_GetDoubleVMFlag},
   {CC"getStringVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/String;",
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Mon Aug 11 14:03:06 2014 +0200
@@ -686,6 +686,10 @@
   if (!is_neg && CommandLineFlags::uint64_tAtPut(name, &uint64_t_v, origin)) {
     return true;
   }
+  size_t size_t_v = (size_t) v;
+  if (!is_neg && CommandLineFlags::size_tAtPut(name, &size_t_v, origin)) {
+    return true;
+  }
   return false;
 }
 
--- a/hotspot/src/share/vm/runtime/globals.cpp	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/src/share/vm/runtime/globals.cpp	Mon Aug 11 14:03:06 2014 +0200
@@ -131,6 +131,19 @@
   *((uint64_t*) _addr) = value;
 }
 
+bool Flag::is_size_t() const {
+  return strcmp(_type, "size_t") == 0;
+}
+
+size_t Flag::get_size_t() const {
+  return *((size_t*) _addr);
+}
+
+void Flag::set_size_t(size_t value) {
+  check_writable();
+  *((size_t*) _addr) = value;
+}
+
 bool Flag::is_double() const {
   return strcmp(_type, "double") == 0;
 }
@@ -306,6 +319,9 @@
   if (is_uint64_t()) {
     st->print("%-16lu", get_uint64_t());
   }
+  if (is_size_t()) {
+    st->print(SIZE_FORMAT_W(-16), get_size_t());
+  }
   if (is_double()) {
     st->print("%-16f", get_double());
   }
@@ -395,6 +411,8 @@
     st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());
   } else if (is_uint64_t()) {
     st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());
+  } else if (is_size_t()) {
+    st->print("-XX:%s=" SIZE_FORMAT, _name, get_size_t());
   } else if (is_double()) {
     st->print("-XX:%s=%f", _name, get_double());
   } else if (is_ccstr()) {
@@ -723,6 +741,34 @@
   faddr->set_origin(origin);
 }
 
+bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value) {
+  Flag* result = Flag::find_flag(name, len);
+  if (result == NULL) return false;
+  if (!result->is_size_t()) return false;
+  *value = result->get_size_t();
+  return true;
+}
+
+bool CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) {
+  Flag* result = Flag::find_flag(name, len);
+  if (result == NULL) return false;
+  if (!result->is_size_t()) return false;
+  size_t old_value = result->get_size_t();
+  trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
+  result->set_size_t(*value);
+  *value = old_value;
+  result->set_origin(origin);
+  return true;
+}
+
+void CommandLineFlagsEx::size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin) {
+  Flag* faddr = address_of_flag(flag);
+  guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type");
+  trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_size_t(), value, origin);
+  faddr->set_size_t(value);
+  faddr->set_origin(origin);
+}
+
 bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
--- a/hotspot/src/share/vm/runtime/globals.hpp	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Mon Aug 11 14:03:06 2014 +0200
@@ -275,6 +275,10 @@
   uint64_t get_uint64_t() const;
   void set_uint64_t(uint64_t value);
 
+  bool is_size_t() const;
+  size_t get_size_t() const;
+  void set_size_t(size_t value);
+
   bool is_double() const;
   double get_double() const;
   void set_double(double value);
@@ -350,7 +354,6 @@
   ~UIntFlagSetting()                         { *flag = val; }
 };
 
-
 class DoubleFlagSetting {
   double val;
   double* flag;
@@ -359,6 +362,14 @@
   ~DoubleFlagSetting()                           { *flag = val; }
 };
 
+class SizeTFlagSetting {
+  size_t val;
+  size_t* flag;
+ public:
+  SizeTFlagSetting(size_t& fl, size_t newValue) { flag = &fl; val = fl; fl = newValue; }
+  ~SizeTFlagSetting()                           { *flag = val; }
+};
+
 
 class CommandLineFlags {
  public:
@@ -377,6 +388,11 @@
   static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin);
   static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
 
+  static bool size_tAt(const char* name, size_t len, size_t* value);
+  static bool size_tAt(const char* name, size_t* value)    { return size_tAt(name, strlen(name), value); }
+  static bool size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin);
+  static bool size_tAtPut(const char* name, size_t* value, Flag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); }
+
   static bool uint64_tAt(const char* name, size_t len, uint64_t* value);
   static bool uint64_tAt(const char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); }
   static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin);
@@ -3883,8 +3899,8 @@
   diagnostic(ccstr, SharedArchiveFile, NULL,                                \
           "Override the default location of the CDS archive file")          \
                                                                             \
-  experimental(uintx, ArrayAllocatorMallocLimit,                            \
-          SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx),                        \
+  experimental(size_t, ArrayAllocatorMallocLimit,                           \
+          SOLARIS_ONLY(64*K) NOT_SOLARIS((size_t)-1),                       \
           "Allocation less than this value will be allocated "              \
           "using malloc. Larger allocations will use mmap.")                \
                                                                             \
--- a/hotspot/src/share/vm/runtime/globals_extension.hpp	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/src/share/vm/runtime/globals_extension.hpp	Mon Aug 11 14:03:06 2014 +0200
@@ -200,6 +200,7 @@
   static void intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin);
   static void uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin);
   static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin);
+  static void size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin);
   static void doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin);
   // Contract:  Flag will make private copy of the incoming value
   static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin);
--- a/hotspot/src/share/vm/services/attachListener.cpp	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/src/share/vm/services/attachListener.cpp	Mon Aug 11 14:03:06 2014 +0200
@@ -320,6 +320,25 @@
   return res? JNI_OK : JNI_ERR;
 }
 
+// set a size_t global flag using value from AttachOperation
+static jint set_size_t_flag(const char* name, AttachOperation* op, outputStream* out) {
+  size_t value;
+  const char* arg1;
+  if ((arg1 = op->arg(1)) != NULL) {
+    int n = sscanf(arg1, SIZE_FORMAT, &value);
+    if (n != 1) {
+      out->print_cr("flag value must be an unsigned integer");
+      return JNI_ERR;
+    }
+  }
+  bool res = CommandLineFlags::size_tAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND);
+  if (! res) {
+    out->print_cr("setting flag %s failed", name);
+  }
+
+  return res? JNI_OK : JNI_ERR;
+}
+
 // set a string global flag using value from AttachOperation
 static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) {
   const char* value;
@@ -356,6 +375,8 @@
       return set_uintx_flag(name, op, out);
     } else if (f->is_uint64_t()) {
       return set_uint64_t_flag(name, op, out);
+    } else if (f->is_size_t()) {
+      return set_size_t_flag(name, op, out);
     } else if (f->is_ccstr()) {
       return set_ccstr_flag(name, op, out);
     } else {
--- a/hotspot/src/share/vm/services/management.cpp	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/src/share/vm/services/management.cpp	Mon Aug 11 14:03:06 2014 +0200
@@ -1696,6 +1696,9 @@
   } else if (flag->is_uint64_t()) {
     global->value.j = (jlong)flag->get_uint64_t();
     global->type = JMM_VMGLOBAL_TYPE_JLONG;
+  } else if (flag->is_size_t()) {
+    global->value.j = (jlong)flag->get_size_t();
+    global->type = JMM_VMGLOBAL_TYPE_JLONG;
   } else if (flag->is_ccstr()) {
     Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false);
     global->value.l = (jobject)JNIHandles::make_local(env, str());
@@ -1851,6 +1854,9 @@
   } else if (flag->is_uint64_t()) {
     uint64_t uvalue = (uint64_t)new_value.j;
     succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, Flag::MANAGEMENT);
+  } else if (flag->is_size_t()) {
+    size_t svalue = (size_t)new_value.j;
+    succeed = CommandLineFlags::size_tAtPut(name, &svalue, Flag::MANAGEMENT);
   } else if (flag->is_ccstr()) {
     oop str = JNIHandles::resolve_external_guard(new_value.l);
     if (str == NULL) {
--- a/hotspot/src/share/vm/utilities/bitMap.cpp	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp	Mon Aug 11 14:03:06 2014 +0200
@@ -567,7 +567,7 @@
   }
 
   static void testResizeNonResource() {
-    const uintx bitmap_bytes = BITMAP_SIZE / BitsPerByte;
+    const size_t bitmap_bytes = BITMAP_SIZE / BitsPerByte;
 
     // Test the default behavior
     testResize(false);
@@ -575,13 +575,13 @@
     {
       // Make sure that AllocatorMallocLimit is larger than our allocation request
       // forcing it to call standard malloc()
-      UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4);
+      SizeTFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4);
       testResize(false);
     }
     {
       // Make sure that AllocatorMallocLimit is smaller than our allocation request
       // forcing it to call mmap() (or equivalent)
-      UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4);
+      SizeTFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4);
       testResize(false);
     }
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestArrayAllocatorMallocLimit.java	Mon Aug 11 14:03:06 2014 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 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 TestArrayAllocatorMallocLimit
+ * @summary Sanity check that the ArrayAllocatorMallocLimit flag can be set.
+ * The test helps verifying that size_t flags can be set/read.
+ * @bug 8054823
+ * @key gc
+ * @library /testlibrary
+ * @run driver TestArrayAllocatorMallocLimit
+ */
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+import java.math.BigInteger;
+
+public class TestArrayAllocatorMallocLimit {
+  public static void main(String [] args) throws Exception {
+    testDefaultValue();
+    testSetValue();
+  }
+
+  private static final String flagName = "ArrayAllocatorMallocLimit";
+
+  //     size_t ArrayAllocatorMallocLimit                 = 18446744073709551615{experimental}
+  private static final String printFlagsFinalPattern = " *size_t *" + flagName + " *:?= *(\\d+) *\\{experimental\\} *";
+
+  public static void testDefaultValue()  throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:+UnlockExperimentalVMOptions", "-XX:+PrintFlagsFinal", "-version");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    String value = output.firstMatch(printFlagsFinalPattern, 1);
+
+    try {
+      Asserts.assertNotNull(value, "Couldn't find size_t flag " + flagName);
+
+      // A size_t is not always parseable with Long.parseValue,
+      // use BigInteger instead.
+      BigInteger biValue = new BigInteger(value);
+
+      // Sanity check that we got a non-zero value.
+      Asserts.assertNotEquals(biValue, "0");
+
+      output.shouldHaveExitValue(0);
+    } catch (Exception e) {
+      System.err.println(output.getOutput());
+      throw e;
+    }
+  }
+
+  public static void testSetValue() throws Exception {
+    long flagValue = 2048;
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:+UnlockExperimentalVMOptions", "-XX:" + flagName + "=" + flagValue, "-XX:+PrintFlagsFinal", "-version");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    String value = output.firstMatch(printFlagsFinalPattern, 1);
+
+    try {
+      Asserts.assertNotNull("Couldn't find size_t flag " + flagName);
+
+      long longValue = Long.parseLong(value);
+
+      Asserts.assertEquals(longValue, flagValue);
+
+      output.shouldHaveExitValue(0);
+    } catch (Exception e) {
+      System.err.println(output.getOutput());
+      throw e;
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/attach/AttachSetGetFlag.java	Mon Aug 11 14:03:06 2014 +0200
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2014, 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
+ * @bug 8054823
+ * @summary Tests the setFlag and printFlag attach command
+ * @library /testlibrary
+ * @build com.oracle.java.testlibrary.* AttachSetGetFlag
+ * @run driver AttachSetGetFlag
+ */
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import sun.tools.attach.HotSpotVirtualMachine;
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.ProcessTools;
+import com.sun.tools.attach.VirtualMachine;
+
+public class AttachSetGetFlag {
+
+  public static void main(String... args) throws Exception {
+    // Test a manageable uintx flag.
+    testGetFlag("MaxHeapFreeRatio", "60");
+    testSetFlag("MaxHeapFreeRatio", "50", "60");
+
+    // Test a non-manageable size_t flag.
+    // Since it is not manageable, we can't test the setFlag functionality.
+    testGetFlag("ArrayAllocatorMallocLimit", "128");
+    // testSetFlag("ArrayAllocatorMallocLimit", "64", "128");
+  }
+
+  public static ProcessBuilder runTarget(String flagName, String flagValue) throws Exception {
+    return ProcessTools.createJavaProcessBuilder(
+        "-XX:+UnlockExperimentalVMOptions",
+        "-XX:" + flagName + "=" + flagValue,
+        "AttachSetGetFlag$Target");
+  }
+
+  public static void testGetFlag(String flagName, String flagValue) throws Exception {
+    ProcessBuilder pb = runTarget(flagName, flagValue);
+
+    Process target = pb.start();
+
+    try {
+      waitForReady(target);
+
+      int pid = (int)target.getPid();
+
+      HotSpotVirtualMachine vm = (HotSpotVirtualMachine)VirtualMachine.attach(((Integer)pid).toString());
+
+      // Test Get
+      BufferedReader remoteDataReader = new BufferedReader(new InputStreamReader(
+          vm.printFlag(flagName)));
+
+      boolean foundExpectedLine = false;
+
+      String line = null;
+      while((line = remoteDataReader.readLine()) != null) {
+        System.out.println("printFlag: " + line);
+        if (line.equals("-XX:" + flagName + "=" + flagValue)) {
+          foundExpectedLine = true;
+        }
+      }
+
+      Asserts.assertTrue(foundExpectedLine, "Didn't get the expected output: '-XX:" + flagName + "=" + flagValue + "'");
+
+      vm.detach();
+    }
+    finally {
+      target.destroy();
+      target.waitFor();
+    }
+  }
+
+  public static void testSetFlag(String flagName, String initialFlagValue, String flagValue) throws Exception {
+    ProcessBuilder pb = runTarget(flagName, initialFlagValue);
+
+    Process target = pb.start();
+
+    try {
+      waitForReady(target);
+
+      int pid = (int)target.getPid();
+
+      HotSpotVirtualMachine vm = (HotSpotVirtualMachine)VirtualMachine.attach(((Integer)pid).toString());
+
+      // First set the value.
+      BufferedReader remoteDataReader = new BufferedReader(new InputStreamReader(
+          vm.setFlag(flagName, flagValue)));
+
+      String line;
+      while((line = remoteDataReader.readLine()) != null) {
+        System.out.println("setFlag: " + line);
+        // Just empty the stream.
+      }
+      remoteDataReader.close();
+
+      // Then read and make sure we get back the set value.
+      remoteDataReader = new BufferedReader(new InputStreamReader(vm.printFlag(flagName)));
+
+      boolean foundExpectedLine = false;
+      line = null;
+      while((line = remoteDataReader.readLine()) != null) {
+        System.out.println("getFlag: " + line);
+        if (line.equals("-XX:" + flagName + "=" + flagValue)) {
+          foundExpectedLine = true;
+        }
+      }
+
+      Asserts.assertTrue(foundExpectedLine, "Didn't get the expected output: '-XX:" + flagName + "=" + flagValue + "'");
+
+      vm.detach();
+
+    } finally {
+      target.destroy();
+      target.waitFor();
+    }
+  }
+
+  private static void waitForReady(Process target) throws Exception {
+    InputStream os = target.getInputStream();
+    try (BufferedReader reader = new BufferedReader(new InputStreamReader(os))) {
+      String line;
+      while ((line = reader.readLine()) != null) {
+        if ("Ready".equals(line)) {
+          return;
+        }
+      }
+    }
+  }
+
+
+  public static class Target {
+    public static void main(String [] args) throws Exception {
+      System.out.println("Ready");
+      System.out.flush();
+      while (true) {
+        Thread.sleep(1000);
+      }
+    }
+  }
+}
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Mon Aug 11 17:12:41 2014 +0400
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Mon Aug 11 14:03:06 2014 +0200
@@ -167,17 +167,20 @@
   public native void    setIntxVMFlag(String name, long value);
   public native void    setUintxVMFlag(String name, long value);
   public native void    setUint64VMFlag(String name, long value);
+  public native void    setSizeTVMFlag(String name, long value);
   public native void    setStringVMFlag(String name, String value);
   public native void    setDoubleVMFlag(String name, double value);
   public native Boolean getBooleanVMFlag(String name);
   public native Long    getIntxVMFlag(String name);
   public native Long    getUintxVMFlag(String name);
   public native Long    getUint64VMFlag(String name);
+  public native Long    getSizeTVMFlag(String name);
   public native String  getStringVMFlag(String name);
   public native Double  getDoubleVMFlag(String name);
   private final List<Function<String,Object>> flagsGetters = Arrays.asList(
     this::getBooleanVMFlag, this::getIntxVMFlag, this::getUintxVMFlag,
-    this::getUint64VMFlag, this::getStringVMFlag, this::getDoubleVMFlag);
+    this::getUint64VMFlag, this::getSizeTVMFlag, this::getStringVMFlag,
+    this::getDoubleVMFlag);
 
   public Object getVMFlag(String name) {
     return flagsGetters.stream()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java	Mon Aug 11 14:03:06 2014 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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 SizeTTest
+ * @bug 8054823
+ * @library /testlibrary /testlibrary/whitebox
+ * @build SizeTTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions SizeTTest
+ * @summary testing of WB::set/getSizeTVMFlag()
+ */
+import com.oracle.java.testlibrary.Platform;
+
+public class SizeTTest {
+    private static final String FLAG_NAME = "ArrayAllocatorMallocLimit";
+    private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE,
+        (1L << 32L) - 1L, 1L << 32L};
+    private static final Long[] EXPECTED_64 = TESTS;
+    private static final Long[] EXPECTED_32 = {0L, 100L,
+        (long) Integer.MAX_VALUE, (1L << 32L) - 1L, 0L};
+
+    public static void main(String[] args) throws Exception {
+        VmFlagTest.runTest(FLAG_NAME, TESTS,
+            Platform.is64bit() ? EXPECTED_64 : EXPECTED_32,
+            VmFlagTest.WHITE_BOX::setSizeTVMFlag,
+            VmFlagTest.WHITE_BOX::getSizeTVMFlag);
+    }
+}