changeset 4743:643da9d13379

8013917: Kitchensink crashed with SIGSEGV in BaselineReporter::diff_callsites Summary: Simple fix when memory allocation site is gone, NMT should report 0 memory size, instead old memory size. Reviewed-by: dcubed, ctornqvi
author zgu
date Mon, 10 Jun 2013 10:45:19 -0400
parents 79d6da9207c8
children a1a295252814 2d9b536bb027
files src/share/vm/services/memReporter.cpp test/runtime/NMT/JcmdDiffCallsite.java
diffstat 2 files changed, 89 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/services/memReporter.cpp	Thu Jun 06 10:15:11 2013 -0700
+++ b/src/share/vm/services/memReporter.cpp	Mon Jun 10 10:45:19 2013 -0400
@@ -190,17 +190,18 @@
   while (cur_malloc_callsite != NULL || prev_malloc_callsite != NULL) {
     if (prev_malloc_callsite == NULL ||
         cur_malloc_callsite->addr() < prev_malloc_callsite->addr()) {
+      // this is a new callsite
       _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(),
         amount_in_current_scale(cur_malloc_callsite->amount()),
         cur_malloc_callsite->count(),
         diff_in_current_scale(cur_malloc_callsite->amount(), 0),
         diff(cur_malloc_callsite->count(), 0));
       cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next();
-    } else if (prev_malloc_callsite == NULL ||
+    } else if (cur_malloc_callsite == NULL ||
                cur_malloc_callsite->addr() > prev_malloc_callsite->addr()) {
-      _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(),
-        amount_in_current_scale(prev_malloc_callsite->amount()),
-        prev_malloc_callsite->count(),
+      // this callsite is already gone
+      _outputer.diff_malloc_callsite(prev_malloc_callsite->addr(),
+        amount_in_current_scale(0), 0,
         diff_in_current_scale(0, prev_malloc_callsite->amount()),
         diff(0, prev_malloc_callsite->count()));
       prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next();
@@ -222,6 +223,7 @@
   VMCallsitePointer*          prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.current();
   while (cur_vm_callsite != NULL || prev_vm_callsite != NULL) {
     if (prev_vm_callsite == NULL || cur_vm_callsite->addr() < prev_vm_callsite->addr()) {
+      // this is a new callsite
       _outputer.diff_virtual_memory_callsite(cur_vm_callsite->addr(),
         amount_in_current_scale(cur_vm_callsite->reserved_amount()),
         amount_in_current_scale(cur_vm_callsite->committed_amount()),
@@ -229,9 +231,10 @@
         diff_in_current_scale(cur_vm_callsite->committed_amount(), 0));
       cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.next();
     } else if (cur_vm_callsite == NULL || cur_vm_callsite->addr() > prev_vm_callsite->addr()) {
+      // this callsite is already gone
       _outputer.diff_virtual_memory_callsite(prev_vm_callsite->addr(),
-        amount_in_current_scale(prev_vm_callsite->reserved_amount()),
-        amount_in_current_scale(prev_vm_callsite->committed_amount()),
+        amount_in_current_scale(0),
+        amount_in_current_scale(0),
         diff_in_current_scale(0, prev_vm_callsite->reserved_amount()),
         diff_in_current_scale(0, prev_vm_callsite->committed_amount()));
       prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.next();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/JcmdDiffCallsite.java	Mon Jun 10 10:45:19 2013 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test detail memory comparison against early baseline
+ * @bug 8013917
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build JcmdDiffCallsite
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail JcmdDiffCallsite
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class JcmdDiffCallsite {
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    WhiteBox wb = WhiteBox.getWhiteBox();
+
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Use WB API to alloc and free with the mtTest type
+    long memAlloc1 = wb.NMTMalloc(512 * 1024);
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    // Run 'jcmd <pid> VM.native_memory baseline'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline"});
+    pb.start();
+
+    wb.NMTFree(memAlloc1);
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    // Run 'jcmd <pid> VM.native_memory detail.diff'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff"});
+    output = new OutputAnalyzer(pb.start());
+
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    // above malloc callsite should report 0
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("(malloc=0");
+  }
+}