Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java
40948 views
1
/*
2
* Copyright (c) 2001, 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
/*
25
* Warning! Using this component need VM option -XX:-UseGCOverheadLimit
26
*
27
*/
28
29
package nsk.share;
30
31
import java.util.*;
32
import nsk.share.gc.gp.*;
33
import nsk.share.test.ExecutionController;
34
import nsk.share.test.Stresser;
35
36
/**
37
* The <code>ClassUnloader</code> class allows to force VM to unload class(es)
38
* using memory stressing technique.
39
*
40
* <p>The method <code>unloadClass()</code> is provided which eats memory
41
* to enforce GC to cleanup the heap. So, if all references to a class
42
* and its loader are canceled, this may result in unloading the class.
43
*
44
* <p>ClassUnloader mainly intends to unload a class which was loaded
45
* with especial <code>ClassUnloader.loadClass()</code> method.
46
* A class is considered unloaded if its class loader is finalized.
47
* If there no finalization of class loader detected for some timeout,
48
* class is considered still loaded and method returns <i>false</i>.
49
*
50
* <p>Such finalization control applies only to a class loaded by
51
* ClassUnloader's <code>loadClass()</code> method. Otherwise, if there
52
* was no such class loaded, <code>unloadClass()</code> doesn't wait
53
* for a timeout and always returns <i>false</i>.
54
*
55
* <p>By default internal class loader of <code>CustomClassLoader</code> class
56
* is used for loading classes. This class loader can load class from .class file
57
* located in the specified directory.
58
* Application may define its own class loader, which may load classes using
59
* any other technique. Such class loader should be derived from base
60
* <code>CustomClassLoader</code> class, and set by <code>setClassLoader()</code>
61
* method.
62
*
63
* @see #setClassLoader(CustomClassLoader)
64
* @see #loadClass(String)
65
* @see #loadClass(String, String)
66
* @see #unloadClass()
67
*/
68
public class ClassUnloader {
69
70
/**
71
* Class name of default class loader.
72
*/
73
public static final String INTERNAL_CLASS_LOADER_NAME = "nsk.share.CustomClassLoader";
74
75
/**
76
* Whole amount of time in milliseconds to wait for class loader finalization.
77
*/
78
private static final int WAIT_TIMEOUT = 15000;
79
80
/**
81
* Piece of time in milliseconds to wait in a loop for class loader finalization.
82
*/
83
private static final int WAIT_DELTA = 1000;
84
85
/**
86
* Has class loader been finalized or not.
87
*/
88
volatile boolean finalized = false;
89
90
/**
91
* Current class loader used for loading classes.
92
*/
93
private CustomClassLoader customClassLoader = null;
94
95
/**
96
* List of classes loaded with current class loader.
97
*/
98
private Vector<Class<?>> classObjects = new Vector<Class<?>>();
99
100
/**
101
* Class object of the first class been loaded with current class loader.
102
* To get the rest loaded classes use <code>getLoadedClass(int)</code>.
103
* The call <code>getLoadedClass()</code> is effectively equivalent to the call
104
* <code>getLoadedClass(0)</code>
105
*
106
* @return class object of the first loaded class.
107
*
108
* @see #getLoadedClass(int)
109
*/
110
public Class<?> getLoadedClass() {
111
return classObjects.get(0);
112
}
113
114
/**
115
* Returns class objects at the specified index in the list of classes loaded
116
* with current class loader.
117
*
118
* @return class objects at the specified index.
119
*/
120
public Class<?> getLoadedClass(int index) {
121
return classObjects.get(index);
122
}
123
124
/**
125
* Creates new instance of <code>CustomClassLoader</code> class as the current
126
* class loader and clears the list of loaded classes.
127
*
128
* @return created instance of <code>CustomClassLoader</code> class.
129
*
130
* @see #getClassLoader()
131
* @see #setClassLoader(CustomClassLoader)
132
*/
133
public CustomClassLoader createClassLoader() {
134
customClassLoader = new CustomClassLoader(this);
135
classObjects.removeAllElements();
136
137
return customClassLoader;
138
}
139
140
/**
141
* Sets new current class loader and clears the list of loaded classes.
142
*
143
* @see #getClassLoader()
144
* @see #createClassLoader()
145
*/
146
public void setClassLoader(CustomClassLoader customClassLoader) {
147
this.customClassLoader = customClassLoader;
148
classObjects.removeAllElements();
149
customClassLoader.setClassUnloader(this);
150
}
151
152
/**
153
* Returns current class loader or <i>null</i> if not yet created or set.
154
*
155
* @return class loader object or null.
156
*
157
* @see #createClassLoader()
158
* @see #setClassLoader(CustomClassLoader)
159
*/
160
public CustomClassLoader getClassLoader() {
161
return customClassLoader;
162
}
163
164
/**
165
* Loads class for specified class name using current class loader.
166
*
167
* <p>Current class loader should be set and capable to load class using only
168
* given class name. No other information such a location of .class files
169
* is passed to class loader.
170
*
171
* @param className name of class to load
172
*
173
* @throws ClassNotFoundException if no bytecode found for specified class name
174
* @throws Failure if current class loader is not specified;
175
* or if class was actually loaded with different class loader
176
*
177
* @see #loadClass(String, String)
178
*/
179
public void loadClass(String className) throws ClassNotFoundException {
180
181
if (customClassLoader == null) {
182
throw new Failure("No current class loader defined");
183
}
184
185
Class<?> cls = Class.forName(className, true, customClassLoader);
186
187
// ensure that class was loaded by current class loader
188
if (cls.getClassLoader() != customClassLoader) {
189
throw new Failure("Class was loaded by unexpected class loader: " + cls.getClassLoader());
190
}
191
192
classObjects.add(cls);
193
}
194
195
/**
196
* Loads class from .class file located into specified directory using
197
* current class loader.
198
*
199
* <p>If there is no current class loader, then default class loader
200
* is created using <code>createClassLoader()</code>. Parameter <i>classDir</i>
201
* is passed to class loader using <code>CustomClassLoader.setClassPath()</code>
202
* method before loading class.
203
*
204
* @param className name of class to load
205
* @param classDir path to .class file location
206
*
207
* @throws ClassNotFoundException if no .class file found
208
* for specified class name
209
* @throws Failure if class was actually loaded with different class loader
210
*
211
* @see #loadClass(String)
212
* @see CustomClassLoader#setClassPath(String)
213
*/
214
public void loadClass(String className, String classDir) throws ClassNotFoundException {
215
216
if (customClassLoader == null) {
217
createClassLoader();
218
}
219
220
customClassLoader.setClassPath(classDir);
221
loadClass(className);
222
}
223
224
/**
225
* Forces GC to unload previously loaded classes by cleaning all references
226
* to class loader with its loaded classes and eating memory.
227
*
228
* @return <i>true</i> if classes unloading has been detected
229
or <i>false</i> otherwise
230
*
231
* @throws Failure if exception other than OutOfMemoryError
232
* is thrown while eating memory
233
*
234
* @see #eatMemory()
235
*/
236
public boolean unloadClass(ExecutionController stresser) {
237
238
finalized = false;
239
240
// free references to class and class loader to be able for collecting by GC
241
long waitTimeout = (customClassLoader == null) ? 0 : WAIT_TIMEOUT;
242
classObjects.removeAllElements();
243
customClassLoader = null;
244
245
// force class unloading by eating memory pool
246
eatMemory(stresser);
247
248
// give GC chance to run and wait for finalization
249
long timeToFinish = System.currentTimeMillis() + waitTimeout;
250
while (!finalized && System.currentTimeMillis() < timeToFinish) {
251
if (!stresser.continueExecution()) {
252
return false;
253
}
254
try {
255
// suspend thread for a while
256
Thread.sleep(WAIT_DELTA);
257
} catch (InterruptedException e) {
258
throw new Failure("Unexpected InterruptedException while class unloading: " + e);
259
}
260
}
261
262
// force GC to unload marked class loader and its classes
263
if (finalized) {
264
Runtime.getRuntime().gc();
265
return true;
266
}
267
268
// class loader has not been finalized
269
return false;
270
}
271
272
public boolean unloadClass() {
273
Stresser stresser = new Stresser() {
274
275
@Override
276
public boolean continueExecution() {
277
return true;
278
}
279
280
};
281
return unloadClass(stresser);
282
}
283
284
/**
285
* Stresses memory by allocating arrays of bytes.
286
*
287
* Note that this method can throw Failure if any exception
288
* is thrown while eating memory. To avoid OOM while allocating
289
* exception we preallocate it before the lunch starts. It means
290
* that exception stack trace does not correspond to the place
291
* where exception is thrown, but points at start of the method.
292
*
293
* @throws Failure if exception other than OutOfMemoryError
294
* is thrown while eating memory
295
*/
296
public static void eatMemory(ExecutionController stresser) {
297
GarbageUtils.eatMemory(stresser, 50, 1024, 2);
298
299
/*
300
* System.runFinalization() may potentially fail with OOM. This is why
301
* System.runFinalization() is repeated several times.
302
*/
303
for (int i = 0; i < 10; ++i) {
304
try {
305
if(!stresser.continueExecution()) {
306
return;
307
}
308
System.runFinalization();
309
break;
310
} catch (OutOfMemoryError e) {
311
}
312
}
313
}
314
315
/**
316
* Stresses memory by allocating arrays of bytes.
317
*
318
* Note that this method can throw Failure if any exception
319
* is thrown while eating memory. To avoid OOM while allocating
320
* exception we preallocate it before the lunch starts. It means
321
* that exception stack trace does not correspond to the place
322
* where exception is thrown, but points at start of the method.
323
*
324
* @throws Failure if exception other than OutOfMemoryError
325
* is thrown while eating memory
326
*/
327
public static void eatMemory() {
328
Stresser stresser = new Stresser() {
329
330
@Override
331
public boolean continueExecution() {
332
return true;
333
}
334
335
};
336
GarbageUtils.eatMemory(stresser, 50, 1024, 2);
337
/*
338
* System.runFinalization() may potentially fail with OOM. This is why
339
* System.runFinalization() is repeated several times.
340
*/
341
for (int i = 0; i < 10; ++i) {
342
try {
343
if(!stresser.continueExecution()) {
344
return;
345
}
346
System.runFinalization();
347
break;
348
} catch (OutOfMemoryError e) {
349
}
350
}
351
}
352
}
353
354