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 /* 26 * @test 27 * @key stress 28 * 29 * @summary converted from VM testbase nsk/stress/strace/strace002. 30 * VM testbase keywords: [stress, quick, strace] 31 * VM testbase readme: 32 * DESCRIPTION 33 * The test checks up java.lang.Thread.getAllStackTraces() method for many 34 * threads, that recursively invoke a pure java method in running mode 35 * ("alive" stack). 36 * The test fails if: 37 * - amount of stack trace elements is more than depth of recursion plus 38 * four elements corresponding to invocations of Thread.run(), Thread.wait(), 39 * Thread.exit(), Thread.yield() and ThreadGroup.remove() methods; 40 * - there is at least one element corresponding to invocation of unexpected 41 * method. 42 * This test is almost the same as nsk.stress.strace.strace001 except for 43 * checking is performed for java.lang.Thread.getAllStackTraces() method. 44 * 45 * @library /vmTestbase 46 * /test/lib 47 * @run driver jdk.test.lib.FileInstaller . . 48 * @run main/othervm nsk.stress.strace.strace002 49 */ 50 51 52 package nsk.stress.strace; 53 54 import nsk.share.ArgumentParser; 55 import nsk.share.Failure; 56 import nsk.share.Log; 57 58 import java.io.PrintStream; 59 import java.util.Map; 60 61 /** 62 * The test check up <code>java.lang.Thread.getAllStackTraces()</code> method for many 63 * threads, that recursively invoke a pure java method in running mode ("alive" stack). 64 * <p> 65 * <p>The test creates <code>THRD_COUNT</code> instances of <code>strace002Thread</code> 66 * class, tries to get their stack traces and checks up that returned array contains 67 * correct stack frames. Each stack frame must be corresponded to one of the following 68 * methods defined by the <code>EXPECTED_METHODS</code> array.</p> 69 * <p>These checking are performed <code>REPEAT_COUNT</code> times.</p> 70 */ 71 public class strace002 { 72 73 static final int DEPTH = 200; 74 static final int THRD_COUNT = 100; 75 static final int REPEAT_COUNT = 10; 76 static final String[] EXPECTED_METHODS = { 77 "java.lang.System.arraycopy", 78 "java.lang.Object.wait", 79 "java.lang.Thread.exit", 80 "java.lang.Thread.yield", 81 "java.lang.ThreadGroup.remove", 82 "java.lang.ThreadGroup.threadTerminated", 83 "nsk.stress.strace.strace002Thread.run", 84 "nsk.stress.strace.strace002Thread.recursiveMethod" 85 }; 86 87 88 static volatile boolean isLocked = false; 89 static PrintStream out; 90 static long waitTime = 2; 91 92 static Object waitStart = new Object(); 93 94 static strace002Thread[] threads; 95 static StackTraceElement[][] snapshots = new StackTraceElement[THRD_COUNT][]; 96 static Log log; 97 98 public static void main(String[] args) { 99 out = System.out; 100 int exitCode = run(args); 101 System.exit(exitCode + 95); 102 } 103 104 volatile int achivedCount = 0; 105 106 public static int run(String[] args) { 107 108 ArgumentParser argHandler = new ArgumentParser(args); 109 log = new Log(out, argHandler); 110 waitTime = argHandler.getWaitTime() * 60000; 111 112 strace002 test = new strace002(); 113 boolean res = true; 114 115 for (int j = 0; j < REPEAT_COUNT; j++) { 116 test.startThreads(); 117 118 if (!test.makeSnapshot(j + 1)) res = false; 119 120 display("waiting for threads finished\n"); 121 test.finishThreads(); 122 } 123 124 if (!res) { 125 complain("***>>>Test failed<<<***"); 126 return 2; 127 } 128 129 return 0; 130 } 131 132 void startThreads() { 133 threads = new strace002Thread[THRD_COUNT]; 134 achivedCount = 0; 135 136 String tmp_name; 137 for (int i = 0; i < THRD_COUNT; i++) { 138 tmp_name = "strace002Thread" + Integer.toString(i); 139 threads[i] = new strace002Thread(this, tmp_name); 140 } 141 142 for (int i = 0; i < THRD_COUNT; i++) { 143 threads[i].start(); 144 } 145 146 waitFor("all threads started ..."); 147 synchronized (waitStart) { 148 isLocked = true; 149 waitStart.notifyAll(); 150 } 151 try { 152 Thread.yield(); 153 Thread.sleep(1); 154 } catch (InterruptedException e) { 155 complain("" + e); 156 } 157 } 158 159 void waitFor(String msg) { 160 if (msg.length() > 0) 161 display("waiting for " + msg); 162 163 while (achivedCount < THRD_COUNT) { 164 try { 165 Thread.sleep(1); 166 } catch (InterruptedException e) { 167 complain("" + e); 168 } 169 } 170 achivedCount = 0; 171 } 172 173 boolean makeSnapshot(int repeat_number) { 174 175 Map traces = Thread.getAllStackTraces(); 176 for (int i = 0; i < threads.length; i++) { 177 snapshots[i] = (StackTraceElement[]) traces.get(threads[i]); 178 } 179 180 return checkTraces(repeat_number); 181 } 182 183 boolean checkTraces(int repeat_number) { 184 StackTraceElement[] elements; 185 186 boolean res = true; 187 display(">>> snapshot " + repeat_number); 188 int expectedCount = DEPTH + 1; 189 190 for (int i = 0; i < threads.length; i++) { 191 elements = snapshots[i]; 192 193 if (elements == null) 194 continue; 195 196 if (elements.length == 0) 197 continue; 198 199 if (elements.length > 3) { 200 display("\tchecking " + threads[i].getName() 201 + "(trace elements: " + elements.length + ")"); 202 } 203 204 if (elements.length > expectedCount) { 205 complain(threads[i].getName() + ">Contains more then " + 206 +expectedCount + " elements"); 207 } 208 209 for (int j = 0; j < elements.length; j++) { 210 if (!checkElement(elements[j])) { 211 complain(threads[i].getName() + ">Unexpected method name: " 212 + elements[j].getMethodName()); 213 complain("\tat " + j + " position"); 214 if (elements[j].isNativeMethod()) { 215 complain("\tline number: (native method)"); 216 complain("\tclass name: " + elements[j].getClassName()); 217 } else { 218 complain("\tline number: " + elements[j].getLineNumber()); 219 complain("\tclass name: " + elements[j].getClassName()); 220 complain("\tfile name: " + elements[j].getFileName()); 221 } 222 res = false; 223 } 224 } 225 } 226 return res; 227 } 228 229 boolean checkElement(StackTraceElement element) { 230 String name = element.getClassName() + "." + element.getMethodName(); 231 for (int i = 0; i < EXPECTED_METHODS.length; i++) { 232 if (EXPECTED_METHODS[i].compareTo(name) == 0) 233 return true; 234 } 235 return false; 236 } 237 238 void finishThreads() { 239 try { 240 for (int i = 0; i < threads.length; i++) { 241 if (threads[i].isAlive()) 242 threads[i].join(waitTime / THRD_COUNT); 243 } 244 } catch (InterruptedException e) { 245 complain("" + e); 246 } 247 isLocked = false; 248 } 249 250 static void display(String message) { 251 log.display(message); 252 } 253 254 static void complain(String message) { 255 log.complain(message); 256 } 257 258 259 } 260 261 class strace002Thread extends Thread { 262 263 private int currentDepth = 0; 264 265 strace002 test; 266 267 strace002Thread(strace002 test, String name) { 268 this.test = test; 269 setName(name); 270 } 271 272 public void run() { 273 try { 274 recursiveMethod(); 275 } catch (Throwable throwable) { 276 System.err.println("# ERROR: " + getName() + ": " + throwable); 277 System.exit(1); 278 } 279 } 280 281 void recursiveMethod() { 282 283 currentDepth++; 284 285 if (currentDepth == 1) { 286 synchronized (test) { 287 test.achivedCount++; 288 } 289 290 int alltime = 0; 291 while (!test.isLocked) { 292 synchronized (test) { 293 try { 294 test.wait(1); 295 alltime++; 296 } catch (InterruptedException e) { 297 strace002.complain("" + e); 298 } 299 if (alltime > strace002.waitTime) { 300 throw new Failure("out of wait time"); 301 } 302 } 303 } 304 } 305 306 if (strace002.DEPTH - currentDepth > 0) { 307 Thread.yield(); 308 recursiveMethod(); 309 } 310 311 currentDepth--; 312 } 313 }