Tue, 17 Oct 2017 12:58:25 +0800
merge
1 /*
2 * Copyright (c) 2003, 2012, 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 */
25 #include "precompiled.hpp"
26 #include "jvmtifiles/jvmtiEnv.hpp"
27 #include "prims/jvmtiTrace.hpp"
29 //
30 // class JvmtiTrace
31 //
32 // Support for JVMTI tracing code
33 //
34 // ------------
35 // Usage:
36 // -XX:TraceJVMTI=DESC,DESC,DESC
37 //
38 // DESC is DOMAIN ACTION KIND
39 //
40 // DOMAIN is function name
41 // event name
42 // "all" (all functions and events)
43 // "func" (all functions except boring)
44 // "allfunc" (all functions)
45 // "event" (all events)
46 // "ec" (event controller)
47 //
48 // ACTION is "+" (add)
49 // "-" (remove)
50 //
51 // KIND is
52 // for func
53 // "i" (input params)
54 // "e" (error returns)
55 // "o" (output)
56 // for event
57 // "t" (event triggered aka posted)
58 // "s" (event sent)
59 //
60 // Example:
61 // -XX:TraceJVMTI=ec+,GetCallerFrame+ie,Breakpoint+s
63 #ifdef JVMTI_TRACE
65 bool JvmtiTrace::_initialized = false;
66 bool JvmtiTrace::_on = false;
67 bool JvmtiTrace::_trace_event_controller = false;
69 void JvmtiTrace::initialize() {
70 if (_initialized) {
71 return;
72 }
73 SafeResourceMark rm;
75 const char *very_end;
76 const char *curr;
77 if (TraceJVMTI != NULL) {
78 curr = TraceJVMTI;
79 } else {
80 curr = ""; // hack in fixed tracing here
81 }
82 very_end = curr + strlen(curr);
83 while (curr < very_end) {
84 const char *curr_end = strchr(curr, ',');
85 if (curr_end == NULL) {
86 curr_end = very_end;
87 }
88 const char *op_pos = strchr(curr, '+');
89 const char *minus_pos = strchr(curr, '-');
90 if (minus_pos != NULL && (minus_pos < op_pos || op_pos == NULL)) {
91 op_pos = minus_pos;
92 }
93 char op;
94 const char *flags = op_pos + 1;
95 const char *flags_end = curr_end;
96 if (op_pos == NULL || op_pos > curr_end) {
97 flags = "ies";
98 flags_end = flags + strlen(flags);
99 op_pos = curr_end;
100 op = '+';
101 } else {
102 op = *op_pos;
103 }
104 jbyte bits = 0;
105 for (; flags < flags_end; ++flags) {
106 switch (*flags) {
107 case 'i':
108 bits |= SHOW_IN;
109 break;
110 case 'I':
111 bits |= SHOW_IN_DETAIL;
112 break;
113 case 'e':
114 bits |= SHOW_ERROR;
115 break;
116 case 'o':
117 bits |= SHOW_OUT;
118 break;
119 case 'O':
120 bits |= SHOW_OUT_DETAIL;
121 break;
122 case 't':
123 bits |= SHOW_EVENT_TRIGGER;
124 break;
125 case 's':
126 bits |= SHOW_EVENT_SENT;
127 break;
128 default:
129 tty->print_cr("Invalid trace flag '%c'", *flags);
130 break;
131 }
132 }
133 const int FUNC = 1;
134 const int EXCLUDE = 2;
135 const int ALL_FUNC = 4;
136 const int EVENT = 8;
137 const int ALL_EVENT = 16;
138 int domain = 0;
139 size_t len = op_pos - curr;
140 if (op_pos == curr) {
141 domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT | EXCLUDE;
142 } else if (len==3 && strncmp(curr, "all", 3)==0) {
143 domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT;
144 } else if (len==7 && strncmp(curr, "allfunc", 7)==0) {
145 domain = ALL_FUNC | FUNC;
146 } else if (len==4 && strncmp(curr, "func", 4)==0) {
147 domain = ALL_FUNC | FUNC | EXCLUDE;
148 } else if (len==8 && strncmp(curr, "allevent", 8)==0) {
149 domain = ALL_EVENT | EVENT;
150 } else if (len==5 && strncmp(curr, "event", 5)==0) {
151 domain = ALL_EVENT | EVENT;
152 } else if (len==2 && strncmp(curr, "ec", 2)==0) {
153 _trace_event_controller = true;
154 tty->print_cr("JVMTI Tracing the event controller");
155 } else {
156 domain = FUNC | EVENT; // go searching
157 }
159 int exclude_index = 0;
160 if (domain & FUNC) {
161 if (domain & ALL_FUNC) {
162 if (domain & EXCLUDE) {
163 tty->print("JVMTI Tracing all significant functions");
164 } else {
165 tty->print_cr("JVMTI Tracing all functions");
166 }
167 }
168 for (int i = 0; i <= _max_function_index; ++i) {
169 if (domain & EXCLUDE && i == _exclude_functions[exclude_index]) {
170 ++exclude_index;
171 } else {
172 bool do_op = false;
173 if (domain & ALL_FUNC) {
174 do_op = true;
175 } else {
176 const char *fname = function_name(i);
177 if (fname != NULL) {
178 size_t fnlen = strlen(fname);
179 if (len==fnlen && strncmp(curr, fname, fnlen)==0) {
180 tty->print_cr("JVMTI Tracing the function: %s", fname);
181 do_op = true;
182 }
183 }
184 }
185 if (do_op) {
186 if (op == '+') {
187 _trace_flags[i] |= bits;
188 } else {
189 _trace_flags[i] &= ~bits;
190 }
191 _on = true;
192 }
193 }
194 }
195 }
196 if (domain & EVENT) {
197 if (domain & ALL_EVENT) {
198 tty->print_cr("JVMTI Tracing all events");
199 }
200 for (int i = 0; i <= _max_event_index; ++i) {
201 bool do_op = false;
202 if (domain & ALL_EVENT) {
203 do_op = true;
204 } else {
205 const char *ename = event_name(i);
206 if (ename != NULL) {
207 size_t evtlen = strlen(ename);
208 if (len==evtlen && strncmp(curr, ename, evtlen)==0) {
209 tty->print_cr("JVMTI Tracing the event: %s", ename);
210 do_op = true;
211 }
212 }
213 }
214 if (do_op) {
215 if (op == '+') {
216 _event_trace_flags[i] |= bits;
217 } else {
218 _event_trace_flags[i] &= ~bits;
219 }
220 _on = true;
221 }
222 }
223 }
224 if (!_on && (domain & (FUNC|EVENT))) {
225 tty->print_cr("JVMTI Trace domain not found");
226 }
227 curr = curr_end + 1;
228 }
229 _initialized = true;
230 }
233 void JvmtiTrace::shutdown() {
234 int i;
235 _on = false;
236 _trace_event_controller = false;
237 for (i = 0; i <= _max_function_index; ++i) {
238 _trace_flags[i] = 0;
239 }
240 for (i = 0; i <= _max_event_index; ++i) {
241 _event_trace_flags[i] = 0;
242 }
243 }
246 const char* JvmtiTrace::enum_name(const char** names, const jint* values, jint value) {
247 for (int index = 0; names[index] != 0; ++index) {
248 if (values[index] == value) {
249 return names[index];
250 }
251 }
252 return "*INVALID-ENUM-VALUE*";
253 }
256 // return a valid string no matter what state the thread is in
257 const char *JvmtiTrace::safe_get_thread_name(Thread *thread) {
258 if (thread == NULL) {
259 return "NULL";
260 }
261 if (!thread->is_Java_thread()) {
262 return thread->name();
263 }
264 JavaThread *java_thread = (JavaThread *)thread;
265 oop threadObj = java_thread->threadObj();
266 if (threadObj == NULL) {
267 return "NULL";
268 }
269 typeArrayOop name = java_lang_Thread::name(threadObj);
270 if (name == NULL) {
271 return "<NOT FILLED IN>";
272 }
273 return UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length());
274 }
277 // return the name of the current thread
278 const char *JvmtiTrace::safe_get_current_thread_name() {
279 if (JvmtiEnv::is_vm_live()) {
280 return JvmtiTrace::safe_get_thread_name(Thread::current());
281 } else {
282 return "VM not live";
283 }
284 }
286 // return a valid string no matter what the state of k_mirror
287 const char * JvmtiTrace::get_class_name(oop k_mirror) {
288 if (java_lang_Class::is_primitive(k_mirror)) {
289 return "primitive";
290 }
291 Klass* k_oop = java_lang_Class::as_Klass(k_mirror);
292 if (k_oop == NULL) {
293 return "INVALID";
294 }
295 return k_oop->external_name();
296 }
298 #endif /*JVMTI_TRACE */