changeset 4372:6a431dbf4a33 hs24-b33

Merge
author amurillo
date Thu, 14 Feb 2013 22:29:42 -0800
parents fcd41f89bfa3 (current diff) 7ffe30a79778 (diff)
children 0310fb7a08b6
files test/runtime/7158988/TestFieldMonitor.sh
diffstat 84 files changed, 2162 insertions(+), 467 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/os/bsd/libproc_impl.c	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/os/bsd/libproc_impl.c	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -91,6 +91,14 @@
    }
 }
 
+void print_error(const char* format,...) {
+  va_list alist;
+  va_start(alist, format);
+  fputs("ERROR: ", stderr);
+  vfprintf(stderr, format, alist);
+  va_end(alist);
+}
+
 bool is_debug() {
    return _libsaproc_debug;
 }
--- a/agent/src/os/bsd/libproc_impl.h	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/os/bsd/libproc_impl.h	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -107,6 +107,7 @@
 int pathmap_open(const char* name);
 
 void print_debug(const char* format,...);
+void print_error(const char* format,...);
 bool is_debug();
 
 typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid);
--- a/agent/src/os/bsd/ps_proc.c	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/os/bsd/ps_proc.c	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -129,42 +129,66 @@
   return (errno == 0)? true: false;
 }
 
+static bool ptrace_continue(pid_t pid, int signal) {
+  // pass the signal to the process so we don't swallow it
+  if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) {
+    print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);
+    return false;
+  }
+  return true;
+}
+
+// waits until the ATTACH has stopped the process
+// by signal SIGSTOP
+static bool ptrace_waitpid(pid_t pid) {
+  int ret;
+  int status;
+  do {
+    // Wait for debuggee to stop.
+    ret = waitpid(pid, &status, 0);
+    if (ret >= 0) {
+      if (WIFSTOPPED(status)) {
+        // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
+        // will still be pending and delivered when the process is DETACHED and the process
+        // will go to sleep.
+        if (WSTOPSIG(status) == SIGSTOP) {
+          // Debuggee stopped by SIGSTOP.
+          return true;
+        }
+        if (!ptrace_continue(pid, WSTOPSIG(status))) {
+          print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
+          return false;
+        }
+      } else {
+        print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
+        return false;
+      }
+    } else {
+      switch (errno) {
+        case EINTR:
+          continue;
+          break;
+        case ECHILD:
+          print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
+          break;
+        case EINVAL:
+          print_debug("waitpid() failed. Invalid options argument.\n");
+          break;
+        default:
+          print_debug("waitpid() failed. Unexpected error %d\n",errno);
+      }
+      return false;
+    }
+  } while(true);
+}
+
 // attach to a process/thread specified by "pid"
 static bool ptrace_attach(pid_t pid) {
   if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) {
     print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
     return false;
   } else {
-    int ret;
-    int status;
-    do {
-      // Wait for debuggee to stop.
-      ret = waitpid(pid, &status, 0);
-      if (ret >= 0) {
-        if (WIFSTOPPED(status)) {
-          // Debuggee stopped.
-          return true;
-        } else {
-          print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
-          return false;
-        }
-      } else {
-        switch (errno) {
-          case EINTR:
-            continue;
-            break;
-          case ECHILD:
-            print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
-            break;
-          case EINVAL:
-            print_debug("waitpid() failed. Invalid options argument.\n");
-            break;
-          default:
-            print_debug("waitpid() failed. Unexpected error %d\n",errno);
-        }
-        return false;
-      }
-    } while(true);
+    return ptrace_waitpid(pid);
   }
 }
 
--- a/agent/src/os/linux/libproc_impl.c	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/os/linux/libproc_impl.c	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -92,6 +92,14 @@
    }
 }
 
+void print_error(const char* format,...) {
+  va_list alist;
+  va_start(alist, format);
+  fputs("ERROR: ", stderr);
+  vfprintf(stderr, format, alist);
+  va_end(alist);
+}
+
 bool is_debug() {
    return _libsaproc_debug;
 }
--- a/agent/src/os/linux/libproc_impl.h	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/os/linux/libproc_impl.h	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -105,6 +105,7 @@
 int pathmap_open(const char* name);
 
 void print_debug(const char* format,...);
+void print_error(const char* format,...);
 bool is_debug();
 
 typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid);
--- a/agent/src/os/linux/ps_proc.c	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/os/linux/ps_proc.c	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
 #include <errno.h>
 #include <sys/ptrace.h>
 #include "libproc_impl.h"
@@ -142,46 +143,71 @@
 
 }
 
+static bool ptrace_continue(pid_t pid, int signal) {
+  // pass the signal to the process so we don't swallow it
+  if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) {
+    print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);
+    return false;
+  }
+  return true;
+}
+
+// waits until the ATTACH has stopped the process
+// by signal SIGSTOP
+static bool ptrace_waitpid(pid_t pid) {
+  int ret;
+  int status;
+  while (true) {
+    // Wait for debuggee to stop.
+    ret = waitpid(pid, &status, 0);
+    if (ret == -1 && errno == ECHILD) {
+      // try cloned process.
+      ret = waitpid(pid, &status, __WALL);
+    }
+    if (ret >= 0) {
+      if (WIFSTOPPED(status)) {
+        // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
+        // will still be pending and delivered when the process is DETACHED and the process
+        // will go to sleep.
+        if (WSTOPSIG(status) == SIGSTOP) {
+          // Debuggee stopped by SIGSTOP.
+          return true;
+        }
+        if (!ptrace_continue(pid, WSTOPSIG(status))) {
+          print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
+          return false;
+        }
+      } else {
+        print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
+        return false;
+      }
+    } else {
+      switch (errno) {
+        case EINTR:
+          continue;
+          break;
+        case ECHILD:
+          print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
+          break;
+        case EINVAL:
+          print_debug("waitpid() failed. Invalid options argument.\n");
+          break;
+        default:
+          print_debug("waitpid() failed. Unexpected error %d\n",errno);
+          break;
+      }
+      return false;
+    }
+  }
+}
+
 // attach to a process/thread specified by "pid"
 static bool ptrace_attach(pid_t pid) {
   if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
     print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
     return false;
   } else {
-    int ret;
-    int status;
-    do {
-      // Wait for debuggee to stop.
-      ret = waitpid(pid, &status, 0);
-      if (ret == -1 && errno == ECHILD) {
-        // try cloned process.
-        ret = waitpid(pid, &status, __WALL);
-      }
-      if (ret >= 0) {
-        if (WIFSTOPPED(status)) {
-          // Debuggee stopped.
-          return true;
-        } else {
-          print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
-          return false;
-        }
-      } else {
-        switch (errno) {
-          case EINTR:
-            continue;
-            break;
-          case ECHILD:
-            print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
-            break;
-          case EINVAL:
-            print_debug("waitpid() failed. Invalid options argument.\n");
-            break;
-          default:
-            print_debug("waitpid() failed. Unexpected error %d\n",errno);
-        }
-        return false;
-      }
-    } while(true);
+    return ptrace_waitpid(pid);
   }
 }
 
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java	Thu Feb 14 22:29:42 2013 -0800
@@ -61,15 +61,13 @@
     CMSBitMap markBitMap = markBitMap();
     long addressSize = VM.getVM().getAddressSize();
     if ( markBitMap.isMarked(addr) &&  markBitMap.isMarked(addr.addOffsetTo(1*addressSize)) ) {
-       System.err.println("Printezis bits are set...");
       Address nextOneAddr = markBitMap.getNextMarkedWordAddress(addr.addOffsetTo(2*addressSize));
       //return size in bytes
       long size =  (nextOneAddr.addOffsetTo(1*addressSize)).minus(addr);
       return size;
     } else {
-     //missing Printezis marks
-     System.err.println("Missing Printszis marks...");
-     return -1;
+      //missing Printezis marks
+      return -1;
     }
 
   }
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Thu Feb 14 22:29:42 2013 -0800
@@ -191,7 +191,6 @@
             //Find the object size using Printezis bits and skip over
             long size = collector().blockSizeUsingPrintezisBits(cur);
             if (size == -1) {
-              System.err.println("Printezis bits not set...");
               break;
             }
             cur = cur.addOffsetTo(adjustObjectSizeInBytes(size));
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java	Thu Feb 14 22:29:42 2013 -0800
@@ -184,7 +184,6 @@
       if (trapReasonName[index] == null) {
         throw new InternalError("missing reason for " + index);
       }
-      System.out.println(trapReasonName[index]);
     }
   }
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java	Wed Feb 13 17:56:44 2013 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java	Thu Feb 14 22:29:42 2013 -0800
@@ -471,7 +471,6 @@
           }
           if (obj == null) {
              //Find the object size using Printezis bits and skip over
-             System.err.println("Finding object size using Printezis bits and skipping over...");
              long size = 0;
 
              if ( (cmsSpaceOld != null) && cmsSpaceOld.contains(handle) ){
--- a/make/hotspot_version	Wed Feb 13 17:56:44 2013 -0800
+++ b/make/hotspot_version	Thu Feb 14 22:29:42 2013 -0800
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=24
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=32
+HS_BUILD_NUMBER=33
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/src/share/tools/whitebox/sun/hotspot/WhiteBox.java	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/tools/whitebox/sun/hotspot/WhiteBox.java	Thu Feb 14 22:29:42 2013 -0800
@@ -69,4 +69,9 @@
   public native long    g1NumFreeRegions();
   public native int     g1RegionSize();
   public native Object[]    parseCommandLine(String commandline, DiagnosticCommand[] args);
+
+  // NMT
+  public native boolean NMTAllocTest();
+  public native boolean NMTFreeTestMemory();
+  public native boolean NMTWaitForDataMerge();
 }
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -2285,7 +2285,7 @@
         {
           ReleaseForegroundGC x(this);
           stats().record_cms_begin();
-          register_gc_start();
+          register_gc_start(GCCause::_cms_concurrent_mark);
 
           VM_CMS_Initial_Mark initial_mark_op(this);
           VMThread::execute(&initial_mark_op);
@@ -2421,11 +2421,11 @@
   }
 }
 
