1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @summary Test merging of committed virtual memory and that we track it correctly
  27  * @key nmt jcmd
  28  * @library /test/lib
  29  * @modules java.base/jdk.internal.misc
  30  *          java.management
  31  * @build sun.hotspot.WhiteBox
  32  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  33  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocCommitMerge
  34  *
  35  */
  36 
  37 import jdk.test.lib.process.ProcessTools;
  38 import jdk.test.lib.process.OutputAnalyzer;
  39 import jdk.test.lib.JDKToolFinder;
  40 
  41 import sun.hotspot.WhiteBox;
  42 
  43 public class VirtualAllocCommitMerge {
  44 
  45     public static WhiteBox wb = WhiteBox.getWhiteBox();
  46 
  47     public static void main(String args[]) throws Exception {
  48         OutputAnalyzer output;
  49         long commitSize = 128 * 1024; // 128KB
  50         long reserveSize = 4 * 1024 * 1024; // 4096KB
  51         long addr;
  52 
  53         String pid = Long.toString(ProcessTools.getProcessId());
  54         ProcessBuilder pb = new ProcessBuilder();
  55 
  56         // reserve
  57         addr = wb.NMTReserveMemory(reserveSize);
  58         pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid,
  59                 "VM.native_memory", "detail" });
  60 
  61         output = new OutputAnalyzer(pb.start());
  62         checkReservedCommittedSummary(output, "4096KB", "0KB");
  63         checkReserved(output, addr, reserveSize, "4096KB");
  64 
  65         long addrA = addr + (0 * commitSize);
  66         long addrB = addr + (1 * commitSize);
  67         long addrC = addr + (2 * commitSize);
  68         long addrD = addr + (3 * commitSize);
  69         long addrE = addr + (4 * commitSize);
  70 
  71         {
  72             // commit overlapping ABC, A, B, C
  73             wb.NMTCommitMemory(addrA, 3 * commitSize);
  74 
  75             output = new OutputAnalyzer(pb.start());
  76             checkReservedCommittedSummary(output, "4096KB", "384KB");
  77             checkReserved(output, addr, reserveSize, "4096KB");
  78 
  79             checkCommitted(output, addrA, 3 * commitSize, "384KB");
  80 
  81 
  82             wb.NMTCommitMemory(addrA, commitSize);
  83 
  84             output = new OutputAnalyzer(pb.start());
  85             checkReservedCommittedSummary(output, "4096KB", "384KB");
  86             checkReserved(output, addr, reserveSize, "4096KB");
  87 
  88             checkCommitted(output, addrA, 3 * commitSize, "384KB");
  89 
  90 
  91             wb.NMTCommitMemory(addrB, commitSize);
  92 
  93             output = new OutputAnalyzer(pb.start());
  94             checkReservedCommittedSummary(output, "4096KB", "384KB");
  95             checkReserved(output, addr, reserveSize, "4096KB");
  96 
  97             checkCommitted(output, addrA, 3 * commitSize, "384KB");
  98 
  99             wb.NMTCommitMemory(addrC, commitSize);
 100 
 101             output = new OutputAnalyzer(pb.start());
 102             checkReservedCommittedSummary(output, "4096KB", "384KB");
 103             checkReserved(output, addr, reserveSize, "4096KB");
 104 
 105             checkCommitted(output, addrA, 3 * commitSize, "384KB");
 106 
 107             // uncommit
 108             wb.NMTUncommitMemory(addrA, 3 * commitSize);
 109 
 110             output = new OutputAnalyzer(pb.start());
 111             checkReservedCommittedSummary(output, "4096KB", "0KB");
 112         }
 113 
 114         // Test discontigous areas
 115         {
 116             // commit ACE
 117             wb.NMTCommitMemory(addrA, commitSize);
 118             wb.NMTCommitMemory(addrC, commitSize);
 119             wb.NMTCommitMemory(addrE, commitSize);
 120 
 121             output = new OutputAnalyzer(pb.start());
 122             checkReservedCommittedSummary(output, "4096KB", "384KB");
 123             checkReserved(output, addr, reserveSize, "4096KB");
 124 
 125             checkCommitted(output, addrA, commitSize, "128KB");
 126             checkCommitted(output, addrC, commitSize, "128KB");
 127             checkCommitted(output, addrE, commitSize, "128KB");
 128 
 129             // uncommit ACE
 130             wb.NMTUncommitMemory(addrA, commitSize);
 131             wb.NMTUncommitMemory(addrC, commitSize);
 132             wb.NMTUncommitMemory(addrE, commitSize);
 133 
 134             output = new OutputAnalyzer(pb.start());
 135             checkReservedCommittedSummary(output, "4096KB", "0KB");
 136         }
 137 
 138         // Test contiguous areas
 139         {
 140             // commit AB
 141             wb.NMTCommitMemory(addrA, commitSize);
 142             wb.NMTCommitMemory(addrB, commitSize);
 143 
 144             output = new OutputAnalyzer(pb.start());
 145             checkReservedCommittedSummary(output, "4096KB", "256KB");
 146             checkReserved(output, addr, reserveSize, "4096KB");
 147 
 148             checkCommitted(output, addrA, 2 * commitSize, "256KB");
 149 
 150             // uncommit AB
 151             wb.NMTUncommitMemory(addrA, commitSize);
 152             wb.NMTUncommitMemory(addrB, commitSize);
 153 
 154             output = new OutputAnalyzer(pb.start());
 155             checkReservedCommittedSummary(output, "4096KB", "0KB");
 156         }
 157 
 158         {
 159             // commit BA
 160             wb.NMTCommitMemory(addrB, commitSize);
 161             wb.NMTCommitMemory(addrA, commitSize);
 162 
 163             output = new OutputAnalyzer(pb.start());
 164             checkReservedCommittedSummary(output, "4096KB", "256KB");
 165             checkReserved(output, addr, reserveSize, "4096KB");
 166 
 167             checkCommitted(output, addrA, 2 * commitSize, "256KB");
 168 
 169             // uncommit AB
 170             wb.NMTUncommitMemory(addrB, commitSize);
 171             wb.NMTUncommitMemory(addrA, commitSize);
 172 
 173             output = new OutputAnalyzer(pb.start());
 174             checkReservedCommittedSummary(output, "4096KB", "0KB");
 175         }
 176 
 177         {
 178             // commit ABC
 179             wb.NMTCommitMemory(addrA, commitSize);
 180             wb.NMTCommitMemory(addrB, commitSize);
 181             wb.NMTCommitMemory(addrC, commitSize);
 182 
 183             output = new OutputAnalyzer(pb.start());
 184             checkReservedCommittedSummary(output, "4096KB", "384KB");
 185             checkReserved(output, addr, reserveSize, "4096KB");
 186 
 187             checkCommitted(output, addrA, 3 * commitSize, "384KB");
 188 
 189             // uncommit
 190             wb.NMTUncommitMemory(addrA, commitSize);
 191             wb.NMTUncommitMemory(addrB, commitSize);
 192             wb.NMTUncommitMemory(addrC, commitSize);
 193 
 194             output = new OutputAnalyzer(pb.start());
 195             checkReservedCommittedSummary(output, "4096KB", "0KB");
 196         }
 197 
 198         {
 199             // commit ACB
 200             wb.NMTCommitMemory(addrA, commitSize);
 201             wb.NMTCommitMemory(addrC, commitSize);
 202             wb.NMTCommitMemory(addrB, commitSize);
 203 
 204             output = new OutputAnalyzer(pb.start());
 205             checkReservedCommittedSummary(output, "4096KB", "384KB");
 206             checkReserved(output, addr, reserveSize, "4096KB");
 207 
 208             checkCommitted(output, addrA, 3 * commitSize, "384KB");
 209 
 210             // uncommit
 211             wb.NMTUncommitMemory(addrA, commitSize);
 212             wb.NMTUncommitMemory(addrC, commitSize);
 213             wb.NMTUncommitMemory(addrB, commitSize);
 214 
 215             output = new OutputAnalyzer(pb.start());
 216             checkReservedCommittedSummary(output, "4096KB", "0KB");
 217         }
 218 
 219         {
 220             // commit BAC
 221             wb.NMTCommitMemory(addrB, commitSize);
 222             wb.NMTCommitMemory(addrA, commitSize);
 223             wb.NMTCommitMemory(addrC, commitSize);
 224 
 225             output = new OutputAnalyzer(pb.start());
 226             checkReservedCommittedSummary(output, "4096KB", "384KB");
 227             checkReserved(output, addr, reserveSize, "4096KB");
 228 
 229             checkCommitted(output, addrA, 3 * commitSize, "384KB");
 230 
 231             // uncommit
 232             wb.NMTUncommitMemory(addrB, commitSize);
 233             wb.NMTUncommitMemory(addrA, commitSize);
 234             wb.NMTUncommitMemory(addrC, commitSize);
 235 
 236             output = new OutputAnalyzer(pb.start());
 237             checkReservedCommittedSummary(output, "4096KB", "0KB");
 238         }
 239 
 240         {
 241             // commit BCA
 242             wb.NMTCommitMemory(addrB, commitSize);
 243             wb.NMTCommitMemory(addrC, commitSize);
 244             wb.NMTCommitMemory(addrA, commitSize);
 245 
 246             output = new OutputAnalyzer(pb.start());
 247             checkReservedCommittedSummary(output, "4096KB", "384KB");
 248             checkReserved(output, addr, reserveSize, "4096KB");
 249 
 250             checkCommitted(output, addrA, 3 * commitSize, "384KB");
 251 
 252             // uncommit
 253             wb.NMTUncommitMemory(addrB, commitSize);
 254             wb.NMTUncommitMemory(addrC, commitSize);
 255             wb.NMTUncommitMemory(addrA, commitSize);
 256 
 257             output = new OutputAnalyzer(pb.start());
 258             checkReservedCommittedSummary(output, "4096KB", "0KB");
 259         }
 260 
 261         {
 262             // commit CAB
 263             wb.NMTCommitMemory(addrC, commitSize);
 264             wb.NMTCommitMemory(addrA, commitSize);
 265             wb.NMTCommitMemory(addrB, commitSize);
 266 
 267             output = new OutputAnalyzer(pb.start());
 268             checkReservedCommittedSummary(output, "4096KB", "384KB");
 269             checkReserved(output, addr, reserveSize, "4096KB");
 270 
 271             checkCommitted(output, addrA, 3 * commitSize, "384KB");
 272 
 273             // uncommit
 274             wb.NMTUncommitMemory(addrC, commitSize);
 275             wb.NMTUncommitMemory(addrA, commitSize);
 276             wb.NMTUncommitMemory(addrB, commitSize);
 277 
 278             output = new OutputAnalyzer(pb.start());
 279             checkReservedCommittedSummary(output, "4096KB", "0KB");
 280         }
 281 
 282         {
 283             // commit CBA
 284             wb.NMTCommitMemory(addrC, commitSize);
 285             wb.NMTCommitMemory(addrB, commitSize);
 286             wb.NMTCommitMemory(addrA, commitSize);
 287 
 288             output = new OutputAnalyzer(pb.start());
 289             checkReservedCommittedSummary(output, "4096KB", "384KB");
 290             checkReserved(output, addr, reserveSize, "4096KB");
 291 
 292             checkCommitted(output, addrA, 3 * commitSize, "384KB");
 293 
 294             // uncommit
 295             wb.NMTUncommitMemory(addrC, commitSize);
 296             wb.NMTUncommitMemory(addrB, commitSize);
 297             wb.NMTUncommitMemory(addrA, commitSize);
 298 
 299             output = new OutputAnalyzer(pb.start());
 300             checkReservedCommittedSummary(output, "4096KB", "0KB");
 301         }
 302 
 303         // release
 304         wb.NMTReleaseMemory(addr, reserveSize);
 305         output = new OutputAnalyzer(pb.start());
 306         output.shouldNotContain("Test (reserved=");
 307         output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
 308                 + Long.toHexString(addr + reserveSize) + "\\] reserved 4096KB for Test");
 309     }
 310 
 311     public static void checkReservedCommittedSummary(OutputAnalyzer output, String reservedString, String committedString) {
 312         output.shouldContain("Test (reserved=" + reservedString + ", committed=" + committedString + ")");
 313     }
 314 
 315     public static void checkReserved(OutputAnalyzer output, long addr, long size, String sizeString) {
 316         output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
 317                            + Long.toHexString(addr + size)
 318                            + "\\] reserved 4096KB for Test");
 319     }
 320 
 321     public static void checkCommitted(OutputAnalyzer output, long addr, long size, String sizeString) {
 322         output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
 323                            + Long.toHexString(addr + size)
 324                            + "\\] committed " + sizeString + " from.*");
 325     }
 326 }