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 package nsk.jvmti.PopFrame;
  25 
  26 import nsk.share.Wicket;
  27 import java.io.PrintStream;
  28 
  29 /**
  30  * This test checks that a frame can be popped and<br>
  31  * no JVMTI events would be generated by the JVMTI function
  32  * <code>PopFrame()</code>.<br>
  33  * The test creates an instance of inner class <code>popFrameCls</code>
  34  * and start it in a separate thread. Then the test pops frame
  35  * from the thread's stack of the class <code>popFrameCls</code>.
  36  */
  37 public class popframe001 {
  38     static final int PASSED = 0;
  39     static final int FAILED = 2;
  40     static final int JCK_STATUS_BASE = 95;
  41 
  42     static boolean DEBUG_MODE = false;
  43     static volatile boolean popFdone = false;
  44     static volatile int totRes = PASSED;
  45     private PrintStream out;
  46     private popFrameCls popFrameClsThr;
  47     static Object barrier = new Object();
  48     static Wicket startingBarrier;
  49 
  50     static {
  51         try {
  52             System.loadLibrary("popframe001");
  53         } catch (UnsatisfiedLinkError e) {
  54             System.err.println("Could not load popframe001 library");
  55             System.err.println("java.library.path:" +
  56                 System.getProperty("java.library.path"));
  57             throw e;
  58         }
  59     }
  60 
  61     native static int doPopFrame(int vrb, popFrameCls popFrameClsThr);
  62     native static int suspThread(int vrb, popFrameCls popFrameClsThr);
  63     native static int resThread(int vrb, popFrameCls popFrameClsThr);
  64 
  65     public static void main(String[] argv) {
  66         argv = nsk.share.jvmti.JVMTITest.commonInit(argv);
  67 
  68         System.exit(run(argv, System.out) + JCK_STATUS_BASE);
  69     }
  70 
  71     public static int run(String argv[], PrintStream out) {
  72         return new popframe001().runIt(argv, out);
  73     }
  74 
  75     private int runIt(String argv[], PrintStream out) {
  76         int retValue = 0;
  77 
  78         this.out = out;
  79         for (int i = 0; i < argv.length; i++) {
  80             if (argv[i].equals("-v")) // verbose mode
  81                 DEBUG_MODE = true;
  82         }
  83 
  84         popFrameClsThr = new popFrameCls("Tested Thread");
  85         startingBarrier = new Wicket();
  86         // start the child thread
  87         popFrameClsThr.start();
  88         startingBarrier.waitFor();
  89         // pause until the child thread exits notification-block
  90         synchronized (barrier) {
  91         }
  92 
  93         if (DEBUG_MODE) {
  94             out.println("Going to suspend the thread...");
  95             retValue = suspThread(1, popFrameClsThr);
  96         } else
  97             retValue = suspThread(0, popFrameClsThr);
  98         if (retValue != PASSED) {
  99             out.println("TEST: failed to suspend thread");
 100             return FAILED;
 101         }
 102 
 103         // pop a frame of the child thread
 104         if (DEBUG_MODE) {
 105             out.println("Going to pop a frame...");
 106             retValue = doPopFrame(1, popFrameClsThr);
 107         } else
 108             retValue = doPopFrame(0, popFrameClsThr);
 109         popFdone = true;
 110         popFrameClsThr.letItGo();
 111         if (retValue != PASSED) {
 112             out.println("TEST: failed to pop frame");
 113             resThread(0, popFrameClsThr);
 114             return FAILED;
 115         }
 116 
 117         if (DEBUG_MODE) {
 118             out.println("Going to resume the thread...");
 119             retValue = resThread(1, popFrameClsThr);
 120         } else
 121             retValue = resThread(0, popFrameClsThr);
 122         if (retValue != PASSED) {
 123             out.println("TEST: failed to resume thread");
 124             return FAILED;
 125         }
 126 
 127         try {
 128             popFrameClsThr.join();
 129         } catch (InterruptedException e) {
 130             out.println("TEST INCOMPLETE: caught " + e);
 131             return FAILED;
 132         }
 133 
 134         return totRes;
 135     }
 136 
 137     class popFrameCls extends Thread {
 138         private volatile boolean flag = true;
 139 
 140         popFrameCls(String name) {
 141             super(name);
 142         }
 143 
 144         public void run() {
 145             activeMethod();
 146             if (DEBUG_MODE)
 147                 out.println("popFrameCls (" + this +
 148                     "): exiting...");
 149         }
 150 
 151         public void activeMethod() {
 152             boolean compl = true; // complain in a finally block
 153 
 154             if (popframe001.popFdone) { // popping has been done
 155                 if (DEBUG_MODE)
 156                     out.println("popFrameCls (" + this +
 157                         "): enter activeMethod() after popping");
 158                 return;
 159             }
 160             try {
 161                 // notify the main thread
 162                 synchronized (popframe001.barrier) {
 163                     if (DEBUG_MODE)
 164                         out.println("popFrameCls (" + this +
 165                             "): notifying main thread");
 166                     popframe001.startingBarrier.unlock();
 167                     if (DEBUG_MODE)
 168                         out.println("popFrameCls (" + this +
 169                             "): inside activeMethod()");
 170                 }
 171                 // loop until the main thread pops us
 172                 int i = 0;
 173                 int n = 1000;
 174                 while (flag) {
 175                     if (n <= 0) {
 176                         n = 1000;
 177                     }
 178                     if (i > n) {
 179                         i = 0;
 180                         n--;
 181                     }
 182                     i++;
 183                 }
 184                 if (popframe001.popFdone) { // popping has been done
 185                     out.println("TEST FAILED: a tested frame has not been really popped");
 186                     popframe001.totRes = FAILED;
 187                     compl = false;
 188                 }
 189             } catch (Exception e) {
 190                 out.println("FAILURE: popFrameCls (" + this + "): caught " + e);
 191                 popframe001.totRes = FAILED;
 192                 compl = false;
 193             } finally {
 194                 if (compl) {
 195                     out.println("TEST FAILED: finally block was executed after PopFrame()");
 196                     popframe001.totRes = FAILED;
 197                 }
 198             }
 199         }
 200 
 201         public void letItGo() {
 202             flag = false;
 203         }
 204     }
 205 }