1 /* |
1 /* |
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
20 * or visit www.oracle.com if you need additional information or have any |
20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 package utils; |
23 package utils; |
24 |
24 |
25 import java.lang.management.ManagementFactory; |
|
26 import java.lang.management.MemoryPoolMXBean; |
|
27 import java.lang.management.MemoryUsage; |
|
28 import java.util.ArrayList; |
25 import java.util.ArrayList; |
29 import java.util.List; |
26 import java.util.List; |
30 |
27 |
31 /** |
28 /** |
32 * This is an class used to provoke GC and perform other GC-related |
29 * This is an class used to provoke GC and perform other GC-related |
34 * |
31 * |
35 */ |
32 */ |
36 public class GcProvoker{ |
33 public class GcProvoker{ |
37 |
34 |
38 // Uses fixed small objects to avoid Humongous objects allocation in G1 |
35 // Uses fixed small objects to avoid Humongous objects allocation in G1 |
39 public static final int MEMORY_CHUNK = 2048; |
36 private 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 |
37 |
45 private final Runtime runtime; |
38 private final Runtime runtime; |
46 |
39 |
47 private List<Object> allocateHeap(float targetUsage) { |
40 private List<Object> allocateHeap(float targetUsage) { |
48 long maxMemory = runtime.maxMemory(); |
41 long maxMemory = runtime.maxMemory(); |
59 } |
52 } |
60 } |
53 } |
61 return list; |
54 return list; |
62 } |
55 } |
63 |
56 |
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 /** |
57 /** |
80 * This method provokes a GC |
58 * This method provokes a GC |
81 */ |
59 */ |
82 public void provokeGc() { |
60 public void provokeGc() { |
83 for (int i = 0; i < 3; i++) { |
61 for (int i = 0; i < 3; i++) { |
91 allocateHeap(targetPercent); |
69 allocateHeap(targetPercent); |
92 System.gc(); |
70 System.gc(); |
93 } |
71 } |
94 } |
72 } |
95 |
73 |
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() { |
74 public GcProvoker() { |
154 runtime = Runtime.getRuntime(); |
75 runtime = Runtime.getRuntime(); |
155 } |
76 } |
156 |
|
157 } |
77 } |