1 /*
2 * Copyright (c) 2015, 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 /**
26 * This is an interface used to provoke GC and perform other GC-related
27 * procedures
28 *
29 */
30 public interface GcProvoker {
31
32 /**
33 * The default implementation
34 *
35 * @return the default GC provoker
36 */
37 public static GcProvoker createGcProvoker() {
38 return new GcProvokerImpl();
39 }
40
41 /**
42 * This method provokes a GC
43 */
44 public void provokeGc();
45
46 /**
47 * Eats heap and metaspace Upon exit targetMemoryUsagePercent percents of
48 * heap and metaspace is have been eaten
49 *
50 * @param targetMemoryUsagePercent how many percent of heap and metaspace to
51 * eat
52 */
53 public void eatMetaspaceAndHeap(float targetMemoryUsagePercent);
54
55 }
|
1 /*
2 * Copyright (c) 2015, 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 package utils;
24
25 import java.lang.management.ManagementFactory;
26 import java.lang.management.MemoryPoolMXBean;
27 import java.lang.management.MemoryUsage;
28 import java.util.ArrayList;
29 import java.util.List;
30
31 /**
32 * This is an class used to provoke GC and perform other GC-related
33 * procedures
34 *
35 */
36 public class GcProvoker{
37
38 // Uses fixed small objects to avoid Humongous objects allocation in G1
39 public static final int MEMORY_CHUNK = 2048;
40 public static final float ALLOCATION_TOLERANCE = 0.05f;
41
42 public static List<Object> allocatedMetaspace;
43 public static List<Object> allocatedMemory;
44
45 private final Runtime runtime;
46
47 private List<Object> allocateHeap(float targetUsage) {
48 long maxMemory = runtime.maxMemory();
49 List<Object> list = new ArrayList<>();
50 long used = 0;
51 long target = (long) (maxMemory * targetUsage);
52 while (used < target) {
53 try {
54 list.add(new byte[MEMORY_CHUNK]);
55 used += MEMORY_CHUNK;
56 } catch (OutOfMemoryError e) {
57 list = null;
58 throw new RuntimeException("Unexpected OOME '" + e.getMessage() + "' while eating " + targetUsage + " of heap memory.");
59 }
60 }
61 return list;
62 }
63
64 private List<Object> allocateAvailableHeap(float targetUsage) {
65 // Calculates size of free memory after allocation with small tolerance.
66 long minFreeMemory = (long) ((1.0 - (targetUsage + ALLOCATION_TOLERANCE)) * runtime.maxMemory());
67 List<Object> list = new ArrayList<>();
68 do {
69 try {
70 list.add(new byte[MEMORY_CHUNK]);
71 } catch (OutOfMemoryError e) {
72 list = null;
73 throw new RuntimeException("Unexpected OOME '" + e.getMessage() + "' while eating " + targetUsage + " of heap memory.");
74 }
75 } while (runtime.freeMemory() > minFreeMemory);
76 return list;
77 }
78
79 /**
80 * This method provokes a GC
81 */
82 public void provokeGc() {
83 for (int i = 0; i < 3; i++) {
84 long edenSize = Pools.getEdenCommittedSize();
85 long heapSize = Pools.getHeapCommittedSize();
86 float targetPercent = ((float) edenSize) / (heapSize);
87 if ((targetPercent < 0) || (targetPercent > 1.0)) {
88 throw new RuntimeException("Error in the percent calculation" + " (eden size: " + edenSize + ", heap size: " + heapSize + ", calculated eden percent: " + targetPercent + ")");
89 }
90 allocateHeap(targetPercent);
91 allocateHeap(targetPercent);
92 System.gc();
93 }
94 }
95
96 /**
97 * Allocates heap and metaspace upon exit not less than targetMemoryUsagePercent percents
98 * of heap and metaspace have been consumed.
99 *
100 * @param targetMemoryUsagePercent how many percent of heap and metaspace to
101 * allocate
102 */
103
104 public void allocateMetaspaceAndHeap(float targetMemoryUsagePercent) {
105 // Metaspace should be filled before Java Heap to prevent unexpected OOME
106 // in the Java Heap while filling Metaspace
107 allocatedMetaspace = eatMetaspace(targetMemoryUsagePercent);
108 allocatedMemory = allocateHeap(targetMemoryUsagePercent);
109 }
110
111 /**
112 * Allocates heap and metaspace upon exit targetMemoryUsagePercent percents
113 * of heap and metaspace have been consumed.
114 *
115 * @param targetMemoryUsagePercent how many percent of heap and metaspace to
116 * allocate
117 */
118 public void allocateAvailableMetaspaceAndHeap(float targetMemoryUsagePercent) {
119 // Metaspace should be filled before Java Heap to prevent unexpected OOME
120 // in the Java Heap while filling Metaspace
121 allocatedMetaspace = eatMetaspace(targetMemoryUsagePercent);
122 allocatedMemory = allocateAvailableHeap(targetMemoryUsagePercent);
123 }
124
125 private List<Object> eatMetaspace(float targetUsage) {
126 List<Object> list = new ArrayList<>();
127 final String metaspacePoolName = "Metaspace";
128 MemoryPoolMXBean metaspacePool = null;
129 for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
130 if (pool.getName().contains(metaspacePoolName)) {
131 metaspacePool = pool;
132 break;
133 }
134 }
135 if (metaspacePool == null) {
136 throw new RuntimeException("MXBean for Metaspace pool wasn't found");
137 }
138 float currentUsage;
139 GeneratedClassProducer gp = new GeneratedClassProducer();
140 do {
141 try {
142 list.add(gp.create(0));
143 } catch (OutOfMemoryError oome) {
144 list = null;
145 throw new RuntimeException("Unexpected OOME '" + oome.getMessage() + "' while eating " + targetUsage + " of Metaspace.");
146 }
147 MemoryUsage memoryUsage = metaspacePool.getUsage();
148 currentUsage = (((float) memoryUsage.getUsed()) / memoryUsage.getMax());
149 } while (currentUsage < targetUsage);
150 return list;
151 }
152
153 public GcProvoker() {
154 runtime = Runtime.getRuntime();
155 }
156
157 }
|