1 /* 2 * Copyright (c) 2007, 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 * jnistress006 is a class that sets up classes that do the work 26 * for the test. 27 * 28 * The Interrupter objects send interrupts to the JNIters. 29 * The GarbageGenerator objects generate garbage. 30 * 31 * sync[0] synchronizes the test cycles. 32 * sync[1] synchronizes access to exception counters. 33 * sync[2] synchronizes the cycle count update. It also insures that 34 * the interrupts do not interfere with the cycle count updates. 35 * This is because cycle count updates are used to define cycles. 36 */ 37 38 39 /* 40 * @test 41 * @key stress 42 * 43 * @summary converted from VM testbase nsk/stress/jni/jnistress006. 44 * VM testbase keywords: [stress, quick, feature_283, nonconcurrent] 45 * 46 * @library /vmTestbase 47 * /test/lib 48 * @run main/othervm/native 49 * nsk.stress.jni.jnistress006 50 * -numTHREADer 20 51 * -threadInterval 200 52 * -numInterrupter 2 53 * -interruptInterval 500 54 * -numGarbage 80 55 * -garbageInterval 5 56 * -numIteration 260 57 */ 58 59 package nsk.stress.jni; 60 61 import nsk.share.Consts; 62 import nsk.share.Debug; 63 import nsk.share.test.StressOptions; 64 65 public class jnistress006 extends Thread { 66 67 /* Maximum number of iterations. Ignored if <= 0L */ 68 static long numIteration = 0L; 69 /* Timeout */ 70 static long timeOut; 71 /* Number of test class objects */ 72 static int numJNIter = 1; 73 /* Time between JNI stressing by the threads under test */ 74 /* (in milliseconds) */ 75 static int jniInterval = 10000; 76 /* Number of interrupting threads */ 77 static int numInterrupter = 1; 78 /* Time between interrupts in milliseconds */ 79 static int interruptInterval = 100; 80 /* Number of garbage generating threads */ 81 static int numGarbage = 1; 82 /* Time between garbage allocations in milliseconds */ 83 static int garbageInterval = 100; 84 // The MAX quantity of creates global refs 85 static int jniStringAllocSize = 30000; 86 87 private static StressOptions stressOptions; 88 main(String[] argv)89 public static void main(String[] argv) { 90 try { 91 int i = 0; 92 int nJNISync = 10; 93 jnistress006 dm = null; 94 boolean errArg = false; 95 96 stressOptions = new StressOptions(argv); 97 98 /* Process arguments */ 99 while (!errArg && i < argv.length) { 100 /* Number of iterations. Ignored if <= 0. */ 101 if (i < argv.length && argv[i].equals("-numIteration")) { 102 ++i; 103 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 104 try { 105 numIteration = Long.parseLong(argv[i++]); 106 } catch (NumberFormatException e) { 107 errArg = true; 108 } 109 } 110 } else if (i < argv.length && argv[i].equals("-numTHREADer")) { 111 ++i; 112 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 113 try { 114 numJNIter = Integer.parseInt(argv[i++]); 115 } catch (NumberFormatException e) { 116 errArg = true; 117 } 118 if (numJNIter <= 0) errArg = true; 119 } 120 } else if (i < argv.length && argv[i].equals("-threadInterval")) { 121 ++i; 122 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 123 try { 124 jniInterval = Integer.parseInt(argv[i++]); 125 } catch (NumberFormatException e) { 126 errArg = true; 127 } 128 } 129 } else if (i < argv.length && argv[i].equals("-numInterrupter")) { 130 ++i; 131 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 132 try { 133 numInterrupter = Integer.parseInt(argv[i++]); 134 } catch (NumberFormatException e) { 135 errArg = true; 136 } 137 } 138 } else if (i < argv.length && argv[i].equals("-interruptInterval")) { 139 ++i; 140 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 141 try { 142 interruptInterval = Integer.parseInt(argv[i++]); 143 } catch (NumberFormatException e) { 144 errArg = true; 145 } 146 } 147 } else if (i < argv.length && argv[i].equals("-numGarbage")) { 148 ++i; 149 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 150 try { 151 numGarbage = Integer.parseInt(argv[i++]); 152 } catch (NumberFormatException e) { 153 errArg = true; 154 } 155 } 156 } else if (i < argv.length && argv[i].equals("-garbageInterval")) { 157 ++i; 158 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 159 try { 160 garbageInterval = Integer.parseInt(argv[i++]); 161 } catch (NumberFormatException e) { 162 errArg = true; 163 } 164 } 165 } else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) { 166 ++i; 167 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 168 try { 169 jniStringAllocSize = Integer.parseInt(argv[i++]); 170 } catch (NumberFormatException e) { 171 errArg = true; 172 } 173 } 174 } else if (i < argv.length && argv[i].startsWith("-stress")) { 175 ++i; 176 if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { 177 ++i; 178 } 179 } else System.out.println("Argument #" + i++ + " is incorrect"); 180 } 181 182 numIteration *= stressOptions.getIterationsFactor(); 183 numJNIter *= stressOptions.getThreadsFactor(); 184 numInterrupter *= stressOptions.getThreadsFactor(); 185 numGarbage *= stressOptions.getThreadsFactor(); 186 timeOut = stressOptions.getTime() * 1000; 187 188 sync = new Synchronizer[10]; 189 for (i = 0; i < nJNISync; i++) 190 sync[i] = new Synchronizer(); 191 dm = new jnistress006(numIteration, numJNIter, jniInterval, 192 numInterrupter, interruptInterval, numGarbage, garbageInterval); 193 194 dm.start(); 195 196 try { 197 dm.join(timeOut); 198 } catch (InterruptedException e) { 199 System.out.println("TESTER THREAD WAS INTERRUPTED"); 200 System.exit(Consts.TEST_FAILED); 201 } 202 203 if (DEBUG) System.out.println("jnistress006::main(): halt!"); 204 205 if (dm.isAlive()) { 206 System.out.println("TIME LIMIT EXCEEDED"); 207 dm.halt(); 208 if (DEBUG) System.out.println("jnistress006::main(): join!"); 209 try { 210 dm.join(10000L); 211 } catch (InterruptedException e) { 212 System.out.println("TESTER THREAD WAS INTERRUPTED"); 213 System.exit(Consts.TEST_FAILED); 214 } 215 } else { 216 System.out.println("TESTER THREAD FINISHED"); 217 } 218 219 if (DEBUG) System.out.println("jnistress006::main(): zzzz..."); 220 221 if (!JNIter006.passed()) 222 System.exit(Consts.TEST_FAILED); 223 224 } catch (Throwable e) { 225 Debug.Fail(e); 226 } 227 } 228 jnistress006( long iters, int nJNI, int jniInterval, int nInter, int iruptInterval, int nGarb, int garbInterval )229 jnistress006( 230 long iters, 231 int nJNI, 232 int jniInterval, 233 int nInter, 234 int iruptInterval, 235 int nGarb, 236 int garbInterval 237 ) { 238 int i = 0; 239 nCycles = iters; 240 /* Should have at least one of nCycles>0 */ 241 if (nCycles <= 0) nCycles = Long.MAX_VALUE; 242 jniter = new JNIter006[nJNI]; 243 interval = jniInterval; 244 irupt = new Interrupter[nInter]; 245 garb = new GarbageGenerator[nGarb]; 246 for (i = 0; i < nJNI; i++) 247 jniter[i] = new JNIter006(sync); 248 for (i = 0; i < nInter; i++) { 249 irupt[i] = new Interrupter(jniter, sync); 250 irupt[i].setInterval(iruptInterval); 251 } 252 for (i = 0; i < nGarb; i++) { 253 garb[i] = new GarbageGenerator(); 254 garb[i].setInterval(garbInterval); 255 } 256 } 257 run()258 public void run() { 259 try { 260 int i = 0; 261 long iCycle = 0L; 262 JNIter006.clearCount(); 263 JNIter006.clearInterruptCount(); 264 for (i = 0; i < jniter.length; i++) 265 jniter[i].start(); 266 267 while (JNIter006.getCount() < jniter.length) { 268 try { 269 sleep(100); 270 } catch (InterruptedException e) { 271 } 272 } 273 JNIter006.clearCount(); 274 // JNIter006.clearInterruptCount(); 275 synchronized (sync[0]) { 276 sync[0].notifyAll(); 277 } 278 279 for (i = 0; i < garb.length; i++) 280 garb[i].start(); 281 for (i = 0; i < irupt.length; i++) 282 irupt[i].start(); 283 284 if (DEBUG) System.out.println("Cycles=" + nCycles); 285 for (iCycle = 0; iCycle < nCycles && !done && JNIter006.passed(); iCycle++) { 286 System.out.print("Cycle: " + iCycle); 287 try { 288 sleep(interval); 289 } catch (InterruptedException e) { 290 } 291 synchronized (sync[1]) { 292 System.out.println(" Interrupt count=" + 293 JNIter006.getInterruptCount()); 294 } 295 JNIter006.clearCount(); 296 synchronized (sync[0]) { 297 sync[0].notifyAll(); 298 } 299 int n = 0; 300 for (i = 0; i < jniter.length; i++) 301 if (jniter[i].finished()) n++; 302 if (n == jniter.length) break; 303 } 304 if (JNIter006.passed()) 305 System.out.println("JNI TEST PASSED"); 306 else 307 System.out.println("JNI TEST FAILED"); 308 for (i = 0; i < irupt.length; i++) 309 irupt[i].halt(); 310 for (i = 0; i < garb.length; i++) 311 garb[i].halt(); 312 for (i = 0; i < jniter.length; i++) 313 jniter[i].halt(); 314 /* Flush any waiters */ 315 if (DEBUG) System.out.println("jnistress006::run(): before sync[0]"); 316 synchronized (sync[0]) { 317 sync[0].notifyAll(); 318 } 319 if (DEBUG) System.out.println("jnistress006::run(): after sync[0]"); 320 for (i = 0; i < irupt.length; i++) { 321 try { 322 irupt[i].join(); 323 } catch (InterruptedException e) { 324 } 325 } 326 if (DEBUG) System.out.println("jnistress006::run(): X"); 327 for (i = 0; i < garb.length; i++) { 328 try { 329 garb[i].join(); 330 } catch (InterruptedException e) { 331 } 332 } 333 if (DEBUG) System.out.println("jnistress006::run(): Y"); 334 synchronized (sync[0]) { 335 sync[0].notifyAll(); 336 } 337 for (i = 0; i < jniter.length; i++) { 338 try { 339 if (jniter[i].isAlive()) { 340 jniter[i].join(); 341 } 342 } catch (InterruptedException e) { 343 } 344 } 345 if (DEBUG) System.out.println("jnistress006::run(): Z"); 346 } catch (Throwable e) { 347 Debug.Fail(e); 348 } 349 } 350 halt()351 public void halt() { 352 done = true; 353 } 354 finished()355 public boolean finished() { 356 return done; 357 } 358 359 long nCycles = 0; 360 JNIter006[] jniter; 361 static Synchronizer[] sync; 362 private int interval = 100; 363 Interrupter[] irupt; 364 GarbageGenerator[] garb; 365 private boolean done = false; 366 final private static boolean DEBUG = false; 367 } 368 369 class JNIter006 extends Thread { 370 371 // The native methods for testing JNI exception calls refs(Object tobj, int jniStringAllocSize)372 public native boolean refs(Object tobj, int jniStringAllocSize); 373 374 static { 375 System.loadLibrary("jnistress006"); 376 } 377 378 Referenced tobj = new Referenced(); 379 static int CountRefs; 380 JNIter006(Synchronizer[] aSync)381 public JNIter006(Synchronizer[] aSync) { 382 sync = aSync; 383 } 384 run()385 public void run() { 386 try { 387 int iter = 0; 388 389 /* Synchronize start of work */ 390 incCount(); 391 synchronized (sync[0]) { 392 try { 393 sync[0].wait(); 394 } catch (InterruptedException e) { 395 } 396 } 397 while (!done && pass) { 398 try { 399 /* Synchronized the JNI stressing */ 400 synchronized (sync[2]) { 401 incCount(); 402 } 403 synchronized (sync[0]) { 404 try { 405 sync[0].wait(); 406 } catch (InterruptedException e) { 407 synchronized (sync[1]) { 408 JNIter006.incInterruptCount(); 409 } 410 } 411 } 412 synchronized (sync[0]) { 413 try { 414 tobj.set_i(123456); 415 pass = refs(tobj, jnistress006.jniStringAllocSize); 416 } catch (Exception e) { 417 System.out.println("Error: " + e); 418 } 419 } 420 if (DEBUG) 421 System.out.println("We have " + activeCount() + " threads now."); 422 synchronized (this) { 423 try { 424 wait(1L); 425 } catch (InterruptedException e) { 426 throw new InterruptedException(); 427 } 428 } 429 } catch (Exception e) { 430 synchronized (sync[1]) { 431 JNIter006.incInterruptCount(); 432 } 433 } 434 iter++; 435 iter = iter % CASECOUNT; 436 } 437 if (DEBUG) System.out.println("JNITer::run(): done=" + done); 438 done = true; 439 if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter006.pass); 440 if (DEBUG) System.out.println("JNIter006::run(): done"); 441 } catch (Throwable e) { 442 Debug.Fail(e); 443 } 444 } 445 incCount()446 private synchronized static void incCount() { 447 count++; 448 } 449 getCount()450 public static int getCount() { 451 return count; 452 } 453 clearCount()454 public synchronized static void clearCount() { 455 count = 0; 456 } 457 incInterruptCount()458 private synchronized static void incInterruptCount() { 459 interruptCount++; 460 } 461 getInterruptCount()462 public static int getInterruptCount() { 463 return interruptCount; 464 } 465 clearInterruptCount()466 public synchronized static void clearInterruptCount() { 467 interruptCount = 0; 468 } 469 halt()470 public void halt() { 471 done = true; 472 } 473 finished()474 public boolean finished() { 475 return done; 476 } 477 passed()478 public static boolean passed() { 479 return pass; 480 } 481 482 Synchronizer[] sync; 483 private static int count = 0; 484 private static int interruptCount = 0; 485 private static boolean done = false; 486 private static boolean pass = true; 487 final private static int CASECOUNT = 2; 488 final private static boolean DEBUG = false; 489 } 490 491 class Referenced { 492 private static int i; 493 set_i(int value)494 public static void set_i(int value) { 495 i = value; 496 } 497 get_i()498 public static int get_i() { 499 return i; 500 } 501 } 502