/* * Copyright (c) 2003, 2021, 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. */ package nsk.jvmti.PopFrame; import java.io.*; /** * This test checks that the JVMTI function PopFrame() * correctly returns the following errors: *
  • JVMTI_ERROR_NULL_POINTER *
  • JVMTI_ERROR_INVALID_THREAD *
  • JVMTI_ERROR_THREAD_NOT_SUSPENDED
    * and no JVMTI events will be generated by the function.
    * The test creates an instance of inner class popFrameCls * and start it in a separate thread. Then the test tries to pop frame * with the following erroneous thread's parameter of the * PopFrame(): *
  • NULL pointer to the thread *
  • an invalid thread *
  • the non suspended popFrameCls' thread

    * The test was changed due to the bug 4448675. */ public class popframe011 { private final static String AGENT_LIB = "popframe011"; private final static int DEF_TIME_MAX = 30; // default max # secs to test static final int PASSED = 0; static final int FAILED = 2; static final int JCK_STATUS_BASE = 95; static boolean DEBUG_MODE = false; static volatile boolean popFdone = false; static volatile int totRes = PASSED; private PrintStream out; private popFrameCls popFrameClsThr; static Object readi = new Object(); // for notification about readiness static Object barrier = new Object(); // for suspending a child thread static { try { System.loadLibrary(AGENT_LIB); } catch (UnsatisfiedLinkError e) { System.err.println("Could not load " + AGENT_LIB + " library"); System.err.println("java.library.path:" + System.getProperty("java.library.path")); throw e; } } native static int doPopFrame(int t_case, popFrameCls popFrameClsThr); native static boolean isThreadNotAliveError(); public static void main(String[] argv) { argv = nsk.share.jvmti.JVMTITest.commonInit(argv); System.exit(run(argv, System.out) + JCK_STATUS_BASE); } public static int run(String argv[], PrintStream out) { return new popframe011().runIt(argv, out); } private int runIt(String argv[], PrintStream out) { int timeMax = 0; if (argv.length == 0) { timeMax = DEF_TIME_MAX; } else { int argIndex = 0; int argvLeft = argv.length; if (argv[0].equals("-v")) { DEBUG_MODE = true; argIndex = 1; argvLeft--; } if (argvLeft == 0) { timeMax = DEF_TIME_MAX; } else if (argvLeft == 1) { try { timeMax = Integer.parseUnsignedInt(argv[argIndex]); } catch (NumberFormatException nfe) { System.err.println("'" + argv[argIndex] + "': invalid timeMax value."); usage(); } } else { usage(); } } System.out.println("About to execute for " + timeMax + " seconds."); // Original popframe002 test block starts here: // int retValue = 0; this.out = out; long count = 0; long start_time = System.currentTimeMillis(); while (System.currentTimeMillis() < start_time + (timeMax * 1000)) { count++; popFdone = false; popFrameClsThr = new popFrameCls(); synchronized (barrier) { // force a child thread to pause synchronized(readi) { popFrameClsThr.start(); // start the child thread // wait until the thread will enter into a necessary method try { readi.wait(); // wait for the child readiness } catch (Exception e) { out.println("TEST FAILURE: waiting for " + popFrameClsThr.toString() + ": caught " + e); return FAILED; } } /* check that if PopFrame() would be invoked with NULL pointer to the thread, it will return the error JVMTI_ERROR_NULL_POINTER */ if (DEBUG_MODE) totRes = retValue = doPopFrame(1, popFrameClsThr); else totRes = retValue = doPopFrame(0, popFrameClsThr); if (DEBUG_MODE && retValue == PASSED) out.println("Check #1 PASSED:\n" + "\tPopFrame(), being invoked with NULL pointer " + "to the thread,\n" + "\treturned the appropriate error JVMTI_ERROR_NULL_POINTER"); /* check that if the thread, whose top frame is to be popped, is invalid, the PopFrame() will return the error JVMTI_ERROR_INVALID_THREAD */ if (DEBUG_MODE) retValue = doPopFrame(3, popFrameClsThr); else retValue = doPopFrame(2, popFrameClsThr); if (retValue == FAILED) { popFdone = true; totRes = FAILED; } else if (DEBUG_MODE && retValue == PASSED) out.println("Check #3 PASSED:\n" + "\tPopFrame(), being invoked with " + "the invalid thread,\n" + "\treturned the appropriate error " + "JVMTI_ERROR_INVALID_THREAD"); /* check that if the thread, whose top frame is to be popped, has not been suspended, the PopFrame() will return the error JVMTI_ERROR_THREAD_NOT_SUSPENDED */ if (DEBUG_MODE) retValue = doPopFrame(5, popFrameClsThr); else retValue = doPopFrame(4, popFrameClsThr); if (retValue == FAILED) { popFdone = true; totRes = FAILED; } else if (DEBUG_MODE && retValue == PASSED) out.println("Check #5 PASSED:\n" + "\tPopFrame(), being invoked with " + "the non suspended thread,\n" + "\treturned the appropriate error " + "JVMTI_ERROR_THREAD_NOT_SUSPENDED"); } // // Original popframe002 test block ends here. while (true) { /* check that if the thread, whose top frame is to be popped, has not been suspended and is exiting, the PopFrame() will return the error JVMTI_ERROR_THREAD_NOT_SUSPENDED or JVMTI_ERROR_THREAD_NOT_ALIVE */ if (DEBUG_MODE) retValue = doPopFrame(7, popFrameClsThr); else retValue = doPopFrame(6, popFrameClsThr); if (retValue == FAILED) { popFdone = true; totRes = FAILED; } else if (DEBUG_MODE && retValue == PASSED) out.println("Check #7 PASSED:\n" + "\tPopFrame(), being invoked with " + "the non suspended and is exiting thread,\n" + "\treturned the appropriate error " + "JVMTI_ERROR_THREAD_NOT_SUSPENDED"); if (isThreadNotAliveError()) { // Done with PopFrame() calls since thread is not alive. break; } } try { popFrameClsThr.join(); } catch (InterruptedException e) { throw new Error("Unexpected: " + e); } if (totRes != PASSED) { break; } } System.out.println("Executed " + count + " loops in " + timeMax + " seconds."); return totRes; } public static void usage() { System.err.println("Usage: " + AGENT_LIB + " [-v][time_max]"); System.err.println("where:"); System.err.println(" -v verbose mode"); System.err.println(" time_max max looping time in seconds"); System.err.println(" (default is " + DEF_TIME_MAX + " seconds)"); System.exit(1); } class popFrameCls extends Thread { public void run() { boolean compl = true; if (popframe011.popFdone) { // popping has been done out.println("TEST FAILED: frame with popFrameCls.run() was popped"); popframe011.totRes = FAILED; } else { synchronized(readi) { readi.notify(); // notify the main thread } } if (DEBUG_MODE) out.println("popFrameCls (" + this + "): inside run()"); try { // pause here and get the main thread a chance to run synchronized (popframe011.barrier) {} compl = false; } catch (Exception e) { out.println("FAILURE: popFrameCls (" + this + "): caught " + e); compl = false; } finally { if (compl) { out.println("TEST FAILED: finally block was executed after PopFrame()"); popframe011.totRes = FAILED; } } } } }