1 /*
2  * Copyright (c) 2007, 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 package nsk.monitoring.share.thread;
24 
25 import nsk.share.log.Log;
26 
27 /**
28  * RecursiveMonitoringThread is a thread that recursively executes some
29  * methods and runs method runInside inside. The method may be implemented
30  * by subclasses. The types of methods are determined by recursionType,
31  * which may be JAVA (only java methods), NATIVE (only native
32  * methods) and MIXED (java and native methods).
33  */
34 public abstract class RecursiveMonitoringThread extends MonitoringThread {
35         private RunType recursionType;
36         private int maxDepth;
37         private static final String[] expectedMethodsJava = {
38                 "nsk.monitoring.share.thread.RecursiveMonitoringThread.recursiveMethod",
39                 "nsk.monitoring.share.thread.RecursiveMonitoringThread.run"
40         };
41         private static final String[] expectedMethodsNative = {
42                 "nsk.monitoring.share.thread.RecursiveMonitoringThread.nativeRecursiveMethod",
43                 "nsk.monitoring.share.thread.RecursiveMonitoringThread.run"
44         };
45         private static final String[] expectedMethodsMixed = {
46                 "nsk.monitoring.share.thread.RecursiveMonitoringThread.nativeRecursiveMethod",
47                 "nsk.monitoring.share.thread.RecursiveMonitoringThread.recursiveMethod",
48                 "nsk.monitoring.share.thread.RecursiveMonitoringThread.run"
49         };
50 
51         static {
52                 System.loadLibrary("RecursiveMonitoringThread");
53         }
54 
RecursiveMonitoringThread(Log log, RunType recursionType, int maxDepth)55         public RecursiveMonitoringThread(Log log, RunType recursionType, int maxDepth) {
56                 super(log);
57                 this.recursionType = recursionType;
58                 this.maxDepth = maxDepth;
59         }
60 
run()61         public void run() {
62                 switch (recursionType) {
63                 case JAVA:
64                 case MIXED:
65                         recursiveMethod(maxDepth);
66                         break;
67                 case NATIVE:
68                         nativeRecursiveMethod(maxDepth, true);
69                         break;
70                 }
71         }
72 
recursiveMethod(int currentDepth)73         protected void recursiveMethod(int currentDepth) {
74                 if (currentDepth-- > 0) {
75                         switch (recursionType) {
76                         case JAVA:
77                                 recursiveMethod(currentDepth);
78                                 break;
79                         case MIXED:
80                                 nativeRecursiveMethod(currentDepth, false);
81                                 break;
82                         }
83                 } else {
84                         runInside();
85                 }
86         }
87 
isStackTraceElementExpected(StackTraceElement element)88         protected boolean isStackTraceElementExpected(StackTraceElement element) {
89                 if (super.isStackTraceElementExpected(element))
90                         return true;
91                 switch (recursionType) {
92                 case JAVA:
93                         return checkStackTraceElement(element, expectedMethodsJava);
94                 case NATIVE:
95                         return checkStackTraceElement(element, expectedMethodsNative);
96                 case MIXED:
97                         return checkStackTraceElement(element, expectedMethodsMixed);
98                 default:
99                         throw new IllegalArgumentException("Unknown recursionType: " + recursionType);
100                 }
101         }
102 
nativeRecursiveMethod(int currentDepth, boolean pureNative)103         protected native void nativeRecursiveMethod(int currentDepth, boolean pureNative);
104 
runInside()105         protected abstract void runInside();
106 }
107