Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/gc/hashcode/ExternalHashingTest/ExternalHashingTest.java
40948 views
1
/*
2
* Copyright (c) 2008, 2021, 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
26
/*
27
* @test
28
* @key stress randomness
29
*
30
* @summary converted from VM Testbase gc/hashcode/ExternalHashingTest.
31
* VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, jrockit]
32
* VM Testbase readme:
33
* DESCRIPTION
34
* Test the possible interaction of external hashing and locking on object
35
* headers.
36
* The approach is to nearly simultaneously lock/hash a relatively small group
37
* of objects. We do this repeatedly (munging), recording all hash values
38
* collected therein.
39
* After doing this for a large number of groups, we force a garbage collection,
40
* which would change the hashCode of an object if it hasn't previously been
41
* hashed. In our case, we _know_ what the previous hashcode was, so we can
42
* recalculate all of their hashes and compare with the original value.
43
* If any of the hashCodes hash changed, we know we have a problem.
44
*
45
* COMMENTS
46
* This test was ported from JRockit test suite.
47
*
48
* @library /vmTestbase
49
* /test/lib
50
* @run main/othervm -XX:-UseGCOverheadLimit gc.hashcode.ExternalHashingTest.ExternalHashingTest
51
*/
52
53
package gc.hashcode.ExternalHashingTest;
54
55
import java.text.SimpleDateFormat;
56
import java.util.Date;
57
import java.util.Random;
58
import java.util.Vector;
59
60
import jdk.test.lib.Utils;
61
62
/**
63
* Test the possible interaction of external hashing and locking on object
64
* headers.
65
*
66
* The approach is to nearly simultaneously lock/hash a relatively small group
67
* of objects. We do this repeatedly (munging), recording all hash values
68
* collected therein.
69
*
70
* After doing this for a large number of groups, we force a garbage collection,
71
* which would change the hashCode of an object if it hasn't previously been
72
* hashed. In our case, we _know_ what the previous hashcode was, so we can
73
* recalculate all of their hashes and compare with the original value.
74
*
75
* If any of the hashCodes hash changed, we know we have a problem.
76
*/
77
78
public final class ExternalHashingTest {
79
80
/** Random number generator. */
81
static Random rand = Utils.getRandomInstance();
82
83
/** Goes to true when the threads should start working. */
84
public static volatile boolean startingGun;
85
86
/** Goes to true when the hashing thread is done. */
87
public static volatile boolean finishHashing;
88
89
/** Goes to true when the locking thread is done. */
90
public static volatile boolean finishLocking;
91
92
/** The number of objects in each batch. */
93
private static final int BATCH_SIZE = 20;
94
95
/** This is the global list of objects that have been hashed. */
96
static Vector allObjects = new Vector();
97
98
/** This is the corresponding list of hashCodes collected. */
99
static Vector allHashes = new Vector();
100
101
/** The default milliseconds to run the program. */
102
private static final long DEFAULT_DURATION = 10000;
103
104
/** All static */
105
private ExternalHashingTest() {}
106
107
/**
108
* This object holds garbage. It is a (probably unnecessary){ embellishment
109
* to increase the amount of garbage created by this benchmark.
110
* <p>
111
* It is global to discourage optimizer from removing it.
112
*/
113
public static Object[] garbageMonger;
114
115
/**
116
* We need a fairly short pause, since we're not using a semaphore to
117
* synchronize threads.
118
*/
119
public static void pause() {
120
try {
121
// Thread.sleep(100);
122
Thread.yield();
123
} catch (Exception e) {
124
e.printStackTrace();
125
System.exit(1);
126
}
127
}
128
129
/**
130
* Returns System.currentTimeMillis() in the Date format.
131
* @return String
132
*/
133
private static String getDateString() {
134
SimpleDateFormat df = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss z");
135
Date date = new Date();
136
date.setTime(System.currentTimeMillis());
137
return df.format(date);
138
}
139
140
/**
141
* Main driver.
142
* @param args command line arguments aren't used.
143
*/
144
public static void main(String[] args) {
145
146
long timeToRun = DEFAULT_DURATION;;
147
148
try {
149
for (int i = 0; i < args.length; i++) {
150
if ("-stressTime".equals(args[i])) {
151
if (i + 1 == args.length) {
152
throw new RuntimeException("Test bug: value of -stressTime option absents");
153
}
154
timeToRun = Long.parseLong(args[i + 1]);
155
if (timeToRun <= 0) {
156
throw new RuntimeException("Test bug: value of -stressTime option is not a positive number");
157
}
158
break;
159
}
160
}
161
} catch (NumberFormatException e) {
162
throw new RuntimeException("Test bug: Exception occured while parsing -stressTime option's value", e);
163
}
164
165
long startTime = System.currentTimeMillis();
166
167
System.out.println("[" + getDateString() + "] Test duration is: " + timeToRun + " ms");
168
System.out.println("[" + getDateString() + "] Do munge objects...");
169
while ((System.currentTimeMillis() - startTime) < timeToRun) {
170
for (int i = 0; i < 100; i++) {
171
mungeObjects();
172
}
173
System.out.println("[" + getDateString() + "] The next 100 objects are munged...");
174
}
175
176
// Force a GC (so that objects move their position)
177
System.out.println("[" + getDateString() + "] Force a GC...");
178
garbageMonger = null;
179
System.gc();
180
181
// Now, to check to see if hashes are correct
182
System.out.println("[" + getDateString() + "] Check hash codes...");
183
for (int i = 0; i < allObjects.size(); i++) {
184
Object o = allObjects.elementAt(i);
185
int hash = ((Integer) allHashes.elementAt(i)).intValue();
186
187
if (o.hashCode() != hash) {
188
System.out.println("Inconsistent hash code found (Object "
189
+ i + " out of " + allObjects.size());
190
System.out.println("Object = " + o.toString() + "; hashCode = 0x"
191
+ Integer.toHexString(o.hashCode())
192
+ "; expected = 0x" + Integer.toHexString(hash));
193
System.exit(1);
194
}
195
}
196
197
System.exit(95 /* PASSED */);
198
}
199
200
/**
201
* Add a single batch of objects to the mix.
202
* <p>
203
* It prepares a list of candidate objects, and presents them to a
204
* LockerThread and a HasherThread in randomized orders.
205
* <p>
206
* The two threads are launched, and control is returned to the caller after
207
* they have finished their processing.
208
*/
209
private static void mungeObjects() {
210
211
startingGun = false;
212
finishHashing = false;
213
finishLocking = false;
214
215
/* Create the list of victims. */
216
Object[] candidates = new Object[BATCH_SIZE];
217
for (int i = 0; i < candidates.length; i++) {
218
candidates[i] = new Object();
219
}
220
221
Object[] lockedList = randomize(candidates);
222
Object[] hashedList = randomize(candidates);
223
int[] foundHashes = new int[BATCH_SIZE];
224
225
// Launch the child threads
226
LockerThread locker = new LockerThread(lockedList);
227
Thread lockerThread = new Thread(locker);
228
Thread hasherThread = new Thread(new HasherThread(hashedList,
229
foundHashes));
230
lockerThread.start();
231
hasherThread.start();
232
startingGun = true;
233
234
while (!finishLocking || !finishHashing) {
235
pause();
236
}
237
238
garbageMonger = new Object[BATCH_SIZE];
239
for (int i = 0; i < BATCH_SIZE; i++) {
240
/* Add all of the results of this pass to the global list. */
241
allObjects.add(hashedList[i]);
242
allHashes.add(Integer.valueOf(foundHashes[i]));
243
244
/* Create even more garbage for the GC to find */
245
garbageMonger[i] = new Object();
246
}
247
248
// just some noise to make sure that do-nothing code is not optimized
249
// away.
250
if (locker.getCount() != BATCH_SIZE) {
251
throw new InternalError("should not get here");
252
}
253
}
254
255
/**
256
* Return the list of objects in random order
257
*/
258
private static Object[] randomize(Object[] list) {
259
260
Vector v = new Vector();
261
for (int i = 0; i < list.length; i++) {
262
v.add(list[i]);
263
}
264
265
Object[] result = new Object[list.length];
266
for (int i = 0; i < list.length; i++) {
267
int pos = rand.nextInt(list.length - i);
268
result[i] = v.remove(pos);
269
}
270
return result;
271
}
272
}
273
274
/**
275
* This helper thread locks all objects in a list in a given order before
276
* returning.
277
*/
278
279
class LockerThread implements Runnable {
280
281
/** The list of objects to be locked. */
282
Object[] theList;
283
284
/**
285
* This junk counter is an attempt to cause the contents of the synchronized
286
* block not to be completely optimized away.
287
*/
288
int count;
289
290
/**
291
* Construct a LockerThread and provide a list of objects to work with.
292
* @param list the objects to lock.
293
*/
294
LockerThread(Object[] list) {
295
theList = list;
296
count = 0;
297
}
298
299
/**
300
* Proceed to lock the objects...
301
*/
302
public void run() {
303
// Synchronize. Wait for caller to say all is go.
304
while (!ExternalHashingTest.startingGun) {
305
ExternalHashingTest.pause();
306
}
307
308
// Perform the locking
309
for (int i = 0; i < theList.length; i++) {
310
synchronized (theList[i]) {
311
count++;
312
}
313
}
314
315
// Tell the caller we are done.
316
ExternalHashingTest.finishLocking = true;
317
}
318
319
/**
320
* Discourage compiler from removing do-nothing count field.
321
* @return the number of objects locked.
322
*/
323
public int getCount() {
324
return count;
325
}
326
}
327
328
/**
329
* This helper thread hashes all objects in a list in a given order before
330
* returning.
331
*/
332
333
class HasherThread implements Runnable {
334
335
/** The list of objects to be hashed. */
336
Object[] theList;
337
338
/** The list of hash codes. */
339
int[] theHashes;
340
341
/**
342
* Construct a HasherThread and provide a list of objects to work with.
343
* @param list the objects to hash.
344
* @param hashes for storing the hash values.
345
*/
346
HasherThread(Object[] list, int[] hashes) {
347
theList = list;
348
theHashes = hashes;
349
}
350
351
/**
352
* Proceed to hash the objects.
353
*/
354
public void run() {
355
// Synchronize. Wait for caller to say all is go.
356
while (!ExternalHashingTest.startingGun) {
357
ExternalHashingTest.pause();
358
}
359
360
// Perform the hashing (collect for the caller)
361
for (int i = 0; i < theList.length; i++) {
362
theHashes[i] = theList[i].hashCode();
363
}
364
// Tell the caller we are done.
365
ExternalHashingTest.finishHashing = true;
366
}
367
}
368
369