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