hotspot/test/serviceability/tmtools/jstat/utils/GarbageProducer.java
changeset 43933 85ee551f3948
equal deleted inserted replaced
43433:acc1d9072823 43933:85ee551f3948
       
     1 /*
       
     2  * Copyright (c) 2017, 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 package utils;
       
    24 
       
    25 import java.lang.management.ManagementFactory;
       
    26 import java.lang.management.MemoryMXBean;
       
    27 import java.lang.management.MemoryPoolMXBean;
       
    28 import java.lang.management.MemoryUsage;
       
    29 import java.util.ArrayList;
       
    30 import java.util.List;
       
    31 
       
    32 /**
       
    33  * This is an class used to allocate specified amount of metaspace and heap.
       
    34  */
       
    35 public class GarbageProducer {
       
    36 
       
    37     // Uses fixed small objects to avoid Humongous objects allocation with G1 GC.
       
    38     private static final int MEMORY_CHUNK = 2048;
       
    39 
       
    40     public static List<Object> allocatedMetaspace;
       
    41     public static List<Object> allocatedMemory;
       
    42 
       
    43     private final MemoryMXBean memoryMXBean;
       
    44     private final float targetMemoryUsagePercent;
       
    45     private final long targetMemoryUsage;
       
    46 
       
    47     /**
       
    48      * @param targetMemoryUsagePercent how many percent of metaspace and heap to
       
    49      * allocate
       
    50      */
       
    51     public GarbageProducer(float targetMemoryUsagePercent) {
       
    52         memoryMXBean = ManagementFactory.getMemoryMXBean();
       
    53         this.targetMemoryUsagePercent = targetMemoryUsagePercent;
       
    54         targetMemoryUsage = (long) (memoryMXBean.getHeapMemoryUsage().getMax() * targetMemoryUsagePercent);
       
    55     }
       
    56 
       
    57     /**
       
    58      * Allocates heap and metaspace upon exit targetMemoryUsagePercent percents
       
    59      * of heap and metaspace have been consumed.
       
    60      */
       
    61     public void allocateMetaspaceAndHeap() {
       
    62         // Metaspace should be filled before Java Heap to prevent unexpected OOME
       
    63         // in the Java Heap while filling Metaspace
       
    64         allocatedMetaspace = eatMetaspace(targetMemoryUsagePercent);
       
    65         allocatedMemory = allocateGarbage(targetMemoryUsage);
       
    66     }
       
    67 
       
    68     private List<Object> eatMetaspace(float targetUsage) {
       
    69         List<Object> list = new ArrayList<>();
       
    70         MemoryPoolMXBean metaspacePool = getMatchedMemoryPool(".*Metaspace.*");
       
    71         float currentUsage;
       
    72         GeneratedClassProducer gp = new GeneratedClassProducer();
       
    73         do {
       
    74             try {
       
    75                 list.add(gp.create(0));
       
    76             } catch (OutOfMemoryError oome) {
       
    77                 list = null;
       
    78                 throw new RuntimeException("Unexpected OOME '" + oome.getMessage() + "' while eating " + targetUsage + " of Metaspace.");
       
    79             }
       
    80             MemoryUsage memoryUsage = metaspacePool.getUsage();
       
    81             currentUsage = (((float) memoryUsage.getUsed()) / memoryUsage.getMax());
       
    82         } while (currentUsage < targetUsage);
       
    83         return list;
       
    84     }
       
    85 
       
    86     private MemoryPoolMXBean getMatchedMemoryPool(String patternPoolName) {
       
    87         return ManagementFactory.getMemoryPoolMXBeans().stream()
       
    88                 .filter(bean -> bean.getName().matches(patternPoolName))
       
    89                 .findFirst()
       
    90                 .orElseThrow(() -> new RuntimeException("Cannot find '" + patternPoolName + "' memory pool."));
       
    91     }
       
    92 
       
    93     private List<Object> allocateGarbage(long targetMemoryUsage) {
       
    94         List<Object> list = new ArrayList<>();
       
    95         do {
       
    96             try {
       
    97                 list.add(new byte[MEMORY_CHUNK]);
       
    98             } catch (OutOfMemoryError e) {
       
    99                 list = null;
       
   100                 throw new RuntimeException("Unexpected OOME '" + e.getMessage() + "'");
       
   101             }
       
   102         } while (memoryMXBean.getHeapMemoryUsage().getUsed() < targetMemoryUsage);
       
   103         return list;
       
   104     }
       
   105 
       
   106     /**
       
   107      * Returns allocation rate for old gen based on appropriate MemoryPoolMXBean
       
   108      * memory usage.
       
   109      *
       
   110      * @return allocation rate
       
   111      */
       
   112     public float getOldGenAllocationRatio() {
       
   113         MemoryPoolMXBean oldGenBean = getMatchedMemoryPool(".*Old.*|.*Tenured.*");
       
   114         MemoryUsage usage = oldGenBean.getUsage();
       
   115         System.out.format("Memory usage for %1s.\n", oldGenBean.getName());
       
   116         System.out.format("Used: %1d\n", usage.getUsed());
       
   117         System.out.format("Commited: %1d\n", usage.getCommitted());
       
   118         System.out.format("Max: %1d\n", usage.getMax());
       
   119         return ((float) usage.getUsed()) / usage.getCommitted();
       
   120     }
       
   121 }