1/*
2 * Copyright (c) 2014, 2016, 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 * @key gc
27 * @bug 8049831
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 *                              sun.hotspot.WhiteBox$WhiteBoxPermission
34 * @run driver TestG1ClassUnloadingHWM
35 * @summary Test that -XX:-ClassUnloadingWithConcurrentMark will trigger a Full GC when more than MetaspaceSize metadata is allocated.
36 */
37
38import jdk.test.lib.process.OutputAnalyzer;
39import jdk.test.lib.process.ProcessTools;
40import java.util.ArrayList;
41import java.util.Arrays;
42import sun.hotspot.WhiteBox;
43
44public class TestG1ClassUnloadingHWM {
45  private static long MetaspaceSize = 32 * 1024 * 1024;
46  private static long YoungGenSize  = 32 * 1024 * 1024;
47
48  private static OutputAnalyzer run(boolean enableUnloading) throws Exception {
49    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
50      "-Xbootclasspath/a:.",
51      "-XX:+UnlockDiagnosticVMOptions",
52      "-XX:+WhiteBoxAPI",
53      "-XX:MetaspaceSize=" + MetaspaceSize,
54      "-Xmn" + YoungGenSize,
55      "-XX:+UseG1GC",
56      "-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark",
57      "-Xlog:gc",
58      TestG1ClassUnloadingHWM.AllocateBeyondMetaspaceSize.class.getName(),
59      "" + MetaspaceSize,
60      "" + YoungGenSize);
61    return new OutputAnalyzer(pb.start());
62  }
63
64  public static OutputAnalyzer runWithG1ClassUnloading() throws Exception {
65    return run(true);
66  }
67
68  public static OutputAnalyzer runWithoutG1ClassUnloading() throws Exception {
69    return run(false);
70  }
71
72  public static void testWithoutG1ClassUnloading() throws Exception {
73    // -XX:-ClassUnloadingWithConcurrentMark is used, so we expect a full GC instead of a concurrent cycle.
74    OutputAnalyzer out = runWithoutG1ClassUnloading();
75
76    out.shouldMatch(".*Pause Full.*");
77    out.shouldNotMatch(".*Pause Initial Mark.*");
78  }
79
80  public static void testWithG1ClassUnloading() throws Exception {
81    // -XX:+ClassUnloadingWithConcurrentMark is used, so we expect a concurrent cycle instead of a full GC.
82    OutputAnalyzer out = runWithG1ClassUnloading();
83
84    out.shouldMatch(".*Pause Initial Mark.*");
85    out.shouldNotMatch(".*Pause Full.*");
86  }
87
88  public static void main(String args[]) throws Exception {
89    testWithG1ClassUnloading();
90    testWithoutG1ClassUnloading();
91  }
92
93  public static class AllocateBeyondMetaspaceSize {
94    public static Object dummy;
95
96    public static void main(String [] args) throws Exception {
97      if (args.length != 2) {
98        throw new IllegalArgumentException("Usage: <MetaspaceSize> <YoungGenSize>");
99      }
100
101      WhiteBox wb = WhiteBox.getWhiteBox();
102
103      // Allocate past the MetaspaceSize limit
104      long metaspaceSize = Long.parseLong(args[0]);
105      long allocationBeyondMetaspaceSize  = metaspaceSize * 2;
106      long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize);
107
108      long youngGenSize = Long.parseLong(args[1]);
109      triggerYoungGCs(youngGenSize);
110
111      wb.freeMetaspace(null, metaspace, metaspace);
112    }
113
114    public static void triggerYoungGCs(long youngGenSize) {
115      long approxAllocSize = 32 * 1024;
116      long numAllocations  = 2 * youngGenSize / approxAllocSize;
117
118      for (long i = 0; i < numAllocations; i++) {
119        dummy = new byte[(int)approxAllocSize];
120      }
121    }
122  }
123}
124
125