Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/metaspace/gc/MetaspaceBaseGC.java
41155 views
1
/*
2
* Copyright (c) 2013, 2018, 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
package metaspace.gc;
25
26
import java.io.IOException;
27
import java.lang.management.ManagementFactory;
28
import java.lang.management.MemoryPoolMXBean;
29
import java.lang.management.MemoryUsage;
30
import java.lang.reflect.Field;
31
import java.lang.reflect.InvocationHandler;
32
import java.lang.reflect.Method;
33
import java.lang.reflect.Proxy;
34
import java.net.URL;
35
import java.net.URLClassLoader;
36
import java.nio.file.Files;
37
import java.nio.file.Paths;
38
import java.util.HashMap;
39
import java.util.HashSet;
40
import java.util.List;
41
import java.util.Map;
42
import java.util.Set;
43
import jdk.internal.misc.Unsafe;
44
45
/**
46
* Test that checks how GC works with Metaspace and "Compared Class Space".
47
*
48
* It comprises 3 test cases:
49
* <ul>
50
* <li>testcase1 - checks that used/committed memory doesn't grow
51
* when gc is invoked</li>
52
* <li>testcase2 - checks that gc is invoked when the class metadata u
53
* sage reaches MetaspaceSize</li>
54
* <li>testcase3 - checks used/committed grow, inspite of gc is invoked</li>
55
* </ul>
56
*
57
* It's supposed that this class will be executed with various setting of VM
58
* flags. Via execute args it's possible to say which test cases to run and
59
* what space to test: Metaspace or Compared Class Space.
60
*/
61
public abstract class MetaspaceBaseGC {
62
63
// storage of loaded classes
64
private final Map<String, MetaspaceBaseGC.Foo> loadedClasses = new HashMap<>();
65
private static int counter = 0;
66
67
// pool to test
68
protected MemoryPoolMXBean pool = null;
69
70
// memory page size
71
protected static final long PAGE_SIZE = detectPageSize();
72
73
// true when PAGE_SIZE is large and
74
protected boolean useLargepages = false;
75
76
// where the log will be saved
77
protected String gclogFileName = null;
78
79
protected final Set<String> vmArgs = new HashSet<>();
80
81
protected abstract void parseArgs(String args[]);
82
protected abstract String getPoolName();
83
protected abstract void doCheck();
84
85
public final void run(String args[]) {
86
configure(args);
87
if (pool == null) {
88
System.out.println("%%% Cannot pull the pool, most likely 32-bits only");
89
return;
90
}
91
System.out.println("%%% Working with " + getPoolName());
92
for (String vmA: vmArgs) {
93
if (vmA.contains("Metaspace") || vmA.contains("Compressed")) {
94
System.out.println("% " + vmA);
95
}
96
}
97
doCheck();
98
System.out.println("% Test passed.");
99
}
100
101
102
protected void configure(String args[]) {
103
vmArgs.addAll(ManagementFactory.getRuntimeMXBean().getInputArguments());
104
105
System.out.println(vmArgs);
106
107
pool = getMemoryPool(getPoolName());
108
if (pool == null) {
109
return; // nothing to check
110
}
111
for (String arg: vmArgs) {
112
if (arg.startsWith("-Xlog:gc") && arg.length() > 8) {
113
gclogFileName = arg.substring(arg.lastIndexOf(':') + 1);
114
}
115
}
116
parseArgs(args);
117
}
118
119
120
/**
121
* Imitates class loading.
122
* Each invocation of this method causes a new class loader object is created
123
* and a new class is loaded by this class loader.
124
* Method throws OOM when run out of memory.
125
*
126
* @param times how many classes to load
127
* @param keepRefs true, if references to created classes should be stored
128
*/
129
protected void loadNewClasses(int times, boolean keepRefs) {
130
for (int i = 0; i < times; i++) {
131
try {
132
String jarUrl = "file:" + counter + ".jar";
133
counter++;
134
URL[] urls = new URL[]{new URL(jarUrl)};
135
URLClassLoader cl = new URLClassLoader(urls);
136
MetaspaceBaseGC.Foo foo = (MetaspaceBaseGC.Foo) Proxy.newProxyInstance(cl,
137
new Class[]{MetaspaceBaseGC.Foo.class},
138
new MetaspaceBaseGC.FooInvocationHandler(new MetaspaceBaseGC.FooBar()));
139
if (keepRefs) {
140
loadedClasses.put(jarUrl, foo);
141
}
142
} catch (java.net.MalformedURLException badThing) {
143
// should never occur
144
System.err.println("Unexpeted error: " + badThing);
145
throw new RuntimeException(badThing);
146
}
147
}
148
149
}
150
151
/**
152
* Cleans references to loaded classes.
153
*/
154
protected void cleanLoadedClasses() {
155
loadedClasses.clear();
156
}
157
158
/**
159
* Invokes System.gc() and sleeps a little.
160
*/
161
protected void gc() {
162
System.gc();
163
try {
164
Thread.currentThread().sleep(500);
165
} catch (Exception whatever) {
166
}
167
}
168
169
/**
170
* Reads gc.log file and returns it as a list of lines.
171
* It's supposed that the test is executed with -Xlog:gc:gc.log option.
172
*
173
* @return List of strings the gc.log file is comprised.
174
* @throws IOException if problem occurred while reading.
175
*/
176
protected List<String> readGCLog() throws IOException {
177
return Files.readAllLines(Paths.get(".", gclogFileName));
178
}
179
180
/**
181
* Reads gc.log file and counts GC induced by metaspace.
182
* @return how many times GC induced by metaspace has occurred.
183
*/
184
protected int getMetaspaceGCCount() {
185
int count = 0;
186
try {
187
for (String line: readGCLog()) {
188
if (line.indexOf("Metadata GC ") > 0) {
189
count++;
190
}
191
}
192
return count;
193
} catch (Throwable t) {
194
t.printStackTrace(System.err);
195
return -1;
196
}
197
}
198
199
protected String lastGCLogLine() {
200
if (gclogFileName == null) {
201
return "";
202
}
203
try {
204
List<String> list = Files.readAllLines(Paths.get(".", gclogFileName));
205
return list.get(list.size() - 1);
206
} catch (IOException e) {
207
return "File not found";
208
}
209
}
210
211
/**
212
* Does it best to checks if the last GC was caused by metaspace.
213
*
214
* This method looks into gc.log file (if -Xloggc:file is given) and returns
215
* true if the last line in the log contains the "Metadata" word.
216
* It's not very reliable way to check, log might not be flushed yet.
217
*
218
* @return
219
*/
220
protected boolean isMetaspaceGC() {
221
return lastGCLogLine().contains("Metadata");
222
}
223
224
/**
225
* Prints amounts of used and committed metaspace preceeded by the message
226
* @param mesg a message to printed prior usages
227
*/
228
protected void printMemoryUsage(String mesg) {
229
MemoryUsage mu = pool.getUsage();
230
printMemoryUsage(mesg, mu.getUsed(), mu.getCommitted());
231
}
232
protected void printMemoryUsage(String mesg, long v1, long v2) {
233
System.out.println(mesg + ": " + bytes2k(v1) + " : " + bytes2k(v2));
234
}
235
protected String bytes2k(long v) {
236
return (v / 1024) + "k";
237
}
238
239
240
241
/**
242
* @return amount of used memory
243
*/
244
public long getUsed() {
245
return pool.getUsage().getUsed();
246
}
247
248
/**
249
* @return amount of committed memory
250
*/
251
public long getCommitted() {
252
return pool.getUsage().getCommitted();
253
}
254
255
private static MemoryPoolMXBean getMemoryPool(String name) {
256
List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
257
for (MemoryPoolMXBean pool : pools) {
258
if (pool.getName().equals(name)) {
259
return pool;
260
}
261
}
262
return null;
263
}
264
265
private static long detectPageSize() {
266
try {
267
Unsafe unsafe = Unsafe.getUnsafe();
268
269
int pageSize = unsafe.pageSize();
270
System.out.println("Page size: " + pageSize);
271
return pageSize;
272
} catch (Exception e) {
273
throw new Fault("Cannot detect page size");
274
}
275
}
276
277
278
long parseValue(String s) {
279
s = s.toLowerCase();
280
int multiplier = 1;
281
switch (s.charAt(s.length() - 1)) {
282
case 'g': multiplier = 1024*1024*1024; break;
283
case 'm': multiplier = 1024*1024; break;
284
case 'k': multiplier = 1024; break;
285
}
286
if (multiplier == 1) {
287
return Long.parseLong(s);
288
} else {
289
return Long.parseLong(s.substring(0, s.length() - 1)) * multiplier;
290
}
291
}
292
293
public static interface Foo {
294
}
295
296
public static class FooBar implements Foo {
297
}
298
299
class FooInvocationHandler implements InvocationHandler {
300
private final Foo foo;
301
302
FooInvocationHandler(MetaspaceBaseGC.Foo foo) {
303
this.foo = foo;
304
}
305
306
@Override
307
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
308
return method.invoke(foo, args);
309
}
310
}
311
312
}
313
314