-void CMSCollector::register_gc_start() {
+void CMSCollector::register_gc_start(GCCause::Cause cause) {
   _cms_start_registered = true;
   CollectedHeap* heap = GenCollectedHeap::heap();
   _gc_timer_cm->register_gc_start(os::elapsed_counter());
-  _gc_tracer_cm->report_gc_start(heap->gc_cause(), _gc_timer_cm->gc_start());
+  _gc_tracer_cm->report_gc_start(cause, _gc_timer_cm->gc_start());
 }
 
 void CMSCollector::register_gc_end() {
@@ -2469,7 +2469,7 @@
     }
     switch (_collectorState) {
       case InitialMarking:
-        register_gc_start();
+        register_gc_start(GenCollectedHeap::heap()->gc_cause());
         init_mark_was_synchronous = true;  // fact to be exploited in re-mark
         checkpointRootsInitial(false);
         assert(_collectorState == Marking, "Collector state should have changed"
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -615,7 +615,7 @@
   ConcurrentGCTimer* _gc_timer_cm;
 
   bool _cms_start_registered;
-  void register_gc_start();
+  void register_gc_start(GCCause::Cause cause);
   void register_gc_end();
 
  protected:
--- a/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -85,7 +85,7 @@
     _curr_index(0), _length(0), _first_par_unreserved_idx(0),
     _region_live_threshold_bytes(0), _remaining_reclaimable_bytes(0) {
   _region_live_threshold_bytes =
-    HeapRegion::GrainBytes * (size_t) G1OldCSetRegionLiveThresholdPercent / 100;
+    HeapRegion::GrainBytes * (size_t) G1MixedGCLiveThresholdPercent / 100;
 }
 
 #ifndef PRODUCT
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -632,8 +632,8 @@
   assert(_heap_end != NULL, "heap bounds should look ok");
   assert(_heap_start < _heap_end, "heap bounds should look ok");
 
-  // reset all the marking data structures and any necessary flags
-  clear_marking_state();
+  // Reset all the marking data structures and any necessary flags
+  reset_marking_state();
 
   if (verbose_low()) {
     gclog_or_tty->print_cr("[global] resetting");
@@ -651,6 +651,23 @@
   set_concurrent_marking_in_progress();
 }
 
+
+void ConcurrentMark::reset_marking_state(bool clear_overflow) {
+  _markStack.setEmpty();
+  _markStack.clear_overflow();
+  if (clear_overflow) {
+    clear_has_overflown();
+  } else {
+    assert(has_overflown(), "pre-condition");
+  }
+  _finger = _heap_start;
+
+  for (uint i = 0; i < _max_task_num; ++i) {
+    CMTaskQueue* queue = _task_queues->queue(i);
+    queue->set_empty();
+  }
+}
+
 void ConcurrentMark::set_phase(uint active_tasks, bool concurrent) {
   assert(active_tasks <= _max_task_num, "we should not have more");
 
@@ -681,7 +698,7 @@
 void ConcurrentMark::set_non_marking_state() {
   // We set the global marking state to some default values when we're
   // not doing marking.
-  clear_marking_state();
+  reset_marking_state();
   _active_tasks = 0;
   clear_concurrent_marking_in_progress();
 }
@@ -848,7 +865,7 @@
     // not clear the overflow flag since we rely on it being true when
     // we exit this method to abort the pause and restart concurent
     // marking.
-    clear_marking_state(concurrent() /* clear_overflow */);
+    reset_marking_state(concurrent() /* clear_overflow */);
     force_overflow()->update();
 
     if (G1Log::fine()) {
@@ -1057,7 +1074,7 @@
     uint active_workers = MAX2(1U, parallel_marking_threads());
 
     CMRootRegionScanTask task(this);
-    if (parallel_marking_threads() > 0) {
+    if (use_parallel_marking_threads()) {
       _parallel_workers->set_active_workers((int) active_workers);
       _parallel_workers->run_task(&task);
     } else {
@@ -1093,7 +1110,7 @@
   set_phase(active_workers, true /* concurrent */);
 
   CMConcurrentMarkingTask markingTask(this, cmThread());
-  if (parallel_marking_threads() > 0) {
+  if (use_parallel_marking_threads()) {
     _parallel_workers->set_active_workers((int)active_workers);
     // Don't set _n_par_threads because it affects MT in proceess_strong_roots()
     // and the decisions on that MT processing is made elsewhere.
@@ -1142,8 +1159,9 @@
   if (has_overflown()) {
     // Oops.  We overflowed.  Restart concurrent marking.
     _restart_for_overflow = true;
-    // Clear the flag. We do not need it any more.
-    clear_has_overflown();
+    // Clear the marking state because we will be restarting
+    // marking due to overflowing the global mark stack.
+    reset_marking_state();
     if (G1TraceMarkStackOverflow) {
       gclog_or_tty->print_cr("\nRemark led to restart for overflow.");
     }
@@ -1167,10 +1185,7 @@
                        /* option */ VerifyOption_G1UseNextMarking);
     }
     assert(!restart_for_overflow(), "sanity");
-  }
-
-  // Reset the marking state if marking completed
-  if (!restart_for_overflow()) {
+    // Completely reset the marking state since marking completed
     set_non_marking_state();
   }
 
@@ -2846,22 +2861,6 @@
 }
 #endif // PRODUCT
 
-void ConcurrentMark::clear_marking_state(bool clear_overflow) {
-  _markStack.setEmpty();
-  _markStack.clear_overflow();
-  if (clear_overflow) {
-    clear_has_overflown();
-  } else {
-    assert(has_overflown(), "pre-condition");
-  }
-  _finger = _heap_start;
-
-  for (int i = 0; i < (int)_max_task_num; ++i) {
-    OopTaskQueue* queue = _task_queues->queue(i);
-    queue->set_empty();
-  }
-}
-
 // Aggregate the counting data that was constructed concurrently
 // with marking.
 class AggregateCountDataHRClosure: public HeapRegionClosure {
@@ -3068,7 +3067,7 @@
   // Clear the liveness counting data
   clear_all_count_data();
   // Empty mark stack
-  clear_marking_state();
+  reset_marking_state();
   for (int i = 0; i < (int)_max_task_num; ++i) {
     _tasks[i]->clear_region_fields();
   }
@@ -3128,7 +3127,9 @@
 }
 
 void ConcurrentMark::print_worker_threads_on(outputStream* st) const {
-  _parallel_workers->print_worker_threads_on(st);
+  if (use_parallel_marking_threads()) {
+    _parallel_workers->print_worker_threads_on(st);
+  }
 }
 
 // We take a break if someone is trying to stop the world.
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -461,15 +461,18 @@
   // It resets the global marking data structures, as well as the
   // task local ones; should be called during initial mark.
   void reset();
-  // It resets all the marking data structures.
-  void clear_marking_state(bool clear_overflow = true);
+
+  // Resets all the marking data structures. Called when we have to restart
+  // marking or when marking completes (via set_non_marking_state below).
+  void reset_marking_state(bool clear_overflow = true);
+
+  // We do this after we're done with marking so that the marking data
+  // structures are initialised to a sensible and predictable state.
+  void set_non_marking_state();
 
   // It should be called to indicate which phase we're in (concurrent
   // mark or remark) and how many threads are currently active.
   void set_phase(uint active_tasks, bool concurrent);
-  // We do this after we're done with marking so that the marking data
-  // structures are initialised to a sensible and predictable state.
-  void set_non_marking_state();
 
   // prints all gathered CM-related statistics
   void print_stats();
@@ -479,17 +482,26 @@
   }
 
   // accessor methods
-  uint parallel_marking_threads() { return _parallel_marking_threads; }
-  uint max_parallel_marking_threads() { return _max_parallel_marking_threads;}
-  double sleep_factor()             { return _sleep_factor; }
-  double marking_task_overhead()    { return _marking_task_overhead;}
-  double cleanup_sleep_factor()     { return _cleanup_sleep_factor; }
-  double cleanup_task_overhead()    { return _cleanup_task_overhead;}
+  uint parallel_marking_threads() const     { return _parallel_marking_threads; }
+  uint max_parallel_marking_threads() const { return _max_parallel_marking_threads;}
+  double sleep_factor()                     { return _sleep_factor; }
+  double marking_task_overhead()            { return _marking_task_overhead;}
+  double cleanup_sleep_factor()             { return _cleanup_sleep_factor; }
+  double cleanup_task_overhead()            { return _cleanup_task_overhead;}
 
-  HeapWord*               finger()        { return _finger;   }
-  bool                    concurrent()    { return _concurrent; }
-  uint                    active_tasks()  { return _active_tasks; }
-  ParallelTaskTerminator* terminator()    { return &_terminator; }
+  bool use_parallel_marking_threads() const {
+    assert(parallel_marking_threads() <=
+           max_parallel_marking_threads(), "sanity");
+    assert((_parallel_workers == NULL && parallel_marking_threads() == 0) ||
+           parallel_marking_threads() > 0,
+           "parallel workers not set up correctly");
+    return _parallel_workers != NULL;
+  }
+
+  HeapWord*               finger()          { return _finger;   }
+  bool                    concurrent()      { return _concurrent; }
+  uint                    active_tasks()    { return _active_tasks; }
+  ParallelTaskTerminator* terminator()      { return &_terminator; }
 
   // It claims the next available region to be scanned by a marking
   // task. It might return NULL if the next region is empty or we have
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -157,13 +157,11 @@
           VM_CGC_Operation op(&final_cl, "GC remark", true /* needs_pll */);
           VMThread::execute(&op);
         }
-        if (cm()->restart_for_overflow() &&
-            G1TraceMarkStackOverflow) {
-          gclog_or_tty->print_cr("Restarting conc marking because of MS overflow "
-                                 "in remark (restart #%d).", iter);
-        }
-
         if (cm()->restart_for_overflow()) {
+          if (G1TraceMarkStackOverflow) {
+            gclog_or_tty->print_cr("Restarting conc marking because of MS overflow "
+                                   "in remark (restart #%d).", iter);
+          }
           if (G1Log::fine()) {
             gclog_or_tty->date_stamp(PrintGCDateStamps);
             gclog_or_tty->stamp(PrintGCTimeStamps);
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1905,7 +1905,6 @@
   _ref_processor_stw(NULL),
   _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
   _bot_shared(NULL),
-  _objs_with_preserved_marks(NULL), _preserved_marks_of_objs(NULL),
   _evac_failure_scan_stack(NULL) ,
   _mark_in_progress(false),
   _cg1r(NULL), _summary_bytes_used(0),
@@ -4324,22 +4323,15 @@
   assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
 
   // Now restore saved marks, if any.
-  if (_objs_with_preserved_marks != NULL) {
-    assert(_preserved_marks_of_objs != NULL, "Both or none.");
-    guarantee(_objs_with_preserved_marks->length() ==
-              _preserved_marks_of_objs->length(), "Both or none.");
-    for (int i = 0; i < _objs_with_preserved_marks->length(); i++) {
-      oop obj   = _objs_with_preserved_marks->at(i);
-      markOop m = _preserved_marks_of_objs->at(i);
-      obj->set_mark(m);
-    }
-
-    // Delete the preserved marks growable arrays (allocated on the C heap).
-    delete _objs_with_preserved_marks;
-    delete _preserved_marks_of_objs;
-    _objs_with_preserved_marks = NULL;
-    _preserved_marks_of_objs = NULL;
-  }
+  assert(_objs_with_preserved_marks.size() ==
+            _preserved_marks_of_objs.size(), "Both or none.");
+  while (!_objs_with_preserved_marks.is_empty()) {
+    oop obj = _objs_with_preserved_marks.pop();
+    markOop m = _preserved_marks_of_objs.pop();
+    obj->set_mark(m);
+  }
+  _objs_with_preserved_marks.clear(true);
+  _preserved_marks_of_objs.clear(true);
 }
 
 void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) {
@@ -4422,15 +4414,8 @@
   // We want to call the "for_promotion_failure" version only in the
   // case of a promotion failure.
   if (m->must_be_preserved_for_promotion_failure(obj)) {
-    if (_objs_with_preserved_marks == NULL) {
-      assert(_preserved_marks_of_objs == NULL, "Both or none.");
-      _objs_with_preserved_marks =
-        new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(40, true);
-      _preserved_marks_of_objs =
-        new (ResourceObj::C_HEAP, mtGC) GrowableArray<markOop>(40, true);
-    }
-    _objs_with_preserved_marks->push(obj);
-    _preserved_marks_of_objs->push(m);
+    _objs_with_preserved_marks.push(obj);
+    _preserved_marks_of_objs.push(m);
   }
 }
 
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -38,6 +38,7 @@
 #include "memory/barrierSet.hpp"
 #include "memory/memRegion.hpp"
 #include "memory/sharedHeap.hpp"
+#include "utilities/stack.hpp"
 
 // A "G1CollectedHeap" is an implementation of a java heap for HotSpot.
 // It uses the "Garbage First" heap organization and algorithm, which
@@ -891,10 +892,9 @@
   // forwarding pointers to themselves.  Reset them.
   void remove_self_forwarding_pointers();
 
-  // When one is non-null, so is the other.  Together, they each pair is
-  // an object with a preserved mark, and its mark value.
-  GrowableArray<oop>*     _objs_with_preserved_marks;
-  GrowableArray<markOop>* _preserved_marks_of_objs;
+  // Together, these store an object with a preserved mark, and its mark value.
+  Stack<oop, mtGC>     _objs_with_preserved_marks;
+  Stack<markOop, mtGC> _preserved_marks_of_objs;
 
   // Preserve the mark of "obj", if necessary, in preparation for its mark
   // word being overwritten with a self-forwarding-pointer.
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -309,9 +309,9 @@
 }
 
 G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) {
-  assert(G1DefaultMinNewGenPercent <= G1DefaultMaxNewGenPercent, "Min larger than max");
-  assert(G1DefaultMinNewGenPercent > 0 && G1DefaultMinNewGenPercent < 100, "Min out of bounds");
-  assert(G1DefaultMaxNewGenPercent > 0 && G1DefaultMaxNewGenPercent < 100, "Max out of bounds");
+  assert(G1NewSizePercent <= G1MaxNewSizePercent, "Min larger than max");
+  assert(G1NewSizePercent > 0 && G1NewSizePercent < 100, "Min out of bounds");
+  assert(G1MaxNewSizePercent > 0 && G1MaxNewSizePercent < 100, "Max out of bounds");
 
   if (FLAG_IS_CMDLINE(NewRatio)) {
     if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
@@ -344,12 +344,12 @@
 }
 
 uint G1YoungGenSizer::calculate_default_min_length(uint new_number_of_heap_regions) {
-  uint default_value = (new_number_of_heap_regions * G1DefaultMinNewGenPercent) / 100;
+  uint default_value = (new_number_of_heap_regions * G1NewSizePercent) / 100;
   return MAX2(1U, default_value);
 }
 
 uint G1YoungGenSizer::calculate_default_max_length(uint new_number_of_heap_regions) {
-  uint default_value = (new_number_of_heap_regions * G1DefaultMaxNewGenPercent) / 100;
+  uint default_value = (new_number_of_heap_regions * G1MaxNewSizePercent) / 100;
   return MAX2(1U, default_value);
 }
 
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -94,18 +94,18 @@
 // will occur.
 //
 // If nothing related to the the young gen size is set on the command
-// line we should allow the young gen to be between
-// G1DefaultMinNewGenPercent and G1DefaultMaxNewGenPercent of the
-// heap size. This means that every time the heap size changes the
-// limits for the young gen size will be updated.
+// line we should allow the young gen to be between G1NewSizePercent
+// and G1MaxNewSizePercent of the heap size. This means that every time
+// the heap size changes, the limits for the young gen size will be
+// recalculated.
 //
 // If only -XX:NewSize is set we should use the specified value as the
-// minimum size for young gen. Still using G1DefaultMaxNewGenPercent
-// of the heap as maximum.
+// minimum size for young gen. Still using G1MaxNewSizePercent of the
+// heap as maximum.
 //
 // If only -XX:MaxNewSize is set we should use the specified value as the
-// maximum size for young gen. Still using G1DefaultMinNewGenPercent
-// of the heap as minimum.
+// maximum size for young gen. Still using G1NewSizePercent of the heap
+// as minimum.
 //
 // If -XX:NewSize and -XX:MaxNewSize are both specified we use these values.
 // No updates when the heap size changes. There is a special case when
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -287,23 +287,24 @@
           "The number of times we'll force an overflow during "             \
           "concurrent marking")                                             \
                                                                             \
-  experimental(uintx, G1DefaultMinNewGenPercent, 20,                        \
-          "Percentage (0-100) of the heap size to use as minimum "          \
-          "young gen size.")                                                \
+  experimental(uintx, G1NewSizePercent, 5,                                  \
+          "Percentage (0-100) of the heap size to use as default "          \
+          "minimum young gen size.")                                        \
                                                                             \
-  experimental(uintx, G1DefaultMaxNewGenPercent, 80,                        \
-          "Percentage (0-100) of the heap size to use as maximum "          \
-          "young gen size.")                                                \
+  experimental(uintx, G1MaxNewSizePercent, 60,                              \
+          "Percentage (0-100) of the heap size to use as default "          \
+          " maximum young gen size.")                                       \
                                                                             \
-  experimental(uintx, G1OldCSetRegionLiveThresholdPercent, 90,              \
-          "Threshold for regions to be added to the collection set. "       \
-          "Regions with more live bytes than this will not be collected.")  \
+  experimental(uintx, G1MixedGCLiveThresholdPercent, 65,                    \
+          "Threshold for regions to be considered for inclusion in the "    \
+          "collection set of mixed GCs. "                                   \
+          "Regions with live bytes exceeding this will not be collected.")  \
                                                                             \
-  product(uintx, G1HeapWastePercent, 5,                                     \
+  product(uintx, G1HeapWastePercent, 10,                                    \
           "Amount of space, expressed as a percentage of the heap size, "   \
           "that G1 is willing not to collect to avoid expensive GCs.")      \
                                                                             \
-  product(uintx, G1MixedGCCountTarget, 4,                                   \
+  product(uintx, G1MixedGCCountTarget, 8,                                   \
           "The target number of mixed GCs after a marking cycle.")          \
                                                                             \
   experimental(uintx, G1OldCSetRegionThresholdPercent, 10,                  \
--- a/src/share/vm/gc_interface/gcCause.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_interface/gcCause.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -72,6 +72,9 @@
     case _cms_final_remark:
       return "CMS Final Remark";
 
+    case _cms_concurrent_mark:
+      return "CMS Concurrent Mark";
+
     case _old_generation_expanded_on_last_scavenge:
       return "Old Generation Expanded On Last Scavenge";
 
--- a/src/share/vm/gc_interface/gcCause.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/gc_interface/gcCause.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -60,6 +60,7 @@
     _cms_generation_full,
     _cms_initial_mark,
     _cms_final_remark,
+    _cms_concurrent_mark,
 
     _old_generation_expanded_on_last_scavenge,
     _old_generation_too_full_to_scavenge,
--- a/src/share/vm/memory/allocation.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/memory/allocation.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -135,10 +135,11 @@
   mtChunk             = 0x0B00,  // chunk that holds content of arenas
   mtJavaHeap          = 0x0C00,  // Java heap
   mtClassShared       = 0x0D00,  // class data sharing
-  mtTracing           = 0x0E00,  // memory used for Tracing
-  mt_number_of_types  = 0x000E,  // number of memory types (mtDontTrack
+  mtTest              = 0x0E00,  // Test type for verifying NMT
+  mtTracing           = 0x0F00,  // memory used for Tracing
+  mt_number_of_types  = 0x000F,  // number of memory types (mtDontTrack
                                  // is not included as validate type)
-  mtDontTrack         = 0x0F00,  // memory we do not or cannot track
+  mtDontTrack         = 0x1000,  // memory we do not or cannot track
   mt_masks            = 0x7F00,
 
   // object type mask
--- a/src/share/vm/oops/cpCacheOop.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/oops/cpCacheOop.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -575,6 +575,24 @@
   return false;
 }
 
+// a constant pool cache entry should never contain old or obsolete methods
+bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
+  if (is_vfinal()) {
+    // virtual and final so _f2 contains method ptr instead of vtable index
+    methodOop m = (methodOop)_f2;
+    // Return false if _f2 refers to an old or an obsolete method.
+    // _f2 == NULL || !m->is_method() are just as unexpected here.
+    return (m != NULL && m->is_method() && !m->is_old() && !m->is_obsolete());
+  } else if ((oop)_f1 == NULL || !((oop)_f1)->is_method()) {
+    // _f1 == NULL || !_f1->is_method() are OK here
+    return true;
+  }
+
+  methodOop m = (methodOop)_f1;
+  // return false if _f1 refers to an old or an obsolete method
+  return (!m->is_old() && !m->is_obsolete());
+}
+
 bool ConstantPoolCacheEntry::is_interesting_method_entry(klassOop k) {
   if (!is_method_entry()) {
     // not a method entry so not interesting by default
@@ -598,7 +616,7 @@
   }
 
   assert(m != NULL && m->is_method(), "sanity check");
-  if (m == NULL || !m->is_method() || m->method_holder() != k) {
+  if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) {
     // robustness for above sanity checks or method is not in
     // the interesting class
     return false;
@@ -683,3 +701,22 @@
     }
   }
 }
+
+// the constant pool cache should never contain old or obsolete methods
+bool constantPoolCacheOopDesc::check_no_old_or_obsolete_entries() {
+  for (int i = 1; i < length(); i++) {
+    if (entry_at(i)->is_interesting_method_entry(NULL) &&
+        !entry_at(i)->check_no_old_or_obsolete_entries()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void constantPoolCacheOopDesc::dump_cache() {
+  for (int i = 1; i < length(); i++) {
+    if (entry_at(i)->is_interesting_method_entry(NULL)) {
+      entry_at(i)->print(tty, i);
+    }
+  }
+}
--- a/src/share/vm/oops/cpCacheOop.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/oops/cpCacheOop.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -363,6 +363,7 @@
   // group don't print the klass name.
   bool adjust_method_entry(methodOop old_method, methodOop new_method,
          bool * trace_name_printed);
+  bool check_no_old_or_obsolete_entries();
   bool is_interesting_method_entry(klassOop k);
 
   // Debugging & Printing
@@ -492,6 +493,8 @@
   // group don't print the klass name.
   void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
                              int methods_length, bool * trace_name_printed);
+  bool check_no_old_or_obsolete_entries();
+  void dump_cache();
 };
 
 #endif // SHARE_VM_OOPS_CPCACHEOOP_HPP
--- a/src/share/vm/oops/klassVtable.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/oops/klassVtable.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -640,11 +640,37 @@
                                 new_method->name()->as_C_string(),
                                 new_method->signature()->as_C_string()));
         }
+        // cannot 'break' here; see for-loop comment above.
       }
     }
   }
 }
 
+// a vtable should never contain old or obsolete methods
+bool klassVtable::check_no_old_or_obsolete_entries() {
+  for (int i = 0; i < length(); i++) {
+    methodOop m = unchecked_method_at(i);
+    if (m != NULL && (m->is_old() || m->is_obsolete())) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void klassVtable::dump_vtable() {
+  tty->print_cr("vtable dump --");
+  for (int i = 0; i < length(); i++) {
+    methodOop m = unchecked_method_at(i);
+    if (m != NULL) {
+      tty->print("      (%5d)  ", i);
+      m->access_flags().print_on(tty);
+      tty->print(" --  ");
+      m->print_name(tty);
+      tty->cr();
+    }
+  }
+}
+
 // CDS/RedefineClasses support - clear vtables so they can be reinitialized
 void klassVtable::clear_vtable() {
   for (int i = 0; i < _length; i++) table()[i].clear();
@@ -994,13 +1020,42 @@
             new_method->name()->as_C_string(),
             new_method->signature()->as_C_string()));
         }
-        break;
+        // cannot 'break' here; see for-loop comment above.
       }
       ime++;
     }
   }
 }
 
+// an itable should never contain old or obsolete methods
+bool klassItable::check_no_old_or_obsolete_entries() {
+  itableMethodEntry* ime = method_entry(0);
+  for (int i = 0; i < _size_method_table; i++) {
+    methodOop m = ime->method();
+    if (m != NULL && (m->is_old() || m->is_obsolete())) {
+      return false;
+    }
+    ime++;
+  }
+  return true;
+}
+
+void klassItable::dump_itable() {
+  itableMethodEntry* ime = method_entry(0);
+  tty->print_cr("itable dump --");
+  for (int i = 0; i < _size_method_table; i++) {
+    methodOop m = ime->method();
+    if (m != NULL) {
+      tty->print("      (%5d)  ", i);
+      m->access_flags().print_on(tty);
+      tty->print(" --  ");
+      m->print_name(tty);
+      tty->cr();
+    }
+    ime++;
+  }
+}
+
 
 // Setup
 class InterfaceVisiterClosure : public StackObj {
@@ -1287,33 +1342,6 @@
   tty->print_cr("%6d bytes total", total);
 }
 
-bool klassVtable::check_no_old_entries() {
-  // Check that there really is no entry
-  for (int i = 0; i < length(); i++) {
-    methodOop m = unchecked_method_at(i);
-    if (m != NULL) {
-        if (m->is_old()) {
-            return false;
-        }
-    }
-  }
-  return true;
-}
-
-void klassVtable::dump_vtable() {
-  tty->print_cr("vtable dump --");
-  for (int i = 0; i < length(); i++) {
-    methodOop m = unchecked_method_at(i);
-    if (m != NULL) {
-      tty->print("      (%5d)  ", i);
-      m->access_flags().print_on(tty);
-      tty->print(" --  ");
-      m->print_name(tty);
-      tty->cr();
-    }
-  }
-}
-
 int  klassItable::_total_classes;   // Total no. of classes with itables
 long klassItable::_total_size;      // Total no. of bytes used for itables
 
--- a/src/share/vm/oops/klassVtable.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/oops/klassVtable.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -98,6 +98,8 @@
   // group don't print the klass name.
   void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
                              int methods_length, bool * trace_name_printed);
+  bool check_no_old_or_obsolete_entries();
+  void dump_vtable();
 
   // Garbage collection
   void oop_follow_contents();
@@ -118,11 +120,6 @@
   void verify(outputStream* st, bool force = false);
   static void print_statistics()                            PRODUCT_RETURN;
 
-#ifndef PRODUCT
-  bool check_no_old_entries();
-  void dump_vtable();
-#endif
-
  protected:
   friend class vtableEntry;
  private:
@@ -292,6 +289,8 @@
   // group don't print the klass name.
   void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
                              int methods_length, bool * trace_name_printed);
+  bool check_no_old_or_obsolete_entries();
+  void dump_itable();
 
   // Garbage collection
   void oop_follow_contents();
--- a/src/share/vm/oops/methodOop.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/oops/methodOop.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -1328,10 +1328,6 @@
 }
 
 
-//-----------------------------------------------------------------------------------
-// Non-product code
-
-#ifndef PRODUCT
 class SignatureTypePrinter : public SignatureTypeNames {
  private:
   outputStream* _st;
@@ -1368,6 +1364,10 @@
 }
 
 
+//-----------------------------------------------------------------------------------
+// Non-product code
+
+#ifndef PRODUCT
 void methodOopDesc::print_codes_on(outputStream* st) const {
   print_codes_on(0, code_size(), st);
 }
--- a/src/share/vm/oops/methodOop.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/oops/methodOop.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -714,8 +714,8 @@
   static bool has_unloaded_classes_in_signature(methodHandle m, TRAPS);
 
   // Printing
-  void print_short_name(outputStream* st = tty)  /*PRODUCT_RETURN*/; // prints as klassname::methodname; Exposed so field engineers can debug VM
-  void print_name(outputStream* st = tty)        PRODUCT_RETURN; // prints as "virtual void foo(int)"
+  void print_short_name(outputStream* st = tty); // prints as klassname::methodname; Exposed so field engineers can debug VM
+  void print_name(outputStream* st = tty); // prints as "virtual void foo(int)"; exposed for TraceRedefineClasses
 
   // Helper routine used for method sorting
   static void sort_methods(objArrayOop methods,
--- a/src/share/vm/oops/objArrayKlass.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/oops/objArrayKlass.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -504,7 +504,7 @@
   }
   int remaining = oa->length() - print_len;
   if (remaining > 0) {
-    tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
+    st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
   }
 }
 
--- a/src/share/vm/oops/typeArrayKlass.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -354,7 +354,7 @@
   }
   int remaining = ta->length() - print_len;
   if (remaining > 0) {
-    tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
+    st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
   }
 }
 
--- a/src/share/vm/opto/callGenerator.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/opto/callGenerator.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -305,11 +305,13 @@
 void LateInlineCallGenerator::do_late_inline() {
   // Can't inline it
   if (call_node() == NULL || call_node()->outcnt() == 0 ||
-      call_node()->in(0) == NULL || call_node()->in(0)->is_top())
+      call_node()->in(0) == NULL || call_node()->in(0)->is_top()) {
     return;
+  }
 
+  const TypeTuple *r = call_node()->tf()->domain();
   for (int i1 = 0; i1 < method()->arg_size(); i1++) {
-    if (call_node()->in(TypeFunc::Parms + i1)->is_top()) {
+    if (call_node()->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) {
       assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
       return;
     }
--- a/src/share/vm/opto/compile.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/opto/compile.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -542,7 +542,7 @@
   bool              has_method_handle_invokes() const { return _has_method_handle_invokes;     }
   void          set_has_method_handle_invokes(bool z) {        _has_method_handle_invokes = z; }
 
-  long _latest_stage_start_counter;
+  jlong _latest_stage_start_counter;
 
   void begin_method() {
 #ifndef PRODUCT
--- a/src/share/vm/prims/jvm.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/prims/jvm.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -4484,6 +4484,5 @@
   // consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
   // counter defined in runtimeService.cpp.
   info->is_attachable = AttachListener::is_attach_supported();
-  info->is_kernel_jvm = 0; // false;
 }
 JVM_END
--- a/src/share/vm/prims/jvm.h	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/prims/jvm.h	Thu Feb 14 22:29:42 2013 -0800
@@ -1549,8 +1549,7 @@
      * the new bit is also added in the main/baseline.
      */
     unsigned int is_attachable : 1;
-    unsigned int is_kernel_jvm : 1;
-    unsigned int : 30;
+    unsigned int : 31;
     unsigned int : 32;
     unsigned int : 32;
 } jvm_version_info;
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -129,8 +129,15 @@
   // See jvmtiExport.hpp for detailed explanation.
   JvmtiExport::set_has_redefined_a_class();
 
-#ifdef ASSERT
-  SystemDictionary::classes_do(check_class, thread);
+// check_class() is optionally called for product bits, but is
+// always called for non-product bits.
+#ifdef PRODUCT
+  if (RC_TRACE_ENABLED(0x00004000)) {
+#endif
+    RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class"));
+    SystemDictionary::classes_do(check_class, thread);
+#ifdef PRODUCT
+  }
 #endif
 }
 
@@ -3349,76 +3356,116 @@
   }
 }
 
-#ifndef PRODUCT
 void VM_RedefineClasses::check_class(klassOop k_oop,
        oop initiating_loader, TRAPS) {
   Klass *k = k_oop->klass_part();
   if (k->oop_is_instance()) {
     HandleMark hm(THREAD);
     instanceKlass *ik = (instanceKlass *) k;
-
-    if (ik->vtable_length() > 0) {
-      ResourceMark rm(THREAD);
-      if (!ik->vtable()->check_no_old_entries()) {
-        tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
+    bool no_old_methods = true;  // be optimistic
+    ResourceMark rm(THREAD);
+
+    // a vtable should never contain old or obsolete methods
+    if (ik->vtable_length() > 0 &&
+        !ik->vtable()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("klassVtable::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
         ik->vtable()->dump_vtable();
+      }
+      no_old_methods = false;
+    }
+
+    // an itable should never contain old or obsolete methods
+    if (ik->itable_length() > 0 &&
+        !ik->itable()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("klassItable::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
+        ik->itable()->dump_itable();
+      }
+      no_old_methods = false;
+    }
+
+    // the constant pool cache should never contain old or obsolete methods
+    if (ik->constants() != NULL &&
+        ik->constants()->cache() != NULL &&
+        !ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("cp-cache::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
+        ik->constants()->cache()->dump_cache();
+      }
+      no_old_methods = false;
+    }
+
+    if (!no_old_methods) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
         dump_methods();
-        assert(false, "OLD method found");
+      } else {
+        tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option "
+          "to see more info about the following guarantee() failure.");
       }
+      guarantee(false, "OLD and/or OBSOLETE method(s) found");
     }
   }
 }
 
 void VM_RedefineClasses::dump_methods() {
-        int j;
-        tty->print_cr("_old_methods --");
-        for (j = 0; j < _old_methods->length(); ++j) {
-          methodOop m = (methodOop) _old_methods->obj_at(j);
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_new_methods --");
-        for (j = 0; j < _new_methods->length(); ++j) {
-          methodOop m = (methodOop) _new_methods->obj_at(j);
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_matching_(old/new)_methods --");
-        for (j = 0; j < _matching_methods_length; ++j) {
-          methodOop m = _matching_old_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-          m = _matching_new_methods[j];
-          tty->print("      (%5d)  ", m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->cr();
-        }
-        tty->print_cr("_deleted_methods --");
-        for (j = 0; j < _deleted_methods_length; ++j) {
-          methodOop m = _deleted_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_added_methods --");
-        for (j = 0; j < _added_methods_length; ++j) {
-          methodOop m = _added_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
+  int j;
+  RC_TRACE(0x00004000, ("_old_methods --"));
+  for (j = 0; j < _old_methods->length(); ++j) {
+    methodOop m = (methodOop) _old_methods->obj_at(j);
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_new_methods --"));
+  for (j = 0; j < _new_methods->length(); ++j) {
+    methodOop m = (methodOop) _new_methods->obj_at(j);
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_matching_(old/new)_methods --"));
+  for (j = 0; j < _matching_methods_length; ++j) {
+    methodOop m = _matching_old_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+    m = _matching_new_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("      (%5d)  ", m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_deleted_methods --"));
+  for (j = 0; j < _deleted_methods_length; ++j) {
+    methodOop m = _deleted_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_added_methods --"));
+  for (j = 0; j < _added_methods_length; ++j) {
+    methodOop m = _added_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
 }
-#endif
--- a/src/share/vm/prims/jvmtiRedefineClasses.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -478,9 +478,8 @@
 
   void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
 
-  static void check_class(klassOop k_oop, oop initiating_loader, TRAPS) PRODUCT_RETURN;
-
-  static void dump_methods()   PRODUCT_RETURN;
+  static void check_class(klassOop k_oop, oop initiating_loader, TRAPS);
+  static void dump_methods();
 
  public:
   VM_RedefineClasses(jint class_count,
--- a/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -54,7 +54,7 @@
 //    0x00000800 |       2048 - previous class breakpoint mgmt
 //    0x00001000 |       4096 - detect calls to obsolete methods
 //    0x00002000 |       8192 - fail a guarantee() in addition to detection
-//    0x00004000 |      16384 - unused
+//    0x00004000 |      16384 - detect old/obsolete methods in metadata
 //    0x00008000 |      32768 - old/new method matching/add/delete
 //    0x00010000 |      65536 - impl details: CP size info
 //    0x00020000 |     131072 - impl details: CP merge pass info
@@ -82,6 +82,13 @@
     tty->print_cr args; \
   } while (0)
 
+#define RC_TRACE_NO_CR(level, args) \
+  if ((TraceRedefineClasses & level) != 0) { \
+    ResourceMark rm; \
+    tty->print("RedefineClasses-0x%x: ", level); \
+    tty->print args; \
+  } while (0)
+
 #define RC_TRACE_WITH_THREAD(level, thread, args) \
   if ((TraceRedefineClasses & level) != 0) { \
     ResourceMark rm(thread); \
--- a/src/share/vm/prims/whitebox.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/prims/whitebox.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -42,6 +42,8 @@
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #endif // !SERIALGC
 
+#include "services/memTracker.hpp"
+
 bool WhiteBox::_used = false;
 
 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
@@ -77,6 +79,57 @@
 WB_END
 #endif // !SERIALGC
 
+// Keep track of the 3 allocations in NMTAllocTest so we can free them later
+// on and verify that they're not visible anymore
+static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL;
+
+// Alloc memory using the test memory type so that we can use that to see if
+// NMT picks it up correctly
+WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env))
+  void *mem;
+
+  if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
+    return false;
+  }
+
+  // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track
+  // everything correctly. Total should be 512k held alive.
+  nmtMtTest1 = os::malloc(128 * 1024, mtTest);
+  mem = os::malloc(1024 * 1024, mtTest);
+  nmtMtTest2 = os::malloc(256 * 1024, mtTest);
+  os::free(mem, mtTest);
+  nmtMtTest3 = os::malloc(128 * 1024, mtTest);
+
+  return true;
+WB_END
+
+// Free the memory allocated by NMTAllocTest
+WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env))
+
+  if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) {
+    return false;
+  }
+
+  os::free(nmtMtTest1, mtTest);
+  nmtMtTest1 = NULL;
+  os::free(nmtMtTest2, mtTest);
+  nmtMtTest2 = NULL;
+  os::free(nmtMtTest3, mtTest);
+  nmtMtTest3 = NULL;
+
+  return true;
+WB_END
+
+// Block until the current generation of NMT data to be merged, used to reliably test the NMT feature
+WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env))
+
+  if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
+    return false;
+  }
+
+  return MemTracker::wbtest_wait_for_data_merge();
+WB_END
+
 //Some convenience methods to deal with objects from java
 int WhiteBox::offset_for_field(const char* field_name, oop object,
     Symbol* signature_symbol) {
@@ -143,6 +196,9 @@
   {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
   {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
 #endif // !SERIALGC
+  {CC"NMTAllocTest",       CC"()Z",                   (void*)&WB_NMTAllocTest      },
+  {CC"NMTFreeTestMemory",  CC"()Z",                   (void*)&WB_NMTFreeTestMemory },
+  {CC"NMTWaitForDataMerge",CC"()Z",                   (void*)&WB_NMTWaitForDataMerge},
 };
 
 #undef CC
--- a/src/share/vm/runtime/arguments.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/runtime/arguments.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -809,7 +809,8 @@
     return true;
   }
 
-  const char * const argname = *arg == '+' || *arg == '-' ? arg + 1 : arg;
+  bool has_plus_minus = (*arg == '+' || *arg == '-');
+  const char* const argname = has_plus_minus ? arg + 1 : arg;
   if (is_newly_obsolete(arg, &since)) {
     char version[256];
     since.to_string(version, sizeof(version));
@@ -817,32 +818,38 @@
     return true;
   }
 
-  // Make a copy and remove everything after '=' (if there is something)
-#define BUFLEN 255
-  char name[BUFLEN+1];
-  strncpy(name, argname, BUFLEN);
-  name[BUFLEN] = '\0';
-  char* end = strchr(name, '=');
-  if (end != NULL) {
-    end[0] = '\0';
+  // For locked flags, report a custom error message if available.
+  // Otherwise, report a standard VM option message.
+
+  size_t arg_len;
+  const char* equal_sign = strchr(argname, '=');
+  if (equal_sign == NULL) {
+    arg_len = strlen(argname);
+  } else {
+    arg_len = equal_sign - argname;
   }
 
-  // For locked flags, report a custom error message if available.
-  // Otherwise, report the standard unrecognized VM option.
-
-  Flag* locked_flag = Flag::find_flag((char*)name, strlen(name), true);
-  if (locked_flag != NULL && !locked_flag->is_unlocked()) {
+  Flag* found_flag = Flag::find_flag((char*)argname, arg_len, true);
+  if (found_flag != NULL) {
     char locked_message_buf[BUFLEN];
-    locked_flag->get_locked_message(locked_message_buf, BUFLEN);
+    found_flag->get_locked_message(locked_message_buf, BUFLEN);
     if (strlen(locked_message_buf) == 0) {
-      jio_fprintf(defaultStream::error_stream(),
-        "Unrecognized VM option '%s'\n", name);
+     if (found_flag->is_bool() && !has_plus_minus) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "Missing +/- setting for VM option '%s'\n", argname);
+      } else if (!found_flag->is_bool() && has_plus_minus) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "Unexpected +/- setting in VM option '%s'\n", argname);
+      } else {
+        jio_fprintf(defaultStream::error_stream(),
+                    "Improperly specified VM option '%s'\n", argname);
+      }
     } else {
       jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf);
     }
   } else {
     jio_fprintf(defaultStream::error_stream(),
-                "Unrecognized VM option '%s'\n", name);
+                "Unrecognized VM option '%s'\n", argname);
   }
 
   // allow for commandline "commenting out" options like -XX:#+Verbose
--- a/src/share/vm/runtime/mutex.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/runtime/mutex.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1312,7 +1312,7 @@
           this->rank() != Mutex::suspend_resume &&
           locks != NULL && locks->rank() <= this->rank() &&
           !SafepointSynchronize::is_at_safepoint() &&
-          this != Interrupt_lock && this != ProfileVM_lock &&
+          this != Interrupt_lock &&
           !(this == Safepoint_lock && contains(locks, Terminator_lock) &&
             SafepointSynchronize::is_synchronizing())) {
         new_owner->print_owned_locks();
--- a/src/share/vm/runtime/mutexLocker.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/runtime/mutexLocker.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -103,7 +103,6 @@
 Monitor* BeforeExit_lock              = NULL;
 Monitor* Notify_lock                  = NULL;
 Monitor* Interrupt_lock               = NULL;
-Monitor* ProfileVM_lock               = NULL;
 Mutex*   ProfilePrint_lock            = NULL;
 Mutex*   ExceptionCache_lock          = NULL;
 Monitor* ObjAllocPost_lock            = NULL;
@@ -279,7 +278,6 @@
   def(MethodCompileQueue_lock      , Monitor, nonleaf+4,   true );
   def(Debug2_lock                  , Mutex  , nonleaf+4,   true );
   def(Debug3_lock                  , Mutex  , nonleaf+4,   true );
-  def(ProfileVM_lock               , Monitor, special,   false); // used for profiling of the VMThread
   def(CompileThread_lock           , Monitor, nonleaf+5,   false );
 
   def(JfrMsg_lock                  , Monitor, nonleaf+2,   true);
--- a/src/share/vm/runtime/mutexLocker.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/runtime/mutexLocker.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -108,7 +108,6 @@
 extern Monitor* BeforeExit_lock;                 // a lock used to guard cleanups and shutdown hooks
 extern Monitor* Notify_lock;                     // a lock used to synchronize the start-up of the vm
 extern Monitor* Interrupt_lock;                  // a lock used for condition variable mediated interrupt processing
-extern Monitor* ProfileVM_lock;                  // a lock used for profiling the VMThread
 extern Mutex*   ProfilePrint_lock;               // a lock used to serialize the printing of profiles
 extern Mutex*   ExceptionCache_lock;             // a lock used to synchronize exception cache updates
 extern Mutex*   OsrList_lock;                    // a lock used to serialize access to OSR queues
--- a/src/share/vm/runtime/os.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/runtime/os.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -869,6 +869,7 @@
         st->print(" for ");
         nm->method()->print_value_on(st);
       }
+      st->cr();
       nm->print_nmethod(verbose);
       return;
     }
--- a/src/share/vm/runtime/sweeper.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/runtime/sweeper.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -148,12 +148,12 @@
 
 int       NMethodSweeper::_number_of_flushes = 0; // Total of full traversals caused by full cache
 int       NMethodSweeper::_total_nof_methods_reclaimed = 0;
-long      NMethodSweeper::_total_time_sweeping = 0;
-long      NMethodSweeper::_total_time_this_sweep = 0;
-long      NMethodSweeper::_peak_sweep_time = 0;
-long      NMethodSweeper::_peak_sweep_fraction_time = 0;
-long      NMethodSweeper::_total_disconnect_time = 0;
-long      NMethodSweeper::_peak_disconnect_time = 0;
+jlong     NMethodSweeper::_total_time_sweeping = 0;
+jlong     NMethodSweeper::_total_time_this_sweep = 0;
+jlong     NMethodSweeper::_peak_sweep_time = 0;
+jlong     NMethodSweeper::_peak_sweep_fraction_time = 0;
+jlong     NMethodSweeper::_total_disconnect_time = 0;
+jlong     NMethodSweeper::_peak_disconnect_time = 0;
 
 class MarkActivationClosure: public CodeBlobClosure {
 public:
@@ -257,9 +257,7 @@
 
 void NMethodSweeper::sweep_code_cache() {
 
-  long sweep_start_counter, sweep_end_counter;
-  long sweep_time;
-  sweep_start_counter = os::elapsed_counter();
+  jlong sweep_start_counter = os::elapsed_counter();
 
   _flushed_count   = 0;
   _zombified_count = 0;
@@ -324,8 +322,8 @@
     }
   }
 
-  sweep_end_counter = os::elapsed_counter();
-  sweep_time = sweep_end_counter - sweep_start_counter;
+  jlong sweep_end_counter = os::elapsed_counter();
+  jlong sweep_time = sweep_end_counter - sweep_start_counter;
   _total_time_sweeping  += sweep_time;
   _total_time_this_sweep += sweep_time;
   _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time);
@@ -523,10 +521,6 @@
   // If there was a race in detecting full code cache, only run
   // one vm op for it or keep the compiler shut off
 
-  long disconnect_start_counter;
-  long disconnect_end_counter;
-  long disconnect_time;
-
   if ((!was_full()) && (is_full)) {
     if (!CodeCache::needs_flushing()) {
       log_sweep("restart_compiler");
@@ -535,7 +529,7 @@
     }
   }
 
-  disconnect_start_counter = os::elapsed_counter();
+  jlong disconnect_start_counter = os::elapsed_counter();
 
   // Traverse the code cache trying to dump the oldest nmethods
   uint curr_max_comp_id = CompileBroker::get_compilation_id();
@@ -583,8 +577,8 @@
     CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation);
   }
 
-  disconnect_end_counter = os::elapsed_counter();
-  disconnect_time = disconnect_end_counter - disconnect_start_counter;
+  jlong disconnect_end_counter = os::elapsed_counter();
+  jlong disconnect_time = disconnect_end_counter - disconnect_start_counter;
   _total_disconnect_time += disconnect_time;
   _peak_disconnect_time = MAX2(disconnect_time, _peak_disconnect_time);
 
--- a/src/share/vm/runtime/sweeper.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/runtime/sweeper.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -54,28 +54,28 @@
   static long      _was_full_traversal;   // trav number at last emergency unloading
 
   // Stat counters
-  static int       _number_of_flushes;           // Total of full traversals caused by full cache
-  static int       _total_nof_methods_reclaimed; // Accumulated nof methods flushed
-  static long      _total_time_sweeping;         // Accumulated time sweeping
-  static long      _total_time_this_sweep;       // Total time this sweep
-  static long      _peak_sweep_time;             // Peak time for a full sweep
-  static long      _peak_sweep_fraction_time;    // Peak time sweeping one fraction
-  static long      _total_disconnect_time;       // Total time cleaning code mem
-  static long      _peak_disconnect_time;        // Peak time cleaning code mem
+  static int       _number_of_flushes;            // Total of full traversals caused by full cache
+  static int       _total_nof_methods_reclaimed;  // Accumulated nof methods flushed
+  static jlong     _total_time_sweeping;          // Accumulated time sweeping
+  static jlong     _total_time_this_sweep;        // Total time this sweep
+  static jlong     _peak_sweep_time;              // Peak time for a full sweep
+  static jlong     _peak_sweep_fraction_time;     // Peak time sweeping one fraction
+  static jlong     _total_disconnect_time;        // Total time cleaning code mem
+  static jlong     _peak_disconnect_time;         // Peak time cleaning code mem
 
   static void process_nmethod(nmethod *nm);
 
   static void log_sweep(const char* msg, const char* format = NULL, ...);
 
  public:
-  static long traversal_count()             { return _traversals; }
-  static int  number_of_flushes()           { return _number_of_flushes; }
-  static int  total_nof_methods_reclaimed() { return _total_nof_methods_reclaimed; }
-  static long total_time_sweeping()         { return _total_time_sweeping; }
-  static long peak_sweep_time()             { return _peak_sweep_time; }
-  static long peak_sweep_fraction_time()    { return _peak_sweep_fraction_time; }
-  static long total_disconnect_time()       { return _total_disconnect_time; }
-  static long peak_disconnect_time()        { return _peak_disconnect_time; }
+  static long traversal_count()              { return _traversals; }
+  static int  number_of_flushes()            { return _number_of_flushes; }
+  static int  total_nof_methods_reclaimed()  { return _total_nof_methods_reclaimed; }
+  static jlong total_time_sweeping()         { return _total_time_sweeping; }
+  static jlong peak_sweep_time()             { return _peak_sweep_time; }
+  static jlong peak_sweep_fraction_time()    { return _peak_sweep_fraction_time; }
+  static jlong total_disconnect_time()       { return _total_disconnect_time; }
+  static jlong peak_disconnect_time()        { return _peak_disconnect_time; }
 
 #ifdef ASSERT
   // Keep track of sweeper activity in the ring buffer
--- a/src/share/vm/services/memBaseline.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memBaseline.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -41,6 +41,7 @@
   {mtTracing,    "Tracing"},
   {mtChunk,      "Pooled Free Chunks"},
   {mtClassShared,"Shared spaces for classes"},
+  {mtTest,       "Test"},
   {mtNone,       "Unknown"}  // It can happen when type tagging records are lagging
                              // behind
 };
--- a/src/share/vm/services/memPtr.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memPtr.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -27,8 +27,8 @@
 #include "services/memTracker.hpp"
 
 volatile jint SequenceGenerator::_seq_number = 1;
+volatile unsigned long SequenceGenerator::_generation = 1;
 NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;)
-DEBUG_ONLY(volatile unsigned long SequenceGenerator::_generation = 0;)
 
 jint SequenceGenerator::next() {
   jint seq = Atomic::add(1, &_seq_number);
--- a/src/share/vm/services/memPtr.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memPtr.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -47,16 +47,16 @@
   static void reset() {
     assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
     _seq_number = 1;
-    DEBUG_ONLY(_generation ++;)
+    _generation ++;
   };
 
-  DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; })
+  static unsigned long current_generation() { return _generation; }
   NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; })
 
  private:
-  static volatile jint _seq_number;
-  NOT_PRODUCT(static jint _max_seq_number; )
-  DEBUG_ONLY(static volatile unsigned long _generation; )
+  static volatile jint             _seq_number;
+  static volatile unsigned long    _generation;
+  NOT_PRODUCT(static jint          _max_seq_number; )
 };
 
 /*
--- a/src/share/vm/services/memRecorder.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memRecorder.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -55,7 +55,7 @@
 MemRecorder::MemRecorder() {
   assert(MemTracker::is_on(), "Native memory tracking is off");
   Atomic::inc(&_instance_count);
-  debug_only(set_generation();)
+  set_generation();
 
   if (MemTracker::track_callsite()) {
     _pointer_records = new (std::nothrow)FixedSizeMemPointerArray<SeqMemPointerRecordEx,
@@ -151,11 +151,12 @@
 }
 
 
-#ifdef ASSERT
 void MemRecorder::set_generation() {
   _generation = SequenceGenerator::current_generation();
 }
 
+#ifdef ASSERT
+
 void MemRecorder::check_dup_seq(jint seq) const {
   MemPointerArrayIteratorImpl itr(_pointer_records);
   MemPointerRecord* rc = (MemPointerRecord*)itr.current();
--- a/src/share/vm/services/memRecorder.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memRecorder.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -213,7 +213,7 @@
   // used for linked list
   MemRecorder*             _next;
   // active recorder can only record a certain generation data
-  debug_only(unsigned long _generation;)
+  unsigned long            _generation;
 
  protected:
   _NOINLINE_ MemRecorder();
@@ -251,6 +251,8 @@
 
   SequencedRecordIterator pointer_itr();
 
+  // return the generation of this recorder which it belongs to
+  unsigned long get_generation() const { return _generation; }
  protected:
   // number of MemRecorder instance
   static volatile jint _instance_count;
@@ -263,7 +265,7 @@
   static int sort_record_fn(const void* e1, const void* e2);
 
   debug_only(void check_dup_seq(jint seq) const;)
-  debug_only(void set_generation();)
+  void set_generation();
 };
 
 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP
--- a/src/share/vm/services/memTrackWorker.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memTrackWorker.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -91,6 +91,8 @@
   MemSnapshot* snapshot = MemTracker::get_snapshot();
   assert(snapshot != NULL, "Worker should not be started");
   MemRecorder* rec;
+  unsigned long processing_generation = 0;
+  bool          worker_idle = false;
 
   while (!MemTracker::shutdown_in_progress()) {
     NOT_PRODUCT(_last_gen_in_use = generations_in_use();)
@@ -100,6 +102,12 @@
       rec = _gen[_head].next_recorder();
     }
     if (rec != NULL) {
+      if (rec->get_generation() != processing_generation || worker_idle) {
+        processing_generation = rec->get_generation();
+        worker_idle = false;
+        MemTracker::set_current_processing_generation(processing_generation);
+      }
+
       // merge the recorder into staging area
       if (!snapshot->merge(rec)) {
         MemTracker::shutdown(MemTracker::NMT_out_of_memory);
@@ -129,6 +137,9 @@
           MemTracker::shutdown(MemTracker::NMT_out_of_memory);
         }
       } else {
+        // worker thread is idle
+        worker_idle = true;
+        MemTracker::report_worker_idle();
         snapshot->wait(1000);
         ThreadCritical tc;
         // check if more data arrived
--- a/src/share/vm/services/memTrackWorker.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memTrackWorker.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -107,6 +107,7 @@
   NOT_PRODUCT(int _merge_count;)
   NOT_PRODUCT(int _last_gen_in_use;)
 
+  // how many generations are queued
   inline int generations_in_use() const {
     return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1));
   }
--- a/src/share/vm/services/memTracker.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memTracker.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -29,6 +29,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/threadCritical.hpp"
+#include "runtime/vm_operations.hpp"
 #include "services/memPtr.hpp"
 #include "services/memReporter.hpp"
 #include "services/memTracker.hpp"
@@ -65,6 +66,8 @@
 MemTracker::ShutdownReason      MemTracker::_reason = NMT_shutdown_none;
 int                             MemTracker::_thread_count = 255;
 volatile jint                   MemTracker::_pooled_recorder_count = 0;
+volatile unsigned long          MemTracker::_processing_generation = 0;
+volatile bool                   MemTracker::_worker_thread_idle = false;
 debug_only(intx                 MemTracker::_main_thread_tid = 0;)
 NOT_PRODUCT(volatile jint       MemTracker::_pending_recorder_count = 0;)
 
@@ -279,7 +282,7 @@
      }
      cur_head->set_next(NULL);
      Atomic::dec(&_pooled_recorder_count);
-     debug_only(cur_head->set_generation();)
+     cur_head->set_generation();
      return cur_head;
   }
 }
@@ -570,6 +573,51 @@
   return false;
 }
 
+// Whitebox API for blocking until the current generation of NMT data has been merged
+bool MemTracker::wbtest_wait_for_data_merge() {
+  // NMT can't be shutdown while we're holding _query_lock
+  MutexLockerEx lock(_query_lock, true);
+  assert(_worker_thread != NULL, "Invalid query");
+  // the generation at query time, so NMT will spin till this generation is processed
+  unsigned long generation_at_query_time = SequenceGenerator::current_generation();
+  unsigned long current_processing_generation = _processing_generation;
+  // if generation counter overflown
+  bool generation_overflown = (generation_at_query_time < current_processing_generation);
+  long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation;
+  // spin
+  while (!shutdown_in_progress()) {
+    if (!generation_overflown) {
+      if (current_processing_generation > generation_at_query_time) {
+        return true;
+      }
+    } else {
+      assert(generations_to_wrap >= 0, "Sanity check");
+      long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation;
+      assert(current_generations_to_wrap >= 0, "Sanity check");
+      // to overflow an unsigned long should take long time, so to_wrap check should be sufficient
+      if (current_generations_to_wrap > generations_to_wrap &&
+          current_processing_generation > generation_at_query_time) {
+        return true;
+      }
+    }
+
+    // if worker thread is idle, but generation is not advancing, that means
+    // there is not safepoint to let NMT advance generation, force one.
+    if (_worker_thread_idle) {
+      VM_ForceSafepoint vfs;
+      VMThread::execute(&vfs);
+    }
+    MemSnapshot* snapshot = get_snapshot();
+    if (snapshot == NULL) {
+      return false;
+    }
+    snapshot->wait(1000);
+    current_processing_generation = _processing_generation;
+  }
+  // We end up here if NMT is shutting down before our data has been merged
+  return false;
+}
+
 // compare memory usage between current snapshot and baseline
 bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) {
   MutexLockerEx lock(_query_lock, true);
--- a/src/share/vm/services/memTracker.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/services/memTracker.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -41,6 +41,10 @@
 
 extern bool NMT_track_callsite;
 
+#ifndef MAX_UNSIGNED_LONG
+#define MAX_UNSIGNED_LONG    (unsigned long)(-1)
+#endif
+
 #ifdef ASSERT
   #define DEBUG_CALLER_PC  (NMT_track_callsite ? os::get_caller_pc(2) : 0)
 #else
@@ -310,6 +314,11 @@
   static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
            bool summary_only = true);
 
+  // the version for whitebox testing support, it ensures that all memory
+  // activities before this method call, are reflected in the snapshot
+  // database.
+  static bool wbtest_wait_for_data_merge();
+
   // sync is called within global safepoint to synchronize nmt data
   static void sync();
 
@@ -362,6 +371,15 @@
   static void create_record_in_recorder(address addr, MEMFLAGS type,
                    size_t size, address pc, JavaThread* thread);
 
+  static void set_current_processing_generation(unsigned long generation) {
+    _worker_thread_idle = false;
+    _processing_generation = generation;
+  }
+
+  static void report_worker_idle() {
+    _worker_thread_idle = true;
+  }
+
  private:
   // global memory snapshot
   static MemSnapshot*     _snapshot;
@@ -413,6 +431,11 @@
   static volatile enum NMTStates   _state;
   // the reason for shutting down nmt
   static enum ShutdownReason       _reason;
+  // the generation that NMT is processing
+  static volatile unsigned long    _processing_generation;
+  // although NMT is still procesing current generation, but
+  // there is not more recorder to process, set idle state
+  static volatile bool             _worker_thread_idle;
 };
 
 #endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP
--- a/src/share/vm/trace/traceEventClasses.xsl	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/trace/traceEventClasses.xsl	Thu Feb 14 22:29:42 2013 -0800
@@ -36,6 +36,7 @@
 // Some parts of traceEvent.hpp are used outside of
 // INCLUDE_TRACE
 
+#include "memory/resourceArea.hpp"
 #include "tracefiles/traceTypes.hpp"
 #include "trace/traceEvent.hpp"
 
@@ -128,6 +129,7 @@
 </xsl:text>
   <xsl:value-of select="concat('  Event', @id, '(EventStartTime timing=TIMED) : TraceEvent&lt;Event', @id, '&gt;(timing) {}', $newline)"/>
   void writeEvent(void) {
+    ResourceMark rm;
     TraceStream ts(*tty);
     ts.print("<xsl:value-of select="@label"/>: [");
 <xsl:apply-templates select="value|structvalue" mode="write-data"/>
--- a/src/share/vm/utilities/accessFlags.cpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/utilities/accessFlags.cpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -59,8 +59,6 @@
   } while(f != old_flags);
 }
 
-#ifndef PRODUCT
-
 void AccessFlags::print_on(outputStream* st) const {
   if (is_public      ()) st->print("public "      );
   if (is_private     ()) st->print("private "     );
@@ -79,8 +77,6 @@
   if (is_obsolete    ()) st->print("{obsolete} "  );
 }
 
-#endif
-
 void accessFlags_init() {
   assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags");
 }
--- a/src/share/vm/utilities/accessFlags.hpp	Wed Feb 13 17:56:44 2013 -0800
+++ b/src/share/vm/utilities/accessFlags.hpp	Thu Feb 14 22:29:42 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -229,7 +229,7 @@
   inline friend AccessFlags accessFlags_from(jint flags);
 
   // Printing/debugging
-  void print_on(outputStream* st) const PRODUCT_RETURN;
+  void print_on(outputStream* st) const;
 };
 
 inline AccessFlags accessFlags_from(jint flags) {
--- a/test/TEST.ROOT	Wed Feb 13 17:56:44 2013 -0800
+++ b/test/TEST.ROOT	Thu Feb 14 22:29:42 2013 -0800
@@ -28,4 +28,4 @@
 # DO NOT EDIT without first contacting hotspot-regtest@sun.com
 
 # The list of keywords supported in this test suite
-keys=cte_test
+keys=cte_test jcmd nmt regression
--- a/test/runtime/7158988/FieldMonitor.java	Wed Feb 13 17:56:44 2013 -0800
+++ b/test/runtime/7158988/FieldMonitor.java	Thu Feb 14 22:29:42 2013 -0800
@@ -24,8 +24,10 @@
 /*
  * @test FieldMonitor.java
  * @bug 7158988
+ * @key regression
  * @summary verify jvm does not crash while debugging
- * @run shell TestFieldMonitor.sh
+ * @run compile TestPostFieldModification.java
+ * @run main/othervm FieldMonitor
  * @author axel.siebenborn@sap.com
  */
 import java.io.BufferedReader;
--- a/test/runtime/7158988/TestFieldMonitor.sh	Wed Feb 13 17:56:44 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#!/bin/sh
-
-if [ "${TESTSRC}" = "" ]
-then TESTSRC=.
-fi
-
-if [ "${TESTJAVA}" = "" ]
-then
-  PARENT=`dirname \`which java\``
-  TESTJAVA=`dirname ${PARENT}`
-  echo "TESTJAVA not set, selecting " ${TESTJAVA}
-  echo "If this is incorrect, try setting the variable manually."
-fi
-
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin)
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    ;;
-  Windows_95 | Windows_98 | Windows_ME )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    echo "Test skipped, only for WinNT"
-    exit 0
-    ;;
-  Windows_NT )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    ;;
-  CYGWIN_NT* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    ;;
-  CYGWIN_* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    echo "Test skipped, only for WinNT"
-    exit 0
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH
-
-cp ${TESTSRC}${FS}*.java .
-
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion
-
-${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java
-
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out
-
-grep "A fatal error has been detected" test.out > ${NULL}
-if [ $? = 0 ]; then
-    cat test.out
-    STATUS=1
-fi
-
-exit $STATUS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/AllocTestType.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,72 @@
+/*
+ * 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 consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd
+ * @key nmt jcmd
+ * @library /testlibrary
+ * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI AllocTestType.java
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class AllocTestType {
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Use WB API to alloc with the mtTest type
+    if (!WhiteBox.getWhiteBox().NMTAllocTest()) {
+      throw new Exception("Call to WB API NMTAllocTest() failed");
+    }
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    // Run 'jcmd <pid> VM.native_memory summary'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=512KB)");
+
+    // Free the memory allocated by NMTAllocTest
+    if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) {
+      throw new Exception("Call to WB API NMTFreeTestMemory() failed");
+    }
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/BaselineWithParameter.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,54 @@
+/*
+ * 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
+ * @bug 8004802
+ * @key nmt jcmd regression
+ * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed
+ * @library /testlibrary
+ * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class BaselineWithParameter {
+
+  public static void main(String args[]) throws Exception {
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    OutputAnalyzer output;
+
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run 'jcmd <pid> VM.native_memory baseline=false'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"});
+    pb.start();
+
+    // Run 'jcmd <pid> VM.native_memory summary=false'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("No command to execute");
+
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineDetail.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,45 @@
+/*
+ * 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
+ * @key nmt
+ * @summary Running with NMT detail should not result in an error or warning
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineDetail {
+
+  public static void main(String args[]) throws Exception {
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:NativeMemoryTracking=detail",
+      "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("error");
+    output.shouldNotContain("warning");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineEmptyArgument.java	Thu Feb 14 22:29:42 2013 -0800
@@ -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
+ * @key nmt
+ * @summary Empty argument to NMT should result in an informative error message
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineEmptyArgument {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking=");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]");
+    output.shouldHaveExitValue(1);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineInvalidArgument.java	Thu Feb 14 22:29:42 2013 -0800
@@ -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
+ * @key nmt
+ * @summary Invalid argument to NMT should result in an informative error message
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineInvalidArgument {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking=apa");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]");
+    output.shouldHaveExitValue(1);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineSummary.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,45 @@
+/*
+ * 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
+ * @key nmt
+ * @summary Running with NMT summary should not result in an error or warning
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineSummary {
+
+  public static void main(String args[]) throws Exception {
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:NativeMemoryTracking=summary",
+      "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("error");
+    output.shouldNotContain("warning");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineTurnOffNMT.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,44 @@
+/*
+ * 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
+ * @key nmt
+ * @summary Turning off NMT should not result in an error or warning
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineTurnOffNMT {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+              "-XX:NativeMemoryTracking=off",
+              "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("error");
+    output.shouldNotContain("warning");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/JcmdScale.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,67 @@
+/*
+ * 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
+ * @key nmt jcmd
+ * @summary Test the NMT scale parameter
+ * @library /testlibrary
+ * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class JcmdScale {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = new ProcessBuilder();
+    OutputAnalyzer output;
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("KB,  committed=");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("MB,  committed=");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("GB,  committed=");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Incorrect scale value: apa");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("GB,  committed=");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Incorrect scale value: apa");
+
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/JcmdWithNMTDisabled.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,63 @@
+/*
+ * 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
+ * @key nmt jcmd
+ * @summary Verify that jcmd correctly reports that NMT is not enabled
+ * @library /testlibrary
+ * First run without enabling NMT
+ * @run main/othervm JcmdWithNMTDisabled
+ * Then run with explicitly disabling NMT, should not be any difference
+ * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class JcmdWithNMTDisabled {
+  static ProcessBuilder pb = new ProcessBuilder();
+  static String pid;
+
+  public static void main(String args[]) throws Exception {
+    // Grab my own PID
+    pid = Integer.toString(ProcessTools.getProcessId());
+
+    jcmdCommand("summary");
+    jcmdCommand("detail");
+    jcmdCommand("baseline");
+    jcmdCommand("summary.diff");
+    jcmdCommand("detail.diff");
+    jcmdCommand("scale=GB");
+    jcmdCommand("shutdown");
+  }
+
+  // Helper method for invoking different jcmd calls, all should fail with the same message saying NMT is not enabled
+  public static void jcmdCommand(String command) throws Exception {
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", command});
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT is not enabled
+    output.shouldContain("Native memory tracking is not enabled");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/PrintNMTStatistics.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,66 @@
+/*
+ * 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
+ * @key nmt regression
+ * @bug 8005936
+ * @summary Make sure PrintNMTStatistics works on normal JVM exit
+ * @library /testlibrary
+ * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI PrintNMTStatistics.java
+ */
+
+import com.oracle.java.testlibrary.*;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.hotspot.WhiteBox;
+
+public class PrintNMTStatistics {
+
+  public static void main(String args[]) throws Exception {
+
+    // We start a new java process running with an argument and use WB API to ensure
+    // we have data for NMT on VM exit
+    if (args.length > 0) {
+      // Use WB API to ensure that all data has been merged before we continue
+      if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
+        throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+      }
+      return;
+    }
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+UnlockDiagnosticVMOptions",
+        "-XX:NativeMemoryTracking=summary",
+        "+XX:+PrintNMTStatistics",
+        "PrintNMTStatistics",
+        "test");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Java Heap  (reserved=");
+    output.shouldNotContain("error");
+    output.shouldNotContain("warning");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,44 @@
+/*
+ * 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
+ * @key nmt
+ * @summary Trying to enable PrintNMTStatistics should result in a warning
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class PrintNMTStatisticsWithNMTDisabled {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:+UnlockDiagnosticVMOptions",
+      "-XX:+PrintNMTStatistics",
+      "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("warning: PrintNMTStatistics is disabled, because native memory tracking is not enabled");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/ShutdownTwice.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,56 @@
+/*
+ * 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
+ * @key nmt jcmd
+ * @summary Run shutdown twice
+ * @library /testlibrary
+ * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class ShutdownTwice {
+
+  public static void main(String args[]) throws Exception {
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    OutputAnalyzer output;
+
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run 'jcmd <pid> VM.native_memory shutdown'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"});
+    output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT is shutting down
+    output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown");
+
+    // Run shutdown again
+    output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT has been shutdown already
+    output.shouldContain("Native memory tracking has been shutdown by user");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/SummaryAfterShutdown.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,56 @@
+/*
+ * 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
+ * @key nmt jcmd
+ * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown
+ * @library /testlibrary
+ * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class SummaryAfterShutdown {
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run 'jcmd <pid> VM.native_memory shutdown'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"});
+    output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT is shutting down
+    output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown");
+
+    // Run 'jcmd <pid> VM.native_memory summary'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
+    output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT has been shutdown
+    output.shouldContain("Native memory tracking has been shutdown by user");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/SummarySanityCheck.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,119 @@
+/*
+ * 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
+ * @key nmt jcmd
+ * @summary Sanity check the output of NMT
+ * @library /testlibrary
+ * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI SummarySanityCheck.java
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck
+ */
+
+import com.oracle.java.testlibrary.*;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.hotspot.WhiteBox;
+
+public class SummarySanityCheck {
+
+  private static String jcmdout;
+  public static void main(String args[]) throws Exception {
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run  'jcmd <pid> VM.native_memory summary scale=KB'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=KB"});
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    jcmdout = output.getOutput();
+    // Split by '-' to get the 'groups'
+    String[] lines = jcmdout.split("\n");
+
+    if (lines.length == 0) {
+      throwTestException("Failed to parse jcmd output");
+    }
+
+    int totalCommitted = 0, totalReserved = 0;
+    int totalCommittedSum = 0, totalReservedSum = 0;
+
+    // Match '- <mtType> (reserved=<reserved>KB, committed=<committed>KB)
+    Pattern mtTypePattern = Pattern.compile("-\\s+(?<typename>[\\w\\s]+)\\(reserved=(?<reserved>\\d+)KB,\\scommitted=(?<committed>\\d+)KB\\)");
+    // Match 'Total: reserved=<reserved>KB, committed=<committed>KB'
+    Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?<reserved>\\d+)KB,\\s\\scommitted=(?<committed>\\d+)KB");
+
+    for (int i = 0; i < lines.length; i++) {
+      if (lines[i].startsWith("Total")) {
+        Matcher totalMemoryMatcher = totalMemoryPattern.matcher(lines[i]);
+
+        if (totalMemoryMatcher.matches() && totalMemoryMatcher.groupCount() == 2) {
+          totalCommitted = Integer.parseInt(totalMemoryMatcher.group("committed"));
+          totalReserved = Integer.parseInt(totalMemoryMatcher.group("reserved"));
+        } else {
+          throwTestException("Failed to match the expected groups in 'Total' memory part");
+        }
+      } else if (lines[i].startsWith("-")) {
+        Matcher typeMatcher = mtTypePattern.matcher(lines[i]);
+        if (typeMatcher.matches()) {
+          int typeCommitted = Integer.parseInt(typeMatcher.group("committed"));
+          int typeReserved = Integer.parseInt(typeMatcher.group("reserved"));
+
+          // Make sure reserved is always less or equals
+          if (typeCommitted > typeReserved) {
+            throwTestException("Committed (" + typeCommitted + ") was more than Reserved ("
+                + typeReserved + ") for mtType: " + typeMatcher.group("typename"));
+          }
+
+          // Add to total and compare them in the end
+          totalCommittedSum += typeCommitted;
+          totalReservedSum += typeReserved;
+        } else {
+          throwTestException("Failed to match the group on line " + i);
+        }
+      }
+    }
+
+    // See if they add up correctly, rounding is a problem so make sure we're within +/- 8KB
+    int committedDiff = totalCommitted - totalCommittedSum;
+    if (committedDiff > 8 || committedDiff < -8) {
+      throwTestException("Total committed (" + totalCommitted + ") did not match the summarized committed (" + totalCommittedSum + ")" );
+    }
+
+    int reservedDiff = totalReserved - totalReservedSum;
+    if (reservedDiff > 8 || reservedDiff < -8) {
+      throwTestException("Total reserved (" + totalReserved + ") did not match the summarized reserved (" + totalReservedSum + ")" );
+    }
+  }
+
+  private static void throwTestException(String reason) throws Exception {
+      throw new Exception(reason + " . Stdout is :\n" + jcmdout);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/OutputAnalyzerTest.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,108 @@
+/*
+ * 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 the OutputAnalyzer utility class
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class OutputAnalyzerTest {
+
+  public static void main(String args[]) throws Exception {
+
+    String stdout = "aaaaaa";
+    String stderr = "bbbbbb";
+
+    OutputAnalyzer output = new OutputAnalyzer(stdout, stderr);
+
+    if (!stdout.equals(output.getStdout())) {
+      throw new Exception("getStdout() returned '" + output.getStdout() + "', expected '" + stdout + "'");
+    }
+
+    if (!stderr.equals(output.getStderr())) {
+      throw new Exception("getStderr() returned '" + output.getStderr() + "', expected '" + stderr + "'");
+    }
+
+    try {
+      output.shouldContain(stdout);
+      output.stdoutShouldContain(stdout);
+      output.shouldContain(stderr);
+      output.stderrShouldContain(stderr);
+    } catch (RuntimeException e) {
+      throw new Exception("shouldContain() failed", e);
+    }
+
+    try {
+      output.shouldContain("cccc");
+      throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.stdoutShouldContain(stderr);
+      throw new Exception("stdoutShouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.stderrShouldContain(stdout);
+      throw new Exception("stdoutShouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.shouldNotContain("cccc");
+      output.stdoutShouldNotContain("cccc");
+      output.stderrShouldNotContain("cccc");
+    } catch (RuntimeException e) {
+      throw new Exception("shouldNotContain() failed", e);
+    }
+
+    try {
+      output.shouldNotContain(stdout);
+      throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.stdoutShouldNotContain(stdout);
+      throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.stderrShouldNotContain(stderr);
+      throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+import java.io.File;
+
+public final class JDKToolFinder {
+
+  private JDKToolFinder() {
+  }
+
+  /**
+   * Returns the full path to an executable in jdk/bin based on System property
+   * test.jdk (set by jtreg test suite)
+   *
+   * @return Full path to an executable in jdk/bin
+   */
+  public static String getJDKTool(String tool) {
+    String binPath = System.getProperty("test.jdk");
+    if (binPath == null) {
+      throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. "
+          + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'.");
+    }
+
+    binPath += File.separatorChar + "bin" + File.separatorChar + tool;
+
+    return binPath;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+import java.io.IOException;
+
+public final class OutputAnalyzer {
+
+  private final String stdout;
+  private final String stderr;
+  private final int exitValue;
+
+  /**
+   * Create an OutputAnalyzer, a utility class for verifying output and exit
+   * value from a Process
+   *
+   * @param process Process to analyze
+   * @throws IOException If an I/O error occurs.
+   */
+  public OutputAnalyzer(Process process) throws IOException {
+    OutputBuffer output = ProcessTools.getOutput(process);
+    exitValue = process.exitValue();
+    this.stdout = output.getStdout();
+    this.stderr = output.getStderr();
+  }
+
+  /**
+   * Create an OutputAnalyzer, a utility class for verifying output
+   *
+   * @param buf String buffer to analyze
+   */
+  public OutputAnalyzer(String buf) {
+    this(buf, buf);
+  }
+
+  /**
+   * Create an OutputAnalyzer, a utility class for verifying output
+   *
+   * @param stdout stdout buffer to analyze
+   * @param stderr stderr buffer to analyze
+   */
+  public OutputAnalyzer(String stdout, String stderr) {
+    this.stdout = stdout;
+    this.stderr = stderr;
+    exitValue = -1;
+  }
+
+  /**
+   * Verify that the stdout and stderr contents of output buffer contains the string
+   *
+   * @param expectedString String that buffer should contain
+   * @throws RuntimeException If the string was not found
+   */
+  public void shouldContain(String expectedString) {
+    if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
+      throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr: [" + stdout + stderr + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stdout contents of output buffer contains the string
+   *
+   * @param expectedString String that buffer should contain
+   * @throws RuntimeException If the string was not found
+   */
+  public void stdoutShouldContain(String expectedString) {
+    if (!stdout.contains(expectedString)) {
+      throw new RuntimeException("'" + expectedString + "' missing from stdout: [" + stdout + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stderr contents of output buffer contains the string
+   *
+   * @param expectedString String that buffer should contain
+   * @throws RuntimeException If the string was not found
+   */
+  public void stderrShouldContain(String expectedString) {
+    if (!stderr.contains(expectedString)) {
+      throw new RuntimeException("'" + expectedString + "' missing from stderr: [" + stderr + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stdout and stderr contents of output buffer does not contain the string
+   *
+   * @param expectedString String that the buffer should not contain
+   * @throws RuntimeException If the string was found
+   */
+  public void shouldNotContain(String notExpectedString) {
+    if (stdout.contains(notExpectedString)) {
+      throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n");
+    }
+    if (stderr.contains(notExpectedString)) {
+      throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stdout contents of output buffer does not contain the string
+   *
+   * @param expectedString String that the buffer should not contain
+   * @throws RuntimeException If the string was found
+   */
+  public void stdoutShouldNotContain(String notExpectedString) {
+    if (stdout.contains(notExpectedString)) {
+      throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stderr contents of output buffer does not contain the string
+   *
+   * @param expectedString String that the buffer should not contain
+   * @throws RuntimeException If the string was found
+   */
+  public void stderrShouldNotContain(String notExpectedString) {
+    if (stderr.contains(notExpectedString)) {
+      throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n");
+    }
+  }
+
+  /**
+   * Verifiy the exit value of the process
+   *
+   * @param expectedExitValue Expected exit value from process
+   * @throws RuntimeException If the exit value from the process did not match the expected value
+   */
+  public void shouldHaveExitValue(int expectedExitValue) {
+    if (getExitValue() != expectedExitValue) {
+      throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue);
+    }
+  }
+
+  /**
+   * Get the contents of the output buffer (stdout and stderr)
+   *
+   * @return Content of the output buffer
+   */
+  public String getOutput() {
+    return stdout + stderr;
+  }
+
+  /**
+   * Get the contents of the stdout buffer
+   *
+   * @return Content of the stdout buffer
+   */
+  public String getStdout() {
+    return stdout;
+  }
+
+  /**
+   * Get the contents of the stderr buffer
+   *
+   * @return Content of the stderr buffer
+   */
+  public String getStderr() {
+    return stderr;
+  }
+
+  /**
+   * Get the process exit value
+   *
+   * @return Process exit value
+   */
+  public int getExitValue() {
+    return exitValue;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+public class OutputBuffer {
+  private final String stdout;
+  private final String stderr;
+
+  /**
+   * Create an OutputBuffer, a class for storing and managing stdout and stderr
+   * results separately
+   *
+   * @param stdout stdout result
+   * @param stderr stderr result
+   */
+  public OutputBuffer(String stdout, String stderr) {
+    this.stdout = stdout;
+    this.stderr = stderr;
+  }
+
+  /**
+   * Returns the stdout result
+   *
+   * @return stdout result
+   */
+  public String getStdout() {
+    return stdout;
+  }
+
+  /**
+   * Returns the stderr result
+   *
+   * @return stderr result
+   */
+  public String getStderr() {
+    return stderr;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import sun.management.VMManagement;
+
+public final class ProcessTools {
+
+  private ProcessTools() {
+  }
+
+  /**
+   * Pumps stdout and stderr from running the process into a String.
+   *
+   * @param processHandler ProcessHandler to run.
+   * @return Output from process.
+   * @throws IOException If an I/O error occurs.
+   */
+  public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException {
+    return getOutput(processBuilder.start());
+  }
+
+  /**
+   * Pumps stdout and stderr the running process into a String.
+   *
+   * @param process Process to pump.
+   * @return Output from process.
+   * @throws IOException If an I/O error occurs.
+   */
+  public static OutputBuffer getOutput(Process process) throws IOException {
+    ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
+    ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
+    StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer);
+    StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer);
+    Thread outPumperThread = new Thread(outPumper);
+    Thread errPumperThread = new Thread(errPumper);
+
+    outPumperThread.setDaemon(true);
+    errPumperThread.setDaemon(true);
+
+    outPumperThread.start();
+    errPumperThread.start();
+
+    try {
+      process.waitFor();
+      outPumperThread.join();
+      errPumperThread.join();
+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+      return null;
+    }
+
+    return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString());
+  }
+
+  /**
+   * Get the process id of the current running Java process
+   *
+   * @return Process id
+   */
+  public static int getProcessId() throws Exception {
+
+    // Get the current process id using a reflection hack
+    RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+    Field jvm = runtime.getClass().getDeclaredField("jvm");
+
+    jvm.setAccessible(true);
+    VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
+
+    Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
+
+    pid_method.setAccessible(true);
+
+    int pid = (Integer) pid_method.invoke(mgmt);
+
+    return pid;
+  }
+
+  /**
+   * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
+   *
+   * @return String[] with platform specific arguments, empty if there are none
+   */
+  public static String[] getPlatformSpecificVMArgs() {
+    String osName = System.getProperty("os.name");
+    String dataModel = System.getProperty("sun.arch.data.model");
+
+    if (osName.equals("SunOS") && dataModel.equals("64")) {
+      return new String[] { "-d64" };
+    }
+
+    return new String[] {};
+  }
+
+  /**
+   * Create ProcessBuilder using the java launcher from the jdk to be tested and
+   * with any platform specific arguments prepended
+   */
+  public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception {
+    String javapath = JDKToolFinder.getJDKTool("java");
+
+    ArrayList<String> args = new ArrayList<>();
+    args.add(javapath);
+    Collections.addAll(args, getPlatformSpecificVMArgs());
+    Collections.addAll(args, command);
+
+    return new ProcessBuilder(args.toArray(new String[args.size()]));
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java	Thu Feb 14 22:29:42 2013 -0800
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+public final class StreamPumper implements Runnable {
+
+  private static final int BUF_SIZE = 256;
+
+  private final OutputStream out;
+  private final InputStream in;
+
+  /**
+   * Create a StreamPumper that reads from in and writes to out.
+   *
+   * @param in The stream to read from.
+   * @param out The stream to write to.
+   */
+  public StreamPumper(InputStream in, OutputStream out) {
+    this.in = in;
+    this.out = out;
+  }
+
+  /**
+   * Implements Thread.run(). Continuously read from <code>in</code> and write
+   * to <code>out</code> until <code>in</code> has reached end of stream. Abort
+   * on interruption. Abort on IOExceptions.
+   */
+  @Override
+  public void run() {
+    int length;
+    InputStream localIn = in;
+    OutputStream localOut = out;
+    byte[] buffer = new byte[BUF_SIZE];
+
+    try {
+      while (!Thread.interrupted() && (length = localIn.read(buffer)) > 0) {
+        localOut.write(buffer, 0, length);
+      }
+    } catch (IOException e) {
+      // Just abort if something like this happens.
+      e.printStackTrace();
+    } finally {
+      try {
+        localOut.flush();
+        in.close();
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+  }
+}