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