annotate agent/src/share/native/jvmdi/sa.cpp @ 10:28372612af5e

6362677: Change parallel GC collector default number of parallel GC threads. Summary: Use the same default number of GC threads as used by ParNewGC and ConcMarkSweepGC (i.e., the 5/8th rule). Reviewed-by: ysr, tonyp
author jmasa
date Fri, 22 Feb 2008 17:17:14 -0800
parents a61af66fc99e
children c18cbe5936b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 #include <stdio.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
26 #include <stdarg.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
27 #include <stdlib.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
28 #include <vector>
a61af66fc99e Initial load
duke
parents:
diff changeset
29 #include "sa.hpp"
a61af66fc99e Initial load
duke
parents:
diff changeset
30 #include "jni.h"
a61af66fc99e Initial load
duke
parents:
diff changeset
31 #include "jvmdi.h"
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33 #ifndef WIN32
a61af66fc99e Initial load
duke
parents:
diff changeset
34 #include <inttypes.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
35 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
36 typedef int int32_t;
a61af66fc99e Initial load
duke
parents:
diff changeset
37 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
38
a61af66fc99e Initial load
duke
parents:
diff changeset
39 #ifdef WIN32
a61af66fc99e Initial load
duke
parents:
diff changeset
40 #include <windows.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
41 #define YIELD() Sleep(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
42 #define SLEEP() Sleep(10)
a61af66fc99e Initial load
duke
parents:
diff changeset
43 #define vsnprintf _vsnprintf
a61af66fc99e Initial load
duke
parents:
diff changeset
44 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
45 Error: please port YIELD() and SLEEP() macros to your platform
a61af66fc99e Initial load
duke
parents:
diff changeset
46 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 using namespace std;
a61af66fc99e Initial load
duke
parents:
diff changeset
49
a61af66fc99e Initial load
duke
parents:
diff changeset
50 //////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
51 // //
a61af66fc99e Initial load
duke
parents:
diff changeset
52 // Exported "interface" for Java language-level interaction between //
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // the SA and the VM. Note that the SA knows about the layout of //
a61af66fc99e Initial load
duke
parents:
diff changeset
54 // certain VM data structures and that knowledge is taken advantage //
a61af66fc99e Initial load
duke
parents:
diff changeset
55 // of in this code, although this interfaces with the VM via JVMDI. //
a61af66fc99e Initial load
duke
parents:
diff changeset
56 // //
a61af66fc99e Initial load
duke
parents:
diff changeset
57 //////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
58
a61af66fc99e Initial load
duke
parents:
diff changeset
59 extern "C" {
a61af66fc99e Initial load
duke
parents:
diff changeset
60 /////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
61 // //
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // Events sent by the VM to the SA //
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // //
a61af66fc99e Initial load
duke
parents:
diff changeset
64 /////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
65
a61af66fc99e Initial load
duke
parents:
diff changeset
66 // Set by the SA when it attaches. Indicates that events should be
a61af66fc99e Initial load
duke
parents:
diff changeset
67 // posted via these exported variables, and that the VM should wait
a61af66fc99e Initial load
duke
parents:
diff changeset
68 // for those events to be acknowledged by the SA (via its setting
a61af66fc99e Initial load
duke
parents:
diff changeset
69 // saEventPending to 0).
a61af66fc99e Initial load
duke
parents:
diff changeset
70 JNIEXPORT volatile int32_t saAttached = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
71
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // Set to nonzero value by the VM when an event has been posted; set
a61af66fc99e Initial load
duke
parents:
diff changeset
73 // back to 0 by the SA when it has processed that event.
a61af66fc99e Initial load
duke
parents:
diff changeset
74 JNIEXPORT volatile int32_t saEventPending = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 // Kind of the event (from jvmdi.h)
a61af66fc99e Initial load
duke
parents:
diff changeset
77 JNIEXPORT volatile int32_t saEventKind = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
78
a61af66fc99e Initial load
duke
parents:
diff changeset
79 //
a61af66fc99e Initial load
duke
parents:
diff changeset
80 // Exception events
a61af66fc99e Initial load
duke
parents:
diff changeset
81 //
a61af66fc99e Initial load
duke
parents:
diff changeset
82 JNIEXPORT jthread saExceptionThread;
a61af66fc99e Initial load
duke
parents:
diff changeset
83 JNIEXPORT jclass saExceptionClass;
a61af66fc99e Initial load
duke
parents:
diff changeset
84 JNIEXPORT jmethodID saExceptionMethod;
a61af66fc99e Initial load
duke
parents:
diff changeset
85 JNIEXPORT int32_t saExceptionLocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
86 JNIEXPORT jobject saExceptionException;
a61af66fc99e Initial load
duke
parents:
diff changeset
87 JNIEXPORT jclass saExceptionCatchClass;
a61af66fc99e Initial load
duke
parents:
diff changeset
88 JNIEXPORT jmethodID saExceptionCatchMethod;
a61af66fc99e Initial load
duke
parents:
diff changeset
89 JNIEXPORT int32_t saExceptionCatchLocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91 //
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // Breakpoint events
a61af66fc99e Initial load
duke
parents:
diff changeset
93 //
a61af66fc99e Initial load
duke
parents:
diff changeset
94 JNIEXPORT jthread saBreakpointThread;
a61af66fc99e Initial load
duke
parents:
diff changeset
95 JNIEXPORT jclass saBreakpointClass;
a61af66fc99e Initial load
duke
parents:
diff changeset
96 JNIEXPORT jmethodID saBreakpointMethod;
a61af66fc99e Initial load
duke
parents:
diff changeset
97 JNIEXPORT jlocation saBreakpointLocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99 ///////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
100 // //
a61af66fc99e Initial load
duke
parents:
diff changeset
101 // Commands sent by the SA to the VM //
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // //
a61af66fc99e Initial load
duke
parents:
diff changeset
103 ///////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
104
a61af66fc99e Initial load
duke
parents:
diff changeset
105 extern JNIEXPORT const int32_t SA_CMD_SUSPEND_ALL = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
106 extern JNIEXPORT const int32_t SA_CMD_RESUME_ALL = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
107 extern JNIEXPORT const int32_t SA_CMD_TOGGLE_BREAKPOINT = 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
108 extern JNIEXPORT const int32_t SA_CMD_BUF_SIZE = 1024;
a61af66fc99e Initial load
duke
parents:
diff changeset
109
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // SA sets this to a nonzero value when it is requesting a command
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // to be processed; VM sets it back to 0 when the command has been
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // executed
a61af66fc99e Initial load
duke
parents:
diff changeset
113 JNIEXPORT volatile int32_t saCmdPending = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
114
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // SA sets this to one of the manifest constants above to indicate
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // the kind of command to be executed
a61af66fc99e Initial load
duke
parents:
diff changeset
117 JNIEXPORT volatile int32_t saCmdType = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
118
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // VM sets this to 0 if the last command succeeded or a nonzero
a61af66fc99e Initial load
duke
parents:
diff changeset
120 // value if it failed
a61af66fc99e Initial load
duke
parents:
diff changeset
121 JNIEXPORT volatile int32_t saCmdResult = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
122
a61af66fc99e Initial load
duke
parents:
diff changeset
123 // If last command failed, this buffer will contain a descriptive
a61af66fc99e Initial load
duke
parents:
diff changeset
124 // error message
a61af66fc99e Initial load
duke
parents:
diff changeset
125 JNIEXPORT char saCmdResultErrMsg[SA_CMD_BUF_SIZE];
a61af66fc99e Initial load
duke
parents:
diff changeset
126
a61af66fc99e Initial load
duke
parents:
diff changeset
127 //
a61af66fc99e Initial load
duke
parents:
diff changeset
128 // Toggling of breakpoint command arguments.
a61af66fc99e Initial load
duke
parents:
diff changeset
129 //
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // Originally there were separate set/clear breakpoint commands
a61af66fc99e Initial load
duke
parents:
diff changeset
131 // taking a class name, method name and signature, and the iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
132 // through the debug information was done in the SA. It turns out
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // that doing this work in the target VM is significantly faster,
a61af66fc99e Initial load
duke
parents:
diff changeset
134 // and since interactivity when setting and clearing breakpoints is
a61af66fc99e Initial load
duke
parents:
diff changeset
135 // important, the solution which resulted in more C/C++ code was used.
a61af66fc99e Initial load
duke
parents:
diff changeset
136 //
a61af66fc99e Initial load
duke
parents:
diff changeset
137
a61af66fc99e Initial load
duke
parents:
diff changeset
138 // Source file name
a61af66fc99e Initial load
duke
parents:
diff changeset
139 JNIEXPORT char saCmdBkptSrcFileName[SA_CMD_BUF_SIZE];
a61af66fc99e Initial load
duke
parents:
diff changeset
140
a61af66fc99e Initial load
duke
parents:
diff changeset
141 // Package name ('/' as separator instead of '.')
a61af66fc99e Initial load
duke
parents:
diff changeset
142 JNIEXPORT char saCmdBkptPkgName[SA_CMD_BUF_SIZE];
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144 // Line number
a61af66fc99e Initial load
duke
parents:
diff changeset
145 JNIEXPORT int32_t saCmdBkptLineNumber;
a61af66fc99e Initial load
duke
parents:
diff changeset
146
a61af66fc99e Initial load
duke
parents:
diff changeset
147 // Output back to SA: indicator whether the last failure of a
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // breakpoint toggle command was really an error or just a lack of
a61af66fc99e Initial load
duke
parents:
diff changeset
149 // debug information covering the requested line. 0 if not error.
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // Valid only if saCmdResult != 0.
a61af66fc99e Initial load
duke
parents:
diff changeset
151 JNIEXPORT int32_t saCmdBkptResWasError;
a61af66fc99e Initial load
duke
parents:
diff changeset
152
a61af66fc99e Initial load
duke
parents:
diff changeset
153 // Output back to SA: resulting line number at which the breakpoint
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // was set or cleared (valid only if saCmdResult == 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
155 JNIEXPORT int32_t saCmdBkptResLineNumber;
a61af66fc99e Initial load
duke
parents:
diff changeset
156
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // Output back to SA: resulting byte code index at which the
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // breakpoint was set or cleared (valid only if saCmdResult == 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
159 JNIEXPORT int32_t saCmdBkptResBCI;
a61af66fc99e Initial load
duke
parents:
diff changeset
160
a61af66fc99e Initial load
duke
parents:
diff changeset
161 // Output back to SA: indicator whether the breakpoint operation
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // resulted in a set or cleared breakpoint; nonzero if set, zero if
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // cleared (valid only if saCmdResult == 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
164 JNIEXPORT int32_t saCmdBkptResWasSet;
a61af66fc99e Initial load
duke
parents:
diff changeset
165
a61af66fc99e Initial load
duke
parents:
diff changeset
166 // Output back to SA: method name the breakpoint was set in (valid
a61af66fc99e Initial load
duke
parents:
diff changeset
167 // only if saCmdResult == 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
168 JNIEXPORT char saCmdBkptResMethodName[SA_CMD_BUF_SIZE];
a61af66fc99e Initial load
duke
parents:
diff changeset
169
a61af66fc99e Initial load
duke
parents:
diff changeset
170 // Output back to SA: method signature (JNI style) the breakpoint
a61af66fc99e Initial load
duke
parents:
diff changeset
171 // was set in (valid only if saCmdResult == 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
172 JNIEXPORT char saCmdBkptResMethodSig[SA_CMD_BUF_SIZE];
a61af66fc99e Initial load
duke
parents:
diff changeset
173 }
a61af66fc99e Initial load
duke
parents:
diff changeset
174
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // Internal state
a61af66fc99e Initial load
duke
parents:
diff changeset
176 static JavaVM* jvm = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
177 static JVMDI_Interface_1* jvmdi = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
178 static jthread debugThreadObj = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 static bool suspended = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
180 static vector<jthread> suspendedThreads;
a61af66fc99e Initial load
duke
parents:
diff changeset
181 static JVMDI_RawMonitor eventLock = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183 class MonitorLocker {
a61af66fc99e Initial load
duke
parents:
diff changeset
184 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
185 JVMDI_RawMonitor lock;
a61af66fc99e Initial load
duke
parents:
diff changeset
186 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
187 MonitorLocker(JVMDI_RawMonitor lock) {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 this->lock = lock;
a61af66fc99e Initial load
duke
parents:
diff changeset
189 if (lock != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
190 jvmdi->RawMonitorEnter(lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
192 }
a61af66fc99e Initial load
duke
parents:
diff changeset
193 ~MonitorLocker() {
a61af66fc99e Initial load
duke
parents:
diff changeset
194 if (lock != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
195 jvmdi->RawMonitorExit(lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
197 }
a61af66fc99e Initial load
duke
parents:
diff changeset
198 };
a61af66fc99e Initial load
duke
parents:
diff changeset
199
a61af66fc99e Initial load
duke
parents:
diff changeset
200 class JvmdiDeallocator {
a61af66fc99e Initial load
duke
parents:
diff changeset
201 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
202 void* ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
203 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
204 JvmdiDeallocator(void* ptr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
205 this->ptr = ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
207 ~JvmdiDeallocator() {
a61af66fc99e Initial load
duke
parents:
diff changeset
208 jvmdi->Deallocate((jbyte*) ptr);
a61af66fc99e Initial load
duke
parents:
diff changeset
209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
210 };
a61af66fc99e Initial load
duke
parents:
diff changeset
211
a61af66fc99e Initial load
duke
parents:
diff changeset
212 class JvmdiRefListDeallocator {
a61af66fc99e Initial load
duke
parents:
diff changeset
213 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
214 JNIEnv* env;
a61af66fc99e Initial load
duke
parents:
diff changeset
215 jobject* refList;
a61af66fc99e Initial load
duke
parents:
diff changeset
216 jint refCount;
a61af66fc99e Initial load
duke
parents:
diff changeset
217 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
218 JvmdiRefListDeallocator(JNIEnv* env, jobject* refList, jint refCount) {
a61af66fc99e Initial load
duke
parents:
diff changeset
219 this->env = env;
a61af66fc99e Initial load
duke
parents:
diff changeset
220 this->refList = refList;
a61af66fc99e Initial load
duke
parents:
diff changeset
221 this->refCount = refCount;
a61af66fc99e Initial load
duke
parents:
diff changeset
222 }
a61af66fc99e Initial load
duke
parents:
diff changeset
223 ~JvmdiRefListDeallocator() {
a61af66fc99e Initial load
duke
parents:
diff changeset
224 for (int i = 0; i < refCount; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
225 env->DeleteGlobalRef(refList[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
227 jvmdi->Deallocate((jbyte*) refList);
a61af66fc99e Initial load
duke
parents:
diff changeset
228 }
a61af66fc99e Initial load
duke
parents:
diff changeset
229 };
a61af66fc99e Initial load
duke
parents:
diff changeset
230
a61af66fc99e Initial load
duke
parents:
diff changeset
231 static void
a61af66fc99e Initial load
duke
parents:
diff changeset
232 stop(char* msg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 fprintf(stderr, "%s", msg);
a61af66fc99e Initial load
duke
parents:
diff changeset
234 fprintf(stderr, "\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
235 exit(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
237
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // This fills in the command result error message, sets the command
a61af66fc99e Initial load
duke
parents:
diff changeset
239 // result to -1, and clears the pending command flag
a61af66fc99e Initial load
duke
parents:
diff changeset
240 static void
a61af66fc99e Initial load
duke
parents:
diff changeset
241 reportErrorToSA(const char* str, ...) {
a61af66fc99e Initial load
duke
parents:
diff changeset
242 va_list varargs;
a61af66fc99e Initial load
duke
parents:
diff changeset
243 va_start(varargs, str);
a61af66fc99e Initial load
duke
parents:
diff changeset
244 vsnprintf(saCmdResultErrMsg, sizeof(saCmdResultErrMsg), str, varargs);
a61af66fc99e Initial load
duke
parents:
diff changeset
245 va_end(varargs);
a61af66fc99e Initial load
duke
parents:
diff changeset
246 saCmdResult = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
247 saCmdPending = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
248 }
a61af66fc99e Initial load
duke
parents:
diff changeset
249
a61af66fc99e Initial load
duke
parents:
diff changeset
250 static bool
a61af66fc99e Initial load
duke
parents:
diff changeset
251 packageNameMatches(char* clazzName, char* pkg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
252 int pkgLen = strlen(pkg);
a61af66fc99e Initial load
duke
parents:
diff changeset
253 int clazzNameLen = strlen(clazzName);
a61af66fc99e Initial load
duke
parents:
diff changeset
254
a61af66fc99e Initial load
duke
parents:
diff changeset
255 if (pkgLen >= clazzNameLen + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
256 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
258
a61af66fc99e Initial load
duke
parents:
diff changeset
259 if (strncmp(clazzName, pkg, pkgLen)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
262
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // Ensure that '/' is the next character if non-empty package name
a61af66fc99e Initial load
duke
parents:
diff changeset
264 int l = pkgLen;
a61af66fc99e Initial load
duke
parents:
diff changeset
265 if (l > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
266 if (clazzName[l] != '/') {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
268 }
a61af66fc99e Initial load
duke
parents:
diff changeset
269 l++;
a61af66fc99e Initial load
duke
parents:
diff changeset
270 }
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // Ensure that there are no more trailing slashes
a61af66fc99e Initial load
duke
parents:
diff changeset
272 while (l < clazzNameLen) {
a61af66fc99e Initial load
duke
parents:
diff changeset
273 if (clazzName[l++] == '/') {
a61af66fc99e Initial load
duke
parents:
diff changeset
274 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
276 }
a61af66fc99e Initial load
duke
parents:
diff changeset
277 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
278 }
a61af66fc99e Initial load
duke
parents:
diff changeset
279
a61af66fc99e Initial load
duke
parents:
diff changeset
280 static void
a61af66fc99e Initial load
duke
parents:
diff changeset
281 executeOneCommand(JNIEnv* env) {
a61af66fc99e Initial load
duke
parents:
diff changeset
282 switch (saCmdType) {
a61af66fc99e Initial load
duke
parents:
diff changeset
283 case SA_CMD_SUSPEND_ALL: {
a61af66fc99e Initial load
duke
parents:
diff changeset
284 if (suspended) {
a61af66fc99e Initial load
duke
parents:
diff changeset
285 reportErrorToSA("Target process already suspended");
a61af66fc99e Initial load
duke
parents:
diff changeset
286 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
288
a61af66fc99e Initial load
duke
parents:
diff changeset
289 // We implement this by getting all of the threads and calling
a61af66fc99e Initial load
duke
parents:
diff changeset
290 // SuspendThread on each one, except for the thread object
a61af66fc99e Initial load
duke
parents:
diff changeset
291 // corresponding to this thread. Each thread for which the call
a61af66fc99e Initial load
duke
parents:
diff changeset
292 // succeeded (i.e., did not return JVMDI_ERROR_INVALID_THREAD)
a61af66fc99e Initial load
duke
parents:
diff changeset
293 // is added to a list which is remembered for later resumption.
a61af66fc99e Initial load
duke
parents:
diff changeset
294 // Note that this currently has race conditions since a thread
a61af66fc99e Initial load
duke
parents:
diff changeset
295 // might be started after we call GetAllThreads and since a
a61af66fc99e Initial load
duke
parents:
diff changeset
296 // thread for which we got an error earlier might be resumed by
a61af66fc99e Initial load
duke
parents:
diff changeset
297 // the VM while we are busy suspending other threads. We could
a61af66fc99e Initial load
duke
parents:
diff changeset
298 // solve this by looping until there are no more threads we can
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // suspend, but a more robust and scalable solution is to add
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // this functionality to the JVMDI interface (i.e.,
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // "suspendAll"). Probably need to provide an exclude list for
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // such a routine.
a61af66fc99e Initial load
duke
parents:
diff changeset
303 jint threadCount;
a61af66fc99e Initial load
duke
parents:
diff changeset
304 jthread* threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
305 if (jvmdi->GetAllThreads(&threadCount, &threads) != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
306 reportErrorToSA("Error while getting thread list");
a61af66fc99e Initial load
duke
parents:
diff changeset
307 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
309
a61af66fc99e Initial load
duke
parents:
diff changeset
310
a61af66fc99e Initial load
duke
parents:
diff changeset
311 for (int i = 0; i < threadCount; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
312 jthread thr = threads[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
313 if (!env->IsSameObject(thr, debugThreadObj)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
314 jvmdiError err = jvmdi->SuspendThread(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
315 if (err == JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // Remember this thread and do not free it
a61af66fc99e Initial load
duke
parents:
diff changeset
317 suspendedThreads.push_back(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
318 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
319 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
320 fprintf(stderr, " SA: Error %d while suspending thread\n", err);
a61af66fc99e Initial load
duke
parents:
diff changeset
321 // FIXME: stop, resume all threads, report error
a61af66fc99e Initial load
duke
parents:
diff changeset
322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
323 }
a61af66fc99e Initial load
duke
parents:
diff changeset
324 env->DeleteGlobalRef(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
325 }
a61af66fc99e Initial load
duke
parents:
diff changeset
326
a61af66fc99e Initial load
duke
parents:
diff changeset
327 // Free up threads
a61af66fc99e Initial load
duke
parents:
diff changeset
328 jvmdi->Deallocate((jbyte*) threads);
a61af66fc99e Initial load
duke
parents:
diff changeset
329
a61af66fc99e Initial load
duke
parents:
diff changeset
330 // Suspension is complete
a61af66fc99e Initial load
duke
parents:
diff changeset
331 suspended = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
332 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
333 }
a61af66fc99e Initial load
duke
parents:
diff changeset
334
a61af66fc99e Initial load
duke
parents:
diff changeset
335 case SA_CMD_RESUME_ALL: {
a61af66fc99e Initial load
duke
parents:
diff changeset
336 if (!suspended) {
a61af66fc99e Initial load
duke
parents:
diff changeset
337 reportErrorToSA("Target process already suspended");
a61af66fc99e Initial load
duke
parents:
diff changeset
338 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
339 }
a61af66fc99e Initial load
duke
parents:
diff changeset
340
a61af66fc99e Initial load
duke
parents:
diff changeset
341 saCmdResult = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
342 bool errorOccurred = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
343 jvmdiError firstError;
a61af66fc99e Initial load
duke
parents:
diff changeset
344 for (int i = 0; i < suspendedThreads.size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
345 jthread thr = suspendedThreads[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
346 jvmdiError err = jvmdi->ResumeThread(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
347 env->DeleteGlobalRef(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
348 if (err != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
349 if (!errorOccurred) {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 errorOccurred = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
351 firstError = err;
a61af66fc99e Initial load
duke
parents:
diff changeset
352 }
a61af66fc99e Initial load
duke
parents:
diff changeset
353 }
a61af66fc99e Initial load
duke
parents:
diff changeset
354 }
a61af66fc99e Initial load
duke
parents:
diff changeset
355 suspendedThreads.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
356 suspended = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
357 if (errorOccurred) {
a61af66fc99e Initial load
duke
parents:
diff changeset
358 reportErrorToSA("Error %d while resuming threads", firstError);
a61af66fc99e Initial load
duke
parents:
diff changeset
359 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
360 }
a61af66fc99e Initial load
duke
parents:
diff changeset
361 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
362 }
a61af66fc99e Initial load
duke
parents:
diff changeset
363
a61af66fc99e Initial load
duke
parents:
diff changeset
364 case SA_CMD_TOGGLE_BREAKPOINT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
365 saCmdBkptResWasError = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
366
a61af66fc99e Initial load
duke
parents:
diff changeset
367 // Search line number info for all loaded classes
a61af66fc99e Initial load
duke
parents:
diff changeset
368 jint classCount;
a61af66fc99e Initial load
duke
parents:
diff changeset
369 jclass* classes;
a61af66fc99e Initial load
duke
parents:
diff changeset
370
a61af66fc99e Initial load
duke
parents:
diff changeset
371 jvmdiError glcRes = jvmdi->GetLoadedClasses(&classCount, &classes);
a61af66fc99e Initial load
duke
parents:
diff changeset
372 if (glcRes != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
373 reportErrorToSA("Error %d while getting loaded classes", glcRes);
a61af66fc99e Initial load
duke
parents:
diff changeset
374 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
375 }
a61af66fc99e Initial load
duke
parents:
diff changeset
376 JvmdiRefListDeallocator rld(env, (jobject*) classes, classCount);
a61af66fc99e Initial load
duke
parents:
diff changeset
377
a61af66fc99e Initial load
duke
parents:
diff changeset
378 bool done = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
379 bool gotOne = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
380 jclass targetClass;
a61af66fc99e Initial load
duke
parents:
diff changeset
381 jmethodID targetMethod;
a61af66fc99e Initial load
duke
parents:
diff changeset
382 jlocation targetLocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
383 jint targetLineNumber;
a61af66fc99e Initial load
duke
parents:
diff changeset
384
a61af66fc99e Initial load
duke
parents:
diff changeset
385 for (int i = 0; i < classCount && !done; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
386 fflush(stderr);
a61af66fc99e Initial load
duke
parents:
diff changeset
387 jclass clazz = classes[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
388 char* srcName;
a61af66fc99e Initial load
duke
parents:
diff changeset
389 jvmdiError sfnRes = jvmdi->GetSourceFileName(clazz, &srcName);
a61af66fc99e Initial load
duke
parents:
diff changeset
390 if (sfnRes == JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
391 JvmdiDeallocator de1(srcName);
a61af66fc99e Initial load
duke
parents:
diff changeset
392 if (!strcmp(srcName, saCmdBkptSrcFileName)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
393 // Got a match. Now see whether the package name of the class also matches
a61af66fc99e Initial load
duke
parents:
diff changeset
394 char* clazzName;
a61af66fc99e Initial load
duke
parents:
diff changeset
395 jvmdiError sigRes = jvmdi->GetClassSignature(clazz, &clazzName);
a61af66fc99e Initial load
duke
parents:
diff changeset
396 if (sigRes != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
397 reportErrorToSA("Error %d while getting a class's signature", sigRes);
a61af66fc99e Initial load
duke
parents:
diff changeset
398 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
399 }
a61af66fc99e Initial load
duke
parents:
diff changeset
400 JvmdiDeallocator de2(clazzName);
a61af66fc99e Initial load
duke
parents:
diff changeset
401 if (packageNameMatches(clazzName + 1, saCmdBkptPkgName)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
402 // Iterate through all methods
a61af66fc99e Initial load
duke
parents:
diff changeset
403 jint methodCount;
a61af66fc99e Initial load
duke
parents:
diff changeset
404 jmethodID* methods;
a61af66fc99e Initial load
duke
parents:
diff changeset
405 if (jvmdi->GetClassMethods(clazz, &methodCount, &methods) != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
406 reportErrorToSA("Error while getting methods of class %s", clazzName);
a61af66fc99e Initial load
duke
parents:
diff changeset
407 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
408 }
a61af66fc99e Initial load
duke
parents:
diff changeset
409 JvmdiDeallocator de3(methods);
a61af66fc99e Initial load
duke
parents:
diff changeset
410 for (int j = 0; j < methodCount && !done; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
411 jmethodID m = methods[j];
a61af66fc99e Initial load
duke
parents:
diff changeset
412 jint entryCount;
a61af66fc99e Initial load
duke
parents:
diff changeset
413 JVMDI_line_number_entry* table;
a61af66fc99e Initial load
duke
parents:
diff changeset
414 jvmdiError lnRes = jvmdi->GetLineNumberTable(clazz, m, &entryCount, &table);
a61af66fc99e Initial load
duke
parents:
diff changeset
415 if (lnRes == JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
416 JvmdiDeallocator de4(table);
a61af66fc99e Initial load
duke
parents:
diff changeset
417 // Look for line number greater than or equal to requested line
a61af66fc99e Initial load
duke
parents:
diff changeset
418 for (int k = 0; k < entryCount && !done; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
419 JVMDI_line_number_entry& entry = table[k];
a61af66fc99e Initial load
duke
parents:
diff changeset
420 if (entry.line_number >= saCmdBkptLineNumber &&
a61af66fc99e Initial load
duke
parents:
diff changeset
421 (!gotOne || entry.line_number < targetLineNumber)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
422 gotOne = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
423 targetClass = clazz;
a61af66fc99e Initial load
duke
parents:
diff changeset
424 targetMethod = m;
a61af66fc99e Initial load
duke
parents:
diff changeset
425 targetLocation = entry.start_location;
a61af66fc99e Initial load
duke
parents:
diff changeset
426 targetLineNumber = entry.line_number;
a61af66fc99e Initial load
duke
parents:
diff changeset
427 done = (targetLineNumber == saCmdBkptLineNumber);
a61af66fc99e Initial load
duke
parents:
diff changeset
428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
430 } else if (lnRes != JVMDI_ERROR_ABSENT_INFORMATION) {
a61af66fc99e Initial load
duke
parents:
diff changeset
431 reportErrorToSA("Unexpected error %d while fetching line number table", lnRes);
a61af66fc99e Initial load
duke
parents:
diff changeset
432 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
433 }
a61af66fc99e Initial load
duke
parents:
diff changeset
434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
435 }
a61af66fc99e Initial load
duke
parents:
diff changeset
436 }
a61af66fc99e Initial load
duke
parents:
diff changeset
437 } else if (sfnRes != JVMDI_ERROR_ABSENT_INFORMATION) {
a61af66fc99e Initial load
duke
parents:
diff changeset
438 reportErrorToSA("Unexpected error %d while fetching source file name", sfnRes);
a61af66fc99e Initial load
duke
parents:
diff changeset
439 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
441 }
a61af66fc99e Initial load
duke
parents:
diff changeset
442
a61af66fc99e Initial load
duke
parents:
diff changeset
443 bool wasSet = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
444 if (gotOne) {
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // Really toggle this breakpoint
a61af66fc99e Initial load
duke
parents:
diff changeset
446 jvmdiError bpRes;
a61af66fc99e Initial load
duke
parents:
diff changeset
447 bpRes = jvmdi->SetBreakpoint(targetClass, targetMethod, targetLocation);
a61af66fc99e Initial load
duke
parents:
diff changeset
448 if (bpRes == JVMDI_ERROR_DUPLICATE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
449 bpRes = jvmdi->ClearBreakpoint(targetClass, targetMethod, targetLocation);
a61af66fc99e Initial load
duke
parents:
diff changeset
450 wasSet = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
451 }
a61af66fc99e Initial load
duke
parents:
diff changeset
452 if (bpRes != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
453 reportErrorToSA("Unexpected error %d while setting or clearing breakpoint at bci %d, line %d",
a61af66fc99e Initial load
duke
parents:
diff changeset
454 bpRes, targetLocation, targetLineNumber);
a61af66fc99e Initial load
duke
parents:
diff changeset
455 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
457 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
458 saCmdBkptResWasError = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
459 reportErrorToSA("No debug information found covering this line");
a61af66fc99e Initial load
duke
parents:
diff changeset
460 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
461 }
a61af66fc99e Initial load
duke
parents:
diff changeset
462
a61af66fc99e Initial load
duke
parents:
diff changeset
463 // Provide result
a61af66fc99e Initial load
duke
parents:
diff changeset
464 saCmdBkptResLineNumber = targetLineNumber;
a61af66fc99e Initial load
duke
parents:
diff changeset
465 saCmdBkptResBCI = targetLocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
466 saCmdBkptResWasSet = (wasSet ? 1 : 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
467 {
a61af66fc99e Initial load
duke
parents:
diff changeset
468 char* methodName;
a61af66fc99e Initial load
duke
parents:
diff changeset
469 char* methodSig;
a61af66fc99e Initial load
duke
parents:
diff changeset
470 if (jvmdi->GetMethodName(targetClass, targetMethod, &methodName, &methodSig)
a61af66fc99e Initial load
duke
parents:
diff changeset
471 == JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
472 JvmdiDeallocator mnd(methodName);
a61af66fc99e Initial load
duke
parents:
diff changeset
473 JvmdiDeallocator msd(methodSig);
a61af66fc99e Initial load
duke
parents:
diff changeset
474 strncpy(saCmdBkptResMethodName, methodName, SA_CMD_BUF_SIZE);
a61af66fc99e Initial load
duke
parents:
diff changeset
475 strncpy(saCmdBkptResMethodSig, methodSig, SA_CMD_BUF_SIZE);
a61af66fc99e Initial load
duke
parents:
diff changeset
476 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
477 strncpy(saCmdBkptResMethodName, "<error>", SA_CMD_BUF_SIZE);
a61af66fc99e Initial load
duke
parents:
diff changeset
478 strncpy(saCmdBkptResMethodSig, "<error>", SA_CMD_BUF_SIZE);
a61af66fc99e Initial load
duke
parents:
diff changeset
479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
481 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
483
a61af66fc99e Initial load
duke
parents:
diff changeset
484 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
485 reportErrorToSA("Command %d not yet supported", saCmdType);
a61af66fc99e Initial load
duke
parents:
diff changeset
486 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
488
a61af66fc99e Initial load
duke
parents:
diff changeset
489 // Successful command execution
a61af66fc99e Initial load
duke
parents:
diff changeset
490 saCmdResult = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
491 saCmdPending = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
493
a61af66fc99e Initial load
duke
parents:
diff changeset
494 static void
a61af66fc99e Initial load
duke
parents:
diff changeset
495 saCommandThread(void *arg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
496 JNIEnv* env = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
497 if (jvm->GetEnv((void **) &env, JNI_VERSION_1_2) != JNI_OK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
498 stop("Error while starting Serviceability Agent "
a61af66fc99e Initial load
duke
parents:
diff changeset
499 "command thread: could not get JNI environment");
a61af66fc99e Initial load
duke
parents:
diff changeset
500 }
a61af66fc99e Initial load
duke
parents:
diff changeset
501
a61af66fc99e Initial load
duke
parents:
diff changeset
502 while (1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
503 // Wait for command
a61af66fc99e Initial load
duke
parents:
diff changeset
504 while (!saCmdPending) {
a61af66fc99e Initial load
duke
parents:
diff changeset
505 SLEEP();
a61af66fc99e Initial load
duke
parents:
diff changeset
506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
507
a61af66fc99e Initial load
duke
parents:
diff changeset
508 executeOneCommand(env);
a61af66fc99e Initial load
duke
parents:
diff changeset
509 }
a61af66fc99e Initial load
duke
parents:
diff changeset
510 }
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 static void
a61af66fc99e Initial load
duke
parents:
diff changeset
513 saEventHook(JNIEnv *env, JVMDI_Event *event)
a61af66fc99e Initial load
duke
parents:
diff changeset
514 {
a61af66fc99e Initial load
duke
parents:
diff changeset
515 MonitorLocker ml(eventLock);
a61af66fc99e Initial load
duke
parents:
diff changeset
516
a61af66fc99e Initial load
duke
parents:
diff changeset
517 saEventKind = event->kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
518
a61af66fc99e Initial load
duke
parents:
diff changeset
519 if (event->kind == JVMDI_EVENT_VM_INIT) {
a61af66fc99e Initial load
duke
parents:
diff changeset
520 // Create event lock
a61af66fc99e Initial load
duke
parents:
diff changeset
521 if (jvmdi->CreateRawMonitor("Serviceability Agent Event Lock", &eventLock)
a61af66fc99e Initial load
duke
parents:
diff changeset
522 != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
523 stop("Unable to create Serviceability Agent's event lock");
a61af66fc99e Initial load
duke
parents:
diff changeset
524 }
a61af66fc99e Initial load
duke
parents:
diff changeset
525 // Start thread which receives commands from the SA.
a61af66fc99e Initial load
duke
parents:
diff changeset
526 jclass threadClass = env->FindClass("java/lang/Thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
527 if (threadClass == NULL) stop("Unable to find class java/lang/Thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
528 jstring threadName = env->NewStringUTF("Serviceability Agent Command Thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
529 if (threadName == NULL) stop("Unable to allocate debug thread name");
a61af66fc99e Initial load
duke
parents:
diff changeset
530 jmethodID ctor = env->GetMethodID(threadClass, "<init>", "(Ljava/lang/String;)V");
a61af66fc99e Initial load
duke
parents:
diff changeset
531 if (ctor == NULL) stop("Unable to find appropriate constructor for java/lang/Thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
532 // Allocate thread object
a61af66fc99e Initial load
duke
parents:
diff changeset
533 jthread thr = (jthread) env->NewObject(threadClass, ctor, threadName);
a61af66fc99e Initial load
duke
parents:
diff changeset
534 if (thr == NULL) stop("Unable to allocate debug thread's java/lang/Thread instance");
a61af66fc99e Initial load
duke
parents:
diff changeset
535 // Remember which thread this is
a61af66fc99e Initial load
duke
parents:
diff changeset
536 debugThreadObj = env->NewGlobalRef(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
537 if (debugThreadObj == NULL) stop("Unable to allocate global ref for debug thread object");
a61af66fc99e Initial load
duke
parents:
diff changeset
538 // Start thread
a61af66fc99e Initial load
duke
parents:
diff changeset
539 jvmdiError err;
a61af66fc99e Initial load
duke
parents:
diff changeset
540 if ((err = jvmdi->RunDebugThread(thr, &saCommandThread, NULL, JVMDI_THREAD_NORM_PRIORITY))
a61af66fc99e Initial load
duke
parents:
diff changeset
541 != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
542 char buf[256];
a61af66fc99e Initial load
duke
parents:
diff changeset
543 sprintf(buf, "Error %d while starting debug thread", err);
a61af66fc99e Initial load
duke
parents:
diff changeset
544 stop(buf);
a61af66fc99e Initial load
duke
parents:
diff changeset
545 }
a61af66fc99e Initial load
duke
parents:
diff changeset
546 // OK, initialization is done
a61af66fc99e Initial load
duke
parents:
diff changeset
547 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
548 }
a61af66fc99e Initial load
duke
parents:
diff changeset
549
a61af66fc99e Initial load
duke
parents:
diff changeset
550 if (!saAttached) {
a61af66fc99e Initial load
duke
parents:
diff changeset
551 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
552 }
a61af66fc99e Initial load
duke
parents:
diff changeset
553
a61af66fc99e Initial load
duke
parents:
diff changeset
554 switch (event->kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
555 case JVMDI_EVENT_EXCEPTION: {
a61af66fc99e Initial load
duke
parents:
diff changeset
556 fprintf(stderr, "SA: Exception thrown -- ignoring\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
557 saExceptionThread = event->u.exception.thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
558 saExceptionClass = event->u.exception.clazz;
a61af66fc99e Initial load
duke
parents:
diff changeset
559 saExceptionMethod = event->u.exception.method;
a61af66fc99e Initial load
duke
parents:
diff changeset
560 saExceptionLocation = event->u.exception.location;
a61af66fc99e Initial load
duke
parents:
diff changeset
561 saExceptionException = event->u.exception.exception;
a61af66fc99e Initial load
duke
parents:
diff changeset
562 saExceptionCatchClass = event->u.exception.catch_clazz;
a61af66fc99e Initial load
duke
parents:
diff changeset
563 saExceptionCatchClass = event->u.exception.catch_clazz;
a61af66fc99e Initial load
duke
parents:
diff changeset
564 saExceptionCatchMethod = event->u.exception.catch_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
565 saExceptionCatchLocation = event->u.exception.catch_location;
a61af66fc99e Initial load
duke
parents:
diff changeset
566 // saEventPending = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
567 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
568 }
a61af66fc99e Initial load
duke
parents:
diff changeset
569
a61af66fc99e Initial load
duke
parents:
diff changeset
570 case JVMDI_EVENT_BREAKPOINT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
571 saBreakpointThread = event->u.breakpoint.thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
572 saBreakpointClass = event->u.breakpoint.clazz;
a61af66fc99e Initial load
duke
parents:
diff changeset
573 saBreakpointMethod = event->u.breakpoint.method;
a61af66fc99e Initial load
duke
parents:
diff changeset
574 saBreakpointLocation = event->u.breakpoint.location;
a61af66fc99e Initial load
duke
parents:
diff changeset
575 saEventPending = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
576 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
578
a61af66fc99e Initial load
duke
parents:
diff changeset
579 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
580 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
581 }
a61af66fc99e Initial load
duke
parents:
diff changeset
582
a61af66fc99e Initial load
duke
parents:
diff changeset
583 while (saAttached && saEventPending) {
a61af66fc99e Initial load
duke
parents:
diff changeset
584 SLEEP();
a61af66fc99e Initial load
duke
parents:
diff changeset
585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
586 }
a61af66fc99e Initial load
duke
parents:
diff changeset
587
a61af66fc99e Initial load
duke
parents:
diff changeset
588 extern "C" {
a61af66fc99e Initial load
duke
parents:
diff changeset
589 JNIEXPORT jint JNICALL
a61af66fc99e Initial load
duke
parents:
diff changeset
590 JVM_OnLoad(JavaVM *vm, char *options, void *reserved)
a61af66fc99e Initial load
duke
parents:
diff changeset
591 {
a61af66fc99e Initial load
duke
parents:
diff changeset
592 jvm = vm;
a61af66fc99e Initial load
duke
parents:
diff changeset
593 if (jvm->GetEnv((void**) &jvmdi, JVMDI_VERSION_1) != JNI_OK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
594 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
595 }
a61af66fc99e Initial load
duke
parents:
diff changeset
596 if (jvmdi->SetEventHook(&saEventHook) != JVMDI_ERROR_NONE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
597 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
598 }
a61af66fc99e Initial load
duke
parents:
diff changeset
599 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
601 };