1 /*
  2  * Copyright (c) 2003, 2023, 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  * @bug     4530538
 27  * @summary Basic unit test of MemoryMXBean.getMemoryPools() and
 28  *          MemoryMXBean.getMemoryManager().
 29  * @requires vm.gc != "Z" & vm.gc != "Shenandoah" & !vm.gc.G1
 30  * @author  Mandy Chung
 31  *
 32  * @modules jdk.management
 33  * @run main MemoryTest 2 3
 34  */
 35 
 36 /*
 37  * @test id=ZSinglegen
 38  * @bug     4530538
 39  * @summary Basic unit test of MemoryMXBean.getMemoryPools() and
 40  *          MemoryMXBean.getMemoryManager().
 41  * @requires vm.gc.ZSinglegen
 42  * @author  Mandy Chung
 43  *
 44  * @modules jdk.management
 45  * @run main/othervm -XX:+UseZGC -XX:-ZGenerational MemoryTest 2 1
 46  */
 47 
 48 /*
 49  * @test id=ZGenerational
 50  * @bug     4530538
 51  * @summary Basic unit test of MemoryMXBean.getMemoryPools() and
 52  *          MemoryMXBean.getMemoryManager().
 53  * @requires vm.gc.ZGenerational
 54  * @author  Mandy Chung
 55  *
 56  * @modules jdk.management
 57  * @run main/othervm -XX:+UseZGC -XX:+ZGenerational MemoryTest 4 2
 58  */
 59 
 60 /*
 61  * @test id=Shenandoah
 62  * @bug     4530538
 63  * @summary Shenandoah has a gc mgr bean for cycles and another
 64  *          for pauses, they both have one pool.
 65  * @requires vm.gc == "Shenandoah" & vm.opt.ShenandoahGCMode != "generational"
 66  * @author  Mandy Chung
 67  *
 68  * @modules jdk.management
 69  * @run main MemoryTest 2 1
 70  */
 71 
 72 /*
 73  * @test id=Genshen
 74  * @bug     4530538
 75  * @summary Shenandoah's generational mode has a gc mgr bean for cycles
 76  *          and another for pauses. They both reference the young and old pools.
 77  * @requires vm.gc == "Shenandoah" & vm.opt.ShenandoahGCMode == "generational"
 78  * @author  Mandy Chung
 79  *
 80  * @modules jdk.management
 81  * @run main MemoryTest 2 2
 82  */
 83 
 84 /*
 85  * @test
 86  * @bug     4530538
 87  * @summary Basic unit test of MemoryMXBean.getMemoryPools() and
 88  *          MemoryMXBean.getMemoryManager().
 89  * @requires vm.gc.G1
 90  * @author  Mandy Chung
 91  *
 92  * @modules jdk.management
 93  * @run main/othervm -XX:+UseG1GC MemoryTest 3 3
 94  */
 95 
 96 /*
 97  * NOTE: This expected result is hardcoded in this test and this test
 98  *       will be affected if the heap memory layout is changed in
 99  *       the future implementation.
100  */
101 
102 import java.lang.management.*;
103 import java.util.*;
104 
105 public class MemoryTest {
106     private static boolean testFailed = false;
107     private static MemoryMXBean mm = ManagementFactory.getMemoryMXBean();
108     private static final int HEAP = 0;
109     private static final int NONHEAP = 1;
110     private static final int NUM_TYPES = 2;
111 
112     // WARNING: if the number of pools changes in the future,
113     // this test needs to be modified to handle different version of VMs.
114 
115     // Hotspot VM 1.5 expected to have
116     //   heap memory pools     = 3 (Eden, Survivor spaces, Old gen)
117     //   non-heap memory pools = 2 (Perm gen, Code cache)
118     //                           or 4 if Class Sharing is enabled.
119     // Number of memory managers = 3
120     // They are: Copy/Scavenger + MSC + CodeCache manager
121     // (or equivalent for other collectors)
122     // Number of GC memory managers = 2
123 
124     // Hotspot VM 1.8+ after perm gen removal is expected to have between two
125     // or five non-heap memory pools:
126     // - Code cache (between one and three depending on the -XX:SegmentedCodeCache option)
127     // - Metaspace
128     // - Compressed Class Space (if compressed class pointers are used)
129 
130     private static int[] expectedMinNumPools = new int[2];
131     private static int[] expectedMaxNumPools = new int[2];
132     private static int expectedNumGCMgrs;
133     private static int expectedNumMgrs;
134     private static String[] types = { "heap", "non-heap" };
135 
136     public static void main(String args[]) throws Exception {
137         expectedNumGCMgrs = Integer.valueOf(args[0]);
138         expectedNumMgrs = expectedNumGCMgrs + 2;
139 
140         int expectedNumPools = Integer.valueOf(args[1]);
141         expectedMinNumPools[HEAP] = expectedNumPools;
142         expectedMaxNumPools[HEAP] = expectedNumPools;
143 
144         expectedMinNumPools[NONHEAP] = 2;
145         expectedMaxNumPools[NONHEAP] = 5;
146 
147         checkMemoryPools();
148         checkMemoryManagers();
149         if (testFailed)
150             throw new RuntimeException("TEST FAILED.");
151 
152         System.out.println("Test passed.");
153 
154     }
155 
156     private static void checkMemoryPools() throws Exception {
157         List pools = ManagementFactory.getMemoryPoolMXBeans();
158         boolean hasPerm = false;
159 
160         int[] numPools = new int[NUM_TYPES];
161         for (ListIterator iter = pools.listIterator(); iter.hasNext();) {
162             MemoryPoolMXBean pool = (MemoryPoolMXBean) iter.next();
163             if (pool.getType() == MemoryType.HEAP) {
164                 numPools[HEAP]++;
165             }
166             if (pool.getType() == MemoryType.NON_HEAP) {
167                 numPools[NONHEAP]++;
168             }
169             if (pool.getName().toLowerCase().contains("perm")) {
170                 hasPerm = true;
171             }
172         }
173 
174         if (hasPerm) {
175             // If the VM has perm gen there will be between 2 and 4 non heap
176             // pools (4 if class data sharing is used)
177             expectedMinNumPools[NONHEAP] = 2;
178             expectedMaxNumPools[NONHEAP] = 4;
179         }
180 
181         // Check the number of Memory pools
182         for (int i = 0; i < NUM_TYPES; i++) {
183             if (numPools[i] < expectedMinNumPools[i] ||
184                     numPools[i] > expectedMaxNumPools[i]) {
185                 throw new RuntimeException("TEST FAILED: " +
186                     "Number of " + types[i] + " pools = " + numPools[i] +
187                     " but expected <= " + expectedMaxNumPools[i] +
188                     " and >= " + expectedMinNumPools[i]);
189             }
190         }
191     }
192 
193     private static void checkMemoryManagers() throws Exception {
194         List mgrs = ManagementFactory.getMemoryManagerMXBeans();
195 
196         int numGCMgr = 0;
197 
198         // Check the number of Memory Managers
199         for (ListIterator iter = mgrs.listIterator(); iter.hasNext();) {
200             MemoryManagerMXBean mgr = (MemoryManagerMXBean) iter.next();
201             String[] poolNames = mgr.getMemoryPoolNames();
202             if (poolNames == null || poolNames.length == 0) {
203                 throw new RuntimeException("TEST FAILED: " +
204                     "Expected to have one or more pools for " +
205                     mgr.getName() + "manager.");
206             }
207 
208             if (mgr instanceof GarbageCollectorMXBean) {
209                 numGCMgr++;
210             } else {
211                 for (int i = 0; i < poolNames.length; i++) {
212                     checkPoolType(poolNames[i], MemoryType.NON_HEAP);
213                 }
214             }
215         }
216 
217         if (mgrs.size() != expectedNumMgrs) {
218             throw new RuntimeException("TEST FAILED: " +
219                 "Number of memory managers = " + mgrs.size() +
220                 " but expected = " + expectedNumMgrs);
221         }
222         if (numGCMgr != expectedNumGCMgrs) {
223             throw new RuntimeException("TEST FAILED: " +
224                 "Number of GC managers = " + numGCMgr + " but expected = " +
225                 expectedNumGCMgrs);
226         }
227     }
228     private static List pools = ManagementFactory.getMemoryPoolMXBeans();
229     private static void checkPoolType(String name, MemoryType type)
230         throws Exception {
231         for (ListIterator iter = pools.listIterator(); iter.hasNext(); ) {
232             MemoryPoolMXBean pool = (MemoryPoolMXBean) iter.next();
233             if (pool.getName().equals(name)) {
234                 if (pool.getType() != type) {
235                     throw new RuntimeException("TEST FAILED: " +
236                         "Pool " + pool.getName() + " is of type " +
237                         pool.getType() + " but expected to be " + type);
238                 } else {
239                     return;
240                 }
241             }
242         }
243         throw new RuntimeException("TEST FAILED: " +
244             "Pool " + name + " is of type " + type +
245             " not found");
246     }
247 }