Path: blob/master/test/hotspot/jtreg/serviceability/tmtools/jstack/WaitNotifyThreadTest.java
41153 views
/*1* Copyright (c) 2015, 2018, 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* @summary Call Object.wait() method. Check that monitor information26* presented in the stack is correct. Call notifyAll method27* monitor info have to disappear from the stack.28* Repeats the same scenario calling interrupt() method29* @modules java.base/jdk.internal.misc30* @library /test/lib31* @library ../share32* @run main/othervm -XX:+UsePerfData WaitNotifyThreadTest33*/34import common.ToolResults;35import java.util.Iterator;36import utils.*;3738public class WaitNotifyThreadTest {3940private Object monitor = new Object();41private final String OBJECT = "a java.lang.Object";42private final String OBJECT_WAIT = "java.lang.Object.wait";43private final String RUN_METHOD = "WaitNotifyThreadTest$WaitThread.run";4445interface Action {46void doAction(Thread thread);47}4849class ActionNotify implements Action {5051@Override52public void doAction(Thread thread) {53// Notify the waiting thread, so it stops waiting and sleeps54synchronized (monitor) {55monitor.notifyAll();56}57// Wait until MyWaitingThread exits the monitor and sleeps58while (thread.getState() != Thread.State.TIMED_WAITING) {}59}60}6162class ActionInterrupt implements Action {6364@Override65public void doAction(Thread thread) {66// Interrupt the thread67thread.interrupt();68// Wait until MyWaitingThread exits the monitor and sleeps69while (thread.getState() != Thread.State.TIMED_WAITING) {}70}71}7273class WaitThread extends Thread {7475@Override76public void run() {77try {78synchronized (monitor) {79monitor.wait();80}81} catch (InterruptedException x) {8283}84Utils.sleep();85}86}8788public static void main(String[] args) throws Exception {89new WaitNotifyThreadTest().doTest();90}9192private void doTest() throws Exception {9394// Verify stack trace consistency when notifying the thread95doTest(new ActionNotify());9697// Verify stack trace consistency when interrupting the thread98doTest(new ActionInterrupt());99}100101private void doTest(Action action) throws Exception {102103final String WAITING_THREAD_NAME = "MyWaitingThread";104105// Start a thread that just waits106WaitThread waitThread = new WaitThread();107waitThread.setName(WAITING_THREAD_NAME);108waitThread.start();109// Wait until MyWaitingThread enters the monitor110while (waitThread.getState() != Thread.State.WAITING) {}111112// Collect output from the jstack tool113JstackTool jstackTool = new JstackTool(ProcessHandle.current().pid());114ToolResults results = jstackTool.measure();115116// Analyze the jstack output for the patterns needed117JStack jstack1 = new DefaultFormat().parse(results.getStdoutString());118ThreadStack ti1 = jstack1.getThreadStack(WAITING_THREAD_NAME);119analyzeThreadStackWaiting(ti1);120121action.doAction(waitThread);122123// Collect output from the jstack tool again124results = jstackTool.measure();125126// Analyze the output again127JStack jstack2 = new DefaultFormat().parse(results.getStdoutString());128ThreadStack ti2 = jstack2.getThreadStack(WAITING_THREAD_NAME);129analyzeThreadStackNoWaiting(ti2);130}131132private void analyzeThreadStackWaiting(ThreadStack ti1) {133Iterator<MethodInfo> it = ti1.getStack().iterator();134135String monitorAddress = null;136while (it.hasNext()) {137MethodInfo mi = it.next();138if (mi.getName().startsWith(OBJECT_WAIT) && mi.getCompilationUnit() == null /*native method*/) {139if (mi.getLocks().size() == 1) {140MonitorInfo monInfo = mi.getLocks().getFirst();141monitorAddress = monInfo.getMonitorAddress();142assertMonitorInfo("waiting on", monInfo, monitorAddress, OBJECT_WAIT);143} else {144throw new RuntimeException(OBJECT_WAIT + " method has to contain one lock record but it contains "145+ mi.getLocks().size());146}147}148149if (mi.getName().startsWith(RUN_METHOD)) {150if (monitorAddress == null) {151throw new RuntimeException("Cannot found monitor info associated with " + OBJECT_WAIT + " method");152}153if (mi.getLocks().size() == 1) {154MonitorInfo monInfo = mi.getLocks().getLast();155if (monitorAddress.equals("no object reference available")) {156monitorAddress = monInfo.getMonitorAddress();157}158assertMonitorInfo("locked", monInfo, monitorAddress, RUN_METHOD);159}160else {161throw new RuntimeException(RUN_METHOD + " method has to contain one lock record but it contains "162+ mi.getLocks().size());163}164}165}166}167168private void assertMonitorInfo(String expectedMessage, MonitorInfo monInfo, String monitorAddress, String method) {169if (monInfo.getType().equals(expectedMessage)170&& compareMonitorClass(monInfo)171&& monInfo.getMonitorAddress().equals(172monitorAddress)) {173System.out.println("Correct monitor info found in " + method + " method");174} else {175System.err.println("Error: incorrect monitor info: " + monInfo.getType() + ", " + monInfo.getMonitorClass() + ", " + monInfo.getMonitorAddress());176System.err.println("Expected: " + expectedMessage + ", a java.lang.Object, " + monitorAddress);177throw new RuntimeException("Incorrect lock record in " + method + " method");178}179}180181private boolean compareMonitorClass(MonitorInfo monInfo) {182// If monitor class info is present in the jstack output183// then compare it with the class of the actual monitor object184// If there is no monitor class info available then return true185return OBJECT.equals(monInfo.getMonitorClass()) || (monInfo.getMonitorClass() == null);186}187188private void analyzeThreadStackNoWaiting(ThreadStack ti2) {189Iterator<MethodInfo> it = ti2.getStack().iterator();190191while (it.hasNext()) {192MethodInfo mi = it.next();193if (mi.getLocks().size() != 0) {194throw new RuntimeException("Unexpected lock record in "195+ mi.getName() + " method");196}197}198}199200}201202203