1 /*
  2  * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2019, Twitter, Inc.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 package gc.metaspace;
 27 
 28 import jdk.test.lib.Platform;
 29 import jdk.test.lib.process.ProcessTools;
 30 import jdk.test.lib.process.OutputAnalyzer;
 31 import java.util.ArrayList;
 32 import java.util.List;
 33 
 34 /* @test TestSizeTransitionsSerial
 35  * @requires vm.gc.Serial
 36  * @summary Tests that the metaspace size transition logging is done correctly.
 37  * @library /test/lib
 38  * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseSerialGC
 39  * @run driver gc.metaspace.TestSizeTransitions true  -XX:+UseSerialGC
 40  */
 41 
 42 /* @test TestSizeTransitionsParallel
 43  * @requires vm.gc.Parallel
 44  * @summary Tests that the metaspace size transition logging is done correctly.
 45  * @library /test/lib
 46  * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseParallelGC
 47  * @run driver gc.metaspace.TestSizeTransitions true  -XX:+UseParallelGC
 48  */
 49 
 50 /* @test TestSizeTransitionsG1
 51  * @requires vm.gc.G1
 52  * @summary Tests that the metaspace size transition logging is done correctly.
 53  * @library /test/lib
 54  * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseG1GC
 55  * @run driver gc.metaspace.TestSizeTransitions true  -XX:+UseG1GC
 56  */
 57 
 58 public class TestSizeTransitions {
 59   public static class Run {
 60     public static void main(String... args) throws Exception {
 61       System.out.println("Run started.");
 62 
 63       // easiest way to generate a metaspace transition is to ask for a full GC
 64       System.gc();
 65 
 66       System.out.println("Run finished.");
 67     }
 68   }
 69 
 70   // matches the log tags
 71   //   e.g., [0.043s][info][gc]
 72   private static final String LOG_TAGS_REGEX = "(\\[.*\\])+ ";
 73 
 74   // matches a size transition
 75   //   e.g., 177K(4864K)->177K(4864K)
 76   private static final String SIZE_TRANSITION_REGEX = "\\d+K\\(\\d+K\\)->\\d+K\\(\\d+K\\)";
 77 
 78   // matches -coops metaspace size transitions
 79   private static final String NO_COMPRESSED_KLASS_POINTERS_REGEX =
 80     String.format("^%s.* Metaspace: %s$",
 81                   LOG_TAGS_REGEX,
 82                   SIZE_TRANSITION_REGEX);
 83 
 84   // matches +coops metaspace size transitions
 85   private static final String COMPRESSED_KLASS_POINTERS_REGEX =
 86     String.format("^%s.* Metaspace: %s NonClass: %s Class: %s$",
 87                   LOG_TAGS_REGEX,
 88                   SIZE_TRANSITION_REGEX,
 89                   SIZE_TRANSITION_REGEX,
 90                   SIZE_TRANSITION_REGEX);
 91 
 92   public static void main(String... args) throws Exception {
 93     // args: <use-coops> <gc-arg>
 94     if (args.length != 2) {
 95       throw new RuntimeException("wrong number of args: " + args.length);
 96     }
 97 
 98     final boolean hasCompressedKlassPointers = Platform.is64bit();
 99     final boolean useCompressedKlassPointers = Boolean.parseBoolean(args[0]);
100     final String gcArg = args[1];
101 
102     if (!hasCompressedKlassPointers && useCompressedKlassPointers) {
103        // No need to run this configuration.
104        System.out.println("Skipping test.");
105        return;
106     }
107 
108     List<String> jvmArgs = new ArrayList<>();
109     if (hasCompressedKlassPointers) {
110       jvmArgs.add(useCompressedKlassPointers ? "-XX:+UseCompressedClassPointers" : "-XX:-UseCompressedClassPointers");
111     }
112     jvmArgs.add(gcArg);
113     jvmArgs.add("-Xmx256m");
114     jvmArgs.add("-Xlog:gc,gc+metaspace=info");
115     jvmArgs.add(TestSizeTransitions.Run.class.getName());
116 
117     System.out.println("JVM args:");
118     for (String a : jvmArgs) {
119       System.out.println("  " + a);
120     }
121 
122     final ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(jvmArgs);
123     final OutputAnalyzer output = new OutputAnalyzer(pb.start());
124     System.out.println(output.getStdout());
125     output.shouldHaveExitValue(0);
126 
127     if (useCompressedKlassPointers) {
128       output.stdoutShouldMatch(COMPRESSED_KLASS_POINTERS_REGEX);
129       output.stdoutShouldNotMatch(NO_COMPRESSED_KLASS_POINTERS_REGEX);
130     } else {
131       output.stdoutShouldMatch(NO_COMPRESSED_KLASS_POINTERS_REGEX);
132       output.stdoutShouldNotMatch(COMPRESSED_KLASS_POINTERS_REGEX);
133     }
134   }
135 }