Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace013.java
41155 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @key stress26*27* @summary converted from VM testbase nsk/stress/strace/strace013.28* VM testbase keywords: [stress, quick, strace, quarantine]29* VM testbase comments: 801595030* VM testbase readme:31* DESCRIPTION32* The test runs many threads, that recursively invoke a pure java method.33* After arriving at defined depth of recursion, each thread is switched to34* waits for a monitor. Then the test calls java.lang.Thread.getStackTrace()35* and java.lang.Thread.getAllStackTraces() methods and checks their results.36* The test fails if:37* - amount of stack trace elements and stack trace elements themselves are38* the same for both methods;39* - there is at least one element corresponding to invocation of unexpected40* method. Expected methods are Thread.sleep(), Thread.run() and the41* recursive method.42*43* @library /vmTestbase44* /test/lib45* @run main/othervm nsk.stress.strace.strace01346*/4748package nsk.stress.strace;4950import nsk.share.ArgumentParser;51import nsk.share.Log;5253import java.io.PrintStream;54import java.util.Map;5556/**57* The test runs <code>THRD_COUNT</code> instances of <code>strace010Thread</code>,58* that recursively invoke a pure java method. After arriving at defined depth59* <code>DEPTH</code> of recursion, each thread is switched to wait a monitor.60* Then the test calls <code>java.lang.Thread.getStackTrace()</code> and61* <code>java.lang.Thread.getAllStackTraces()</code> methods and checks their results.62* <p>63* <p>It is expected that these methods return the same stack traces. Each stack frame64* for both stack traces must be corresponded to invocation of one of the methods65* defined by the <code>EXPECTED_METHODS</code> array.</p>66*/67public class strace013 {6869static final int DEPTH = 200;70static final int THRD_COUNT = 100;71static final String[] EXPECTED_METHODS = {72"java.lang.Object.wait",73"nsk.stress.strace.strace013Thread.run",74"nsk.stress.strace.strace013Thread.recursiveMethod"75};767778static PrintStream out;79static long waitTime = 2;8081static Object lockedObject = new Object();8283volatile int achivedCount = 0;84strace013Thread[] threads;85static Log log;8687public static void main(String[] args) {88out = System.out;89int exitCode = run(args);90System.exit(exitCode + 95);91}9293public static int run(String[] args) {94ArgumentParser argHandler = new ArgumentParser(args);95log = new Log(out, argHandler);96waitTime = argHandler.getWaitTime() * 60000;9798strace013 test = new strace013();99boolean res = true;100101test.startThreads();102103res = test.makeSnapshot();104105test.finishThreads();106107if (!res) {108complain("***>>>Test failed<<<***");109return 2;110}111112display(">>>Test passed<<<");113return 0;114}115116void startThreads() {117threads = new strace013Thread[THRD_COUNT];118achivedCount = 0;119120String tmp_name;121display("starting threads...");122for (int i = 0; i < THRD_COUNT; i++) {123tmp_name = "strace013Thread" + Integer.toString(i);124threads[i] = new strace013Thread(this, tmp_name);125threads[i].start();126}127128waitFor("the defined recursion depth ...");129}130131void waitFor(String msg) {132if (msg.length() > 0)133display("waiting for " + msg);134135while (achivedCount < THRD_COUNT) {136try {137Thread.sleep(1);138} catch (InterruptedException e) {139complain("" + e);140}141}142achivedCount = 0;143}144145boolean makeSnapshot() {146147Map traces = null;148int count = 0;149StackTraceElement[][] elements = null;150151display("making all threads snapshots...");152traces = Thread.getAllStackTraces();153count = ((StackTraceElement[]) traces.get(threads[0])).length;154155display("making snapshots of each thread...");156elements = new StackTraceElement[THRD_COUNT][];157for (int i = 0; i < THRD_COUNT; i++) {158elements[i] = threads[i].getStackTrace();159}160161display("notifying");162synchronized (strace013.lockedObject) {163strace013.lockedObject.notifyAll();164}165166display("");167168display("checking lengths of stack traces...");169StackTraceElement[] all;170for (int i = 1; i < THRD_COUNT; i++) {171all = (StackTraceElement[]) traces.get(threads[i]);172int k = all.length;173if (count - k > 2) {174complain("wrong lengths of stack traces:\n\t"175+ threads[0].getName() + ": " + count176+ "\t"177+ threads[i].getName() + ": " + k);178return false;179}180}181182display("checking stack traces...");183boolean res = true;184for (int i = 0; i < THRD_COUNT; i++) {185all = (StackTraceElement[]) traces.get(threads[i]);186if (!checkTraces(threads[i].getName(), elements[i], all)) {187res = false;188}189}190return res;191}192193boolean checkTraces(String threadName, StackTraceElement[] threadSnap,194StackTraceElement[] allSnap) {195196int checkedLength = threadSnap.length < allSnap.length ?197threadSnap.length : allSnap.length;198boolean res = true;199200for (int j = 0; j < checkedLength; j++) {201if (!checkElement(threadSnap[j])) {202complain("Unexpected " + j + "-element:");203complain("\tmethod name: " + threadSnap[j].getMethodName());204complain("\tclass name: " + threadSnap[j].getClassName());205if (threadSnap[j].isNativeMethod()) {206complain("\tline number: (native method)");207} else {208complain("\tline number: " + threadSnap[j].getLineNumber());209complain("\tfile name: " + threadSnap[j].getFileName());210}211complain("");212res = false;213}214}215return res;216}217218boolean checkElement(StackTraceElement element) {219String name = element.getClassName() + "." + element.getMethodName();220for (int i = 0; i < EXPECTED_METHODS.length; i++) {221if (EXPECTED_METHODS[i].compareTo(name) == 0)222return true;223}224return false;225}226227void finishThreads() {228try {229for (int i = 0; i < threads.length; i++) {230if (threads[i].isAlive()) {231display("waiting for finish " + threads[i].getName());232threads[i].join(waitTime);233}234}235} catch (InterruptedException e) {236complain("" + e);237}238}239240static void display(String message) {241log.display(message);242}243244static void complain(String message) {245log.complain(message);246}247248}249250class strace013Thread extends Thread {251252private int currentDepth = 0;253254static int[] arr = new int[1000];255strace013 test;256257strace013Thread(strace013 test, String name) {258this.test = test;259setName(name);260}261262public void run() {263try {264recursiveMethod(arr);265} catch (Throwable throwable) {266System.err.println("# ERROR: " + getName() + ": " + throwable);267System.exit(1);268}269}270271void recursiveMethod(int[] arr) {272currentDepth++;273274if (strace013.DEPTH - currentDepth > 0) {275recursiveMethod(arr);276}277278if (strace013.DEPTH == currentDepth) {279280strace013.display(getName() + ">waiting on a monitor");281282synchronized (test) {283test.achivedCount++;284}285286synchronized (strace013.lockedObject) {287try {288strace013.lockedObject.wait();289} catch (InterruptedException e) {290strace013.complain("" + e);291}292}293strace013.display(getName() + ">notified");294}295296currentDepth--;297}298}299300301