1 /* 2 * Copyright (c) 2003, 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 * @test 26 * @key stress 27 * 28 * @summary converted from VM testbase nsk/stress/strace/strace005. 29 * VM testbase keywords: [stress, strace] 30 * VM testbase readme: 31 * DESCRIPTION 32 * The test checks up java.lang.Thread.getStackTrace() method for many threads, 33 * that recursively invoke pure java and native methods by turns in running 34 * mode ("alive" stack). 35 * The test fails if: 36 * - amount of stack trace elements is more than depth of recursion plus 37 * four elements corresponding to invocations of Thread.run(), Thread.wait(), 38 * Thread.exit(), Thread.yield() and ThreadGroup.remove() methods; 39 * - there is at least one element corresponding to invocation of unexpected 40 * method. 41 * This test is almost the same as nsk.stress.strace.strace001 and 42 * nsk.stress.strace.strace003 except for the recursive methods are 43 * pure java and native one. 44 * COMMENTS 45 * Below assertion is revealed on engineer's build. It is needed to check 46 * on a promoted build. 47 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 48 * waiting for all threads started ... 49 * Unexpected Signal : 11 occurred at PC=0xFDBB7820 50 * Function=[Unknown. Nearest: SUNWprivate_1.1+0x3B7820] 51 * Library=java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/client/libjvm.so 52 * Current Java thread: 53 * at nsk.stress.strace.strace005Thread.recursiveMethod2(Native Method) 54 * at nsk.stress.strace.strace005Thread.recursiveMethod1(strace005.java:285) 55 * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 * at nsk.stress.strace.strace005Thread.recursiveMethod2(Native Method) 57 * at nsk.stress.strace.strace005Thread.recursiveMethod1(strace005.java:285) 58 * at nsk.stress.strace.strace005Thread.recursiveMethod2(Native Method) 59 * Dynamic libraries: 60 * 0x10000 jdk/4593133/solaris-sparc/bin/java 61 * 0xff350000 /usr/lib/libthread.so.1 62 * 0xff390000 /usr/lib/libdl.so.1 63 * 0xff200000 /usr/lib/libc.so.1 64 * 0xff330000 /usr/platform/SUNW,Ultra-60/lib/libc_psr.so.1 65 * 0xfd800000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/client/libjvm.so 66 * 0xff2d0000 /usr/lib/libCrun.so.1 67 * 0xff1d0000 /usr/lib/libsocket.so.1 68 * 0xff100000 /usr/lib/libnsl.so.1 69 * 0xff0d0000 /usr/lib/libm.so.1 70 * 0xff0b0000 /usr/lib/libsched.so.1 71 * 0xff300000 /usr/lib/libw.so.1 72 * 0xff090000 /usr/lib/libmp.so.2 73 * 0xff050000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/native_threads/libhpi.so 74 * 0xfd7d0000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/libverify.so 75 * 0xfd790000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/libjava.so 76 * 0xfe7e0000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/libzip.so 77 * 0xfc6e0000 java/vitp/tests/4593133/src/libstrace005.so 78 * Heap at VM Abort: 79 * Heap 80 * def new generation total 2112K, used 336K [0xf1800000, 0xf1a20000, 0xf1f10000) 81 * eden space 2048K, 16% used [0xf1800000, 0xf1854300, 0xf1a00000) 82 * from space 64K, 0% used [0xf1a00000, 0xf1a00000, 0xf1a10000) 83 * to space 64K, 0% used [0xf1a10000, 0xf1a10000, 0xf1a20000) 84 * tenured generation total 1408K, used 0K [0xf1f10000, 0xf2070000, 0xf5800000) 85 * the space 1408K, 0% used [0xf1f10000, 0xf1f10000, 0xf1f10200, 0xf2070000) 86 * compacting perm gen total 4096K, used 1020K [0xf5800000, 0xf5c00000, 0xf9800000) 87 * the space 4096K, 24% used [0xf5800000, 0xf58ff028, 0xf58ff200, 0xf5c00000) 88 * Local Time = Fri Apr 25 18:09:16 2003 89 * Elapsed Time = 13 90 * # 91 * # HotSpot Virtual Machine Error : 11 92 * # Error ID : src/share/vm/runtime/os.cpp, 753 [ Patched ] 93 * # Please report this error at 94 * # http://java.sun.com/cgi-bin/bugreport.cgi 95 * # 96 * # Java VM: Java HotSpot(TM) Client VM (1.4.1-internal-debug mixed mode) 97 * # 98 * # An error report file has been saved as hs_err_pid16847.log. 99 * # Please refer to the file for further information. 100 * # 101 * Dumping core.... 102 * Abort 103 * Finished at: Fri Apr 25 18:09:17 NSK 2003 104 * 105 * @library /vmTestbase 106 * /test/lib 107 * @run driver jdk.test.lib.FileInstaller . . 108 * @run main/othervm/native nsk.stress.strace.strace005 109 */ 110 111 package nsk.stress.strace; 112 113 import nsk.share.ArgumentParser; 114 import nsk.share.Failure; 115 import nsk.share.Log; 116 117 import java.io.PrintStream; 118 119 /** 120 * The test checks up <code>java.lang.Thread.getStackTrace()</code> method for many threads, 121 * that recursively invoke pure java and native methods by turns in running mode 122 * ("alive" stack). 123 * <p> 124 * <p>The test creates <code>THRD_COUNT</code> instances of <code>strace005Thread</code> 125 * class, tries to get their stack traces and checks up that returned array contains 126 * correct stack frames. Each stack frame must be corresponded to one of the following 127 * methods defined by the <code>EXPECTED_METHODS</code> array.</p> 128 * <p>These checking are performed <code>REPEAT_COUNT</code> times.</p> 129 */ 130 public class strace005 { 131 132 static final int DEPTH = 500; 133 static final int THRD_COUNT = 100; 134 static final int REPEAT_COUNT = 10; 135 static final String[] EXPECTED_METHODS = { 136 "java.lang.System.arraycopy", 137 "java.lang.Object.wait", 138 "java.lang.Thread.exit", 139 "java.lang.Thread.yield", 140 "java.lang.ThreadGroup.remove", 141 "java.lang.ThreadGroup.threadTerminated", 142 "nsk.stress.strace.strace005Thread.run", 143 "nsk.stress.strace.strace005Thread.recursiveMethod1", 144 "nsk.stress.strace.strace005Thread.recursiveMethod2" 145 }; 146 147 148 static volatile boolean isLocked = false; 149 static PrintStream out; 150 static long waitTime = 2; 151 152 static Object waitStart = new Object(); 153 154 static strace005Thread[] threads; 155 static StackTraceElement[][] snapshots = new StackTraceElement[THRD_COUNT][]; 156 static Log log; 157 158 volatile int achivedCount = 0; 159 160 public static void main(String[] args) { 161 out = System.out; 162 int exitCode = run(args); 163 System.exit(exitCode + 95); 164 } 165 166 public static int run(String[] args) { 167 ArgumentParser argHandler = new ArgumentParser(args); 168 log = new Log(out, argHandler); 169 waitTime = argHandler.getWaitTime() * 60000; 170 171 strace005 test = new strace005(); 172 boolean res = true; 173 174 for (int j = 0; j < REPEAT_COUNT; j++) { 175 test.startThreads(); 176 177 if (!test.makeSnapshot(j + 1)) res = false; 178 179 display("waiting for threads finished\n"); 180 test.finishThreads(); 181 } 182 183 if (!res) { 184 complain("***>>>Test failed<<<***"); 185 return 2; 186 } 187 188 return 0; 189 } 190 191 void startThreads() { 192 threads = new strace005Thread[THRD_COUNT]; 193 achivedCount = 0; 194 195 String tmp_name; 196 for (int i = 0; i < THRD_COUNT; i++) { 197 tmp_name = "strace005Thread" + Integer.toString(i); 198 threads[i] = new strace005Thread(this, tmp_name); 199 // threads[i].setPriority(Thread.MIN_PRIORITY); 200 } 201 202 for (int i = 0; i < THRD_COUNT; i++) { 203 threads[i].start(); 204 } 205 206 waitFor("all threads started ..."); 207 synchronized (waitStart) { 208 isLocked = true; 209 waitStart.notifyAll(); 210 } 211 try { 212 Thread.yield(); 213 Thread.sleep(1); 214 } catch (InterruptedException e) { 215 complain("" + e); 216 } 217 } 218 219 void waitFor(String msg) { 220 if (msg.length() > 0) 221 display("waiting for " + msg); 222 223 while (achivedCount < THRD_COUNT) { 224 try { 225 Thread.sleep(1); 226 } catch (InterruptedException e) { 227 complain("" + e); 228 } 229 } 230 achivedCount = 0; 231 } 232 233 boolean makeSnapshot(int repeat_number) { 234 // wait for native resolution completed (all threads have finished recursiveMethod2) 235 boolean isNativeResolved = false; 236 while (!isNativeResolved) { 237 try { 238 isNativeResolved = true; 239 for (int i = 0; i < threads.length; ++i) 240 if (!threads[i].isNativeResolved) 241 isNativeResolved = false; 242 Thread.sleep(20); 243 } catch (InterruptedException e) { 244 throw new Error(e); 245 } 246 } 247 248 for (int i = 0; i < threads.length; i++) { 249 snapshots[i] = threads[i].getStackTrace(); 250 } 251 252 return checkTraces(repeat_number); 253 } 254 255 boolean checkTraces(int repeat_number) { 256 StackTraceElement[] elements; 257 258 boolean res = true; 259 display(">>> snapshot " + repeat_number); 260 int expectedCount = DEPTH + 1; 261 262 for (int i = 0; i < threads.length; i++) { 263 elements = snapshots[i]; 264 265 if (elements == null || elements.length == 0) 266 continue; 267 268 if (elements.length > 0) { 269 display("\tchecking " + threads[i].getName() 270 + "(trace elements: " + elements.length + ")"); 271 } 272 273 if (elements.length > expectedCount) { 274 complain(threads[i].getName() + ">Contains more then " + 275 +expectedCount + " elements"); 276 } 277 278 for (int j = 0; j < elements.length; j++) { 279 if (!checkElement(elements[j])) { 280 complain(threads[i].getName() + ">Unexpected method name: " 281 + elements[j].getMethodName()); 282 complain("\tat " + j + " position"); 283 if (elements[j].isNativeMethod()) { 284 complain("\tline number: (native method)"); 285 complain("\tclass name: " + elements[j].getClassName()); 286 } else { 287 complain("\tline number: " + elements[j].getLineNumber()); 288 complain("\tclass name: " + elements[j].getClassName()); 289 complain("\tfile name: " + elements[j].getFileName()); 290 } 291 res = false; 292 } 293 } 294 } 295 return res; 296 } 297 298 boolean checkElement(StackTraceElement element) { 299 String name = element.getClassName() + "." + element.getMethodName(); 300 for (int i = 0; i < EXPECTED_METHODS.length; i++) { 301 if (EXPECTED_METHODS[i].compareTo(name) == 0) 302 return true; 303 } 304 return false; 305 } 306 307 void finishThreads() { 308 try { 309 for (int i = 0; i < threads.length; i++) { 310 if (threads[i].isAlive()) 311 threads[i].join(waitTime / THRD_COUNT); 312 } 313 } catch (InterruptedException e) { 314 complain("" + e); 315 } 316 isLocked = false; 317 } 318 319 static void display(String message) { 320 log.display(message); 321 } 322 323 static void complain(String message) { 324 log.complain(message); 325 } 326 327 } 328 329 /** 330 * The test creates many instances of <code>strace005Thread</code> class and tries 331 * to get their stack traces. 332 */ 333 class strace005Thread extends Thread { 334 335 private int currentDepth = 0; 336 public boolean isNativeResolved = false; 337 338 strace005 test; 339 340 static { 341 try { 342 System.loadLibrary("strace005"); 343 } catch (UnsatisfiedLinkError e) { 344 System.err.println("Could not load strace005 library"); 345 System.err.println("java.library.path:" 346 + System.getProperty("java.library.path")); 347 throw e; 348 } 349 } 350 351 strace005Thread(strace005 test, String name) { 352 this.test = test; 353 setName(name); 354 } 355 356 public void run() { 357 358 recursiveMethod1(); 359 360 } 361 362 void recursiveMethod1() { 363 364 currentDepth++; 365 366 if (currentDepth == 1) { 367 synchronized (test) { 368 test.achivedCount++; 369 } 370 371 int alltime = 0; 372 while (!strace005.isLocked) { 373 synchronized (test) { 374 try { 375 test.wait(1); 376 alltime++; 377 } catch (InterruptedException e) { 378 strace005.complain("" + e); 379 } 380 if (alltime > strace005.waitTime) { 381 throw new Failure("out of wait time"); 382 } 383 } 384 } 385 } else if (currentDepth > 1 && !isNativeResolved) 386 isNativeResolved = true; 387 388 if (strace005.DEPTH - currentDepth > 0) { 389 try { 390 yield(); 391 recursiveMethod2(); 392 } catch (StackOverflowError e) { 393 // ignore this exception 394 } 395 } 396 397 currentDepth--; 398 } 399 400 native void recursiveMethod2(); 401 }