alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (ThreadStackTrace.java)

This example Java source code file (ThreadStackTrace.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

blockedthread, examiner, exception, failed, indent, interruptedexception, management, object, runtimeexception, semaphore, stacktraceelement, string, test, threadinfo, threadstacktrace

The ThreadStackTrace.java Java example source code

/*
 * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug     4530538
 * @summary Basic unit test of ThreadInfo.getStackTrace() and
 *          ThreadInfo.getThreadState()
 * @author  Mandy Chung
 *
 * @run build Semaphore Utils
 * @run main ThreadStackTrace
 */

import java.lang.management.*;

public class ThreadStackTrace {
    private static ThreadMXBean mbean
        = ManagementFactory.getThreadMXBean();
    private static boolean notified = false;
    private static Object lockA = new Object();
    private static Object lockB = new Object();
    private static volatile boolean testFailed = false;
    private static String[] blockedStack = {"run", "test", "A", "B", "C", "D"};
    private static int bsDepth = 6;
    private static int methodB = 4;
    private static String[] examinerStack = {"run", "examine1", "examine2"};
    private static int esDepth = 3;
    private static int methodExamine1= 2;

    private static void checkNullThreadInfo(Thread t) throws Exception {
        ThreadInfo ti = mbean.getThreadInfo(t.getId());
        if (ti != null) {
            ThreadInfo info =
                mbean.getThreadInfo(t.getId(), Integer.MAX_VALUE);
            System.out.println(INDENT + "TEST FAILED:");
            if (info != null) {
                printStack(t, info.getStackTrace());
                System.out.println(INDENT + "Thread state: " + info.getThreadState());
            }
            throw new RuntimeException("TEST FAILED: " +
                "getThreadInfo() is expected to return null for " + t);
        }
    }

    private static boolean trace = false;
    public static void main(String args[]) throws Exception {
        if (args.length > 0 && args[0].equals("trace")) {
            trace = true;
        }

        Examiner examiner = new Examiner("Examiner");
        BlockedThread blocked = new BlockedThread("BlockedThread");
        examiner.setThread(blocked);

        checkNullThreadInfo(examiner);
        checkNullThreadInfo(blocked);

        // Start the threads and check them in  Blocked and Waiting states
        examiner.start();

        // block until examiner begins doing its real work
        examiner.waitForStarted();

        System.out.println("Checking stack trace for the examiner thread " +
                           "is waiting to begin.");

        // The Examiner should be waiting to be notified by the BlockedThread
        Utils.checkThreadState(examiner, Thread.State.WAITING);

        // Check that the stack is returned correctly for a new thread
        checkStack(examiner, examinerStack, esDepth);

        System.out.println("Now starting the blocked thread");
        blocked.start();

        try {
            examiner.join();
            blocked.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("Unexpected exception.");
            testFailed = true;
        }

        // Check that the stack is returned correctly for a terminated thread
        checkNullThreadInfo(examiner);
        checkNullThreadInfo(blocked);

        if (testFailed)
            throw new RuntimeException("TEST FAILED.");

        System.out.println("Test passed.");
    }

    private static String INDENT = "    ";
    private static void printStack(Thread t, StackTraceElement[] stack) {
        System.out.println(INDENT +  t +
                           " stack: (length = " + stack.length + ")");
        if (t != null) {
            for (int j = 0; j < stack.length; j++) {
                System.out.println(INDENT + stack[j]);
            }
            System.out.println();
        }
    }

    private static void checkStack(Thread t, String[] expectedStack,
                                   int depth) throws Exception {
        ThreadInfo ti = mbean.getThreadInfo(t.getId(), Integer.MAX_VALUE);
        StackTraceElement[] stack = ti.getStackTrace();

        if (trace) {
            printStack(t, stack);
        }
        int frame = stack.length - 1;
        for (int i = 0; i < depth; i++) {
            if (! stack[frame].getMethodName().equals(expectedStack[i])) {
                throw new RuntimeException("TEST FAILED: " +
                    "Expected " + expectedStack[i] + " in frame " + frame +
                    " but got " + stack[frame].getMethodName());
            }
            frame--;
        }
    }

    static class BlockedThread extends Thread {
        private Semaphore handshake = new Semaphore();

        BlockedThread(String name) {
            super(name);
        }
        boolean hasWaitersForBlocked() {
            return (handshake.getWaiterCount() > 0);
        }

        void waitUntilBlocked() {
            handshake.semaP();

            // give a chance for the examiner thread to really wait
            Utils.goSleep(20);
        }

        void waitUntilLockAReleased() {
            handshake.semaP();

            // give a chance for the examiner thread to really wait
            Utils.goSleep(50);
        }

        private void notifyWaiter() {
            // wait until the examiner waits on the semaphore
            while (handshake.getWaiterCount() == 0) {
                Utils.goSleep(20);
            }
            handshake.semaV();
        }

        private void test() {
            A();
        }
        private void A() {
            B();
        }
        private void B() {
            C();

            // notify the examiner about to block on lockB
            notifyWaiter();

            synchronized (lockB) {
            };
        }
        private void C() {
            D();
        }
        private void D() {
            // Notify that examiner about to enter lockA
            notifyWaiter();

            synchronized (lockA) {
                notified = false;
                while (!notified) {
                    try {
                        // notify the examiner about to release lockA
                        notifyWaiter();
                        // Wait and let examiner thread check the mbean
                        lockA.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println("Unexpected exception.");
                        testFailed = true;
                    }
                }
                System.out.println("BlockedThread notified");
            }
        }

        public void run() {
            test();
        } // run()
    } // BlockedThread

    static class Examiner extends Thread {
        private static BlockedThread blockedThread;
        private Semaphore handshake = new Semaphore();

        Examiner(String name) {
            super(name);
        }

        public void setThread(BlockedThread thread) {
            blockedThread = thread;
        }

        public synchronized void waitForStarted() {
            // wait until the examiner is about to block
            handshake.semaP();

            // wait until the examiner is waiting for blockedThread's notification
            while (!blockedThread.hasWaitersForBlocked()) {
                Utils.goSleep(50);
            }
            // give a chance for the examiner thread to really wait
            Utils.goSleep(20);
        }

        private Thread itself;
        private void examine1() {
            synchronized (lockB) {
                examine2();
                try {
                    System.out.println("Checking examiner's its own stack trace");
                    Utils.checkThreadState(itself, Thread.State.RUNNABLE);
                    checkStack(itself, examinerStack, methodExamine1);

                    // wait until blockedThread is blocked on lockB
                    blockedThread.waitUntilBlocked();

                    System.out.println("Checking stack trace for " +
                        "BlockedThread - should be blocked on lockB.");
                    Utils.checkThreadState(blockedThread, Thread.State.BLOCKED);
                    checkStack(blockedThread, blockedStack, methodB);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("Unexpected exception.");
                    testFailed = true;
                }
            }
        }

        private void examine2() {
            synchronized (lockA) {
                // wait until main thread gets signalled of the semaphore
                while (handshake.getWaiterCount() == 0) {
                    Utils.goSleep(20);
                }

                handshake.semaV();  // notify the main thread
                try {
                    // Wait until BlockedThread is about to block on lockA
                    blockedThread.waitUntilBlocked();

                    System.out.println("Checking examiner's its own stack trace");
                    Utils.checkThreadState(itself, Thread.State.RUNNABLE);
                    checkStack(itself, examinerStack, esDepth);

                    System.out.println("Checking stack trace for " +
                        "BlockedThread - should be blocked on lockA.");
                    Utils.checkThreadState(blockedThread, Thread.State.BLOCKED);
                    checkStack(blockedThread, blockedStack, bsDepth);

                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("Unexpected exception.");
                    testFailed = true;
                }
            }

            // release lockA and let BlockedThread to get the lock
            // and wait on lockA
            blockedThread.waitUntilLockAReleased();

            synchronized (lockA) {
                try {
                    System.out.println("Checking stack trace for " +
                        "BlockedThread - should be waiting on lockA.");
                    Utils.checkThreadState(blockedThread, Thread.State.WAITING);
                    checkStack(blockedThread, blockedStack, bsDepth);

                    // Let the blocked thread go
                    notified = true;
                    lockA.notify();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("Unexpected exception.");
                    testFailed = true;
                }
            }
            // give some time for BlockedThread to proceed
            Utils.goSleep(50);
        } // examine2()

        public void run() {
            itself = Thread.currentThread();
            examine1();
        } // run()
    } // Examiner
}

Other Java examples (source code examples)

Here is a short list of links related to this Java ThreadStackTrace.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.