Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/metaspace/stressDictionary/StressDictionary.java
41153 views
1
/*
2
* Copyright (c) 2013, 2020, 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
* @test
26
* @key randomness
27
*
28
* @summary converted from VM Testbase metaspace/stressDictionary.
29
* VM Testbase keywords: [nonconcurrent, javac]
30
*
31
* @library /vmTestbase /test/lib
32
* @run main/othervm/timeout=600 metaspace.stressDictionary.StressDictionary -stressTime 30
33
*/
34
35
package metaspace.stressDictionary;
36
37
import java.util.*;
38
import java.lang.management.ManagementFactory;
39
import java.lang.reflect.InvocationTargetException;
40
import java.lang.reflect.Method;
41
import java.util.concurrent.*;
42
import java.util.concurrent.atomic.AtomicLong;
43
44
import nsk.share.gc.GCTestBase;
45
import nsk.share.test.*;
46
import vm.share.InMemoryJavaCompiler;
47
48
/**
49
* There is a data structure named "dictionary" in class BlockFreelist. It stores
50
* information about free memory blocks for further reusing. Allocation of new block goes
51
* from dictionary only if dictionary is fat enough. (At the moment of test creation this limit is 64K.)
52
* So to stress dictionary we should fill it permanently. The easiest way to fill the dictionary
53
* is to fail class loading. This failed action will return allocated blocks to dictionary.
54
*
55
* There are two type of threads in this test: threads, failing classloading and threads,
56
* loading regular classes and checking they work properly.
57
*/
58
public class StressDictionary extends GCTestBase {
59
60
private static byte[] bytecode;
61
62
private class FillingDictionaryWorker implements Callable<Object> {
63
private final Random random;
64
public FillingDictionaryWorker(long seed) {
65
this.random = new Random(seed);
66
}
67
@Override
68
public Object call() throws Exception {
69
while (stresser.continueExecution()) {
70
try {
71
byte[] badBytecode = bytecode.clone();
72
badBytecode[random.nextInt(badBytecode.length)] = (byte) 42;
73
classloader.define(badBytecode);
74
} catch (Throwable e) {
75
// We can get ClassFormatError, ClassNotFoundException or anything else here
76
}
77
}
78
return null;
79
}
80
}
81
82
private class RegularWorker implements Callable<Object> {
83
@Override
84
public Object call() throws Exception {
85
while (stresser.continueExecution()) {
86
Class<?> c = classloader.define(bytecode);
87
testClass(c);
88
}
89
return null;
90
}
91
}
92
93
private static String[] args;
94
95
private static final String methodName = "myMethod";
96
97
private static final int NUMBER_OF_CORRUPTING_THREADS = 10;
98
99
private static final int NUMBER_OF_METHOD_CALLS = 50;
100
101
private static final int NUMBER_OF_NOT_CORRUPTING_THREADS = 10;
102
103
private AtomicLong classesCounter = new AtomicLong(0);
104
105
private volatile ClassloaderUnderTest classloader = new ClassloaderUnderTest();
106
107
private Random random;
108
109
private ExecutionController stresser;
110
111
public static void main(String[] args) {
112
StressDictionary.args = args;
113
Tests.runTest(new StressDictionary(), args);
114
}
115
116
public void run() {
117
random = new Random(runParams.getSeed());
118
stresser = new Stresser(args);
119
stresser.start(1);
120
// Generate some bytecodes.
121
bytecode = generateAndCompile();
122
List<Callable<Object>> tasks = new LinkedList<Callable<Object>>();
123
for (int i = 0; i < NUMBER_OF_CORRUPTING_THREADS; i++) {
124
tasks.add(this.new FillingDictionaryWorker(random.nextLong()));
125
}
126
for (int i = 0; i < NUMBER_OF_NOT_CORRUPTING_THREADS; i++) {
127
tasks.add(this.new RegularWorker());
128
}
129
ExecutorService executorService = Executors.newCachedThreadPool();
130
List<Future<Object>> results = null;
131
try {
132
results = executorService.invokeAll(tasks);
133
} catch (InterruptedException e) {
134
e.printStackTrace();
135
}
136
137
int act_results = results.size();
138
int exp_results = NUMBER_OF_CORRUPTING_THREADS +
139
NUMBER_OF_NOT_CORRUPTING_THREADS;
140
if (act_results == exp_results) {
141
System.err.println("INFO: There are " + act_results + " results.");
142
} else {
143
throw new RuntimeException("Wrong # of results from invokeAll(); "
144
+ "exp_results=" + exp_results + "; "
145
+ "act_results=" + act_results + ".");
146
}
147
148
int cancelled_cnt = 0;
149
int not_done_cnt = 0;
150
for (int i = 0; i < act_results; i++) {
151
if (!results.get(i).isDone()) {
152
not_done_cnt++;
153
System.err.println("ERROR: task #" + i + " is not done.");
154
}
155
if (results.get(i).isCancelled()) {
156
cancelled_cnt++;
157
System.err.println("ERROR: task #" + i + " was canceled.");
158
}
159
}
160
161
if (cancelled_cnt == 0) {
162
System.err.println("INFO: no tasks were cancelled.");
163
}
164
if (not_done_cnt == 0) {
165
System.err.println("INFO: all tasks are done.");
166
}
167
if (cancelled_cnt != 0 && not_done_cnt != 0) {
168
throw new RuntimeException(cancelled_cnt
169
+ " tasks were cancelled and "
170
+ not_done_cnt
171
+ " tasks are not done.");
172
} else if (cancelled_cnt != 0) {
173
throw new RuntimeException(cancelled_cnt
174
+ " tasks were cancelled.");
175
} else if (not_done_cnt != 0) {
176
throw new RuntimeException(not_done_cnt + " tasks are not done.");
177
}
178
}
179
180
private byte[] generateAndCompile() {
181
Map<String, CharSequence> sources = new HashMap<String, CharSequence>();
182
String className = "MyClass" + classesCounter.incrementAndGet();
183
sources.put(className, generateSource(className));
184
return InMemoryJavaCompiler.compile(sources).values().iterator().next();
185
}
186
187
private CharSequence generateSource(String className) {
188
return "public class " + className + " { " +
189
"public static String s1 = \"s1" + random.nextInt() + "\"; " +
190
"public String s2 = \"s2" + random.nextInt() + "\"; " +
191
"public String " + methodName + "() {return s1 + s2; } " +
192
"}";
193
}
194
195
private void testClass(Class<?> clazz) {
196
try {
197
for (Method m : clazz.getMethods()) {
198
if (m.getName().equals(methodName)) {
199
for (int j = 0; j < NUMBER_OF_METHOD_CALLS; j++) {
200
m.invoke(clazz.newInstance());
201
}
202
}
203
}
204
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
205
log.error("Class check failed: " + e.getMessage());
206
e.printStackTrace();
207
setFailed(true);
208
}
209
210
}
211
212
}
213
214