jvmtiTrace.cpp revision 0
1941N/A/*
1941N/A * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
1941N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1941N/A *
1941N/A * This code is free software; you can redistribute it and/or modify it
1941N/A * under the terms of the GNU General Public License version 2 only, as
1941N/A * published by the Free Software Foundation.
1941N/A *
1941N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1941N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1941N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1941N/A * version 2 for more details (a copy is included in the LICENSE file that
1941N/A * accompanied this code).
1941N/A *
1941N/A * You should have received a copy of the GNU General Public License version
1941N/A * 2 along with this work; if not, write to the Free Software Foundation,
1941N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1941N/A *
1941N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
1941N/A * CA 95054 USA or visit www.sun.com if you need additional information or
1941N/A * have any questions.
1941N/A *
1941N/A */
1941N/A
1941N/A# include "incls/_precompiled.incl"
1941N/A# include "incls/_jvmtiTrace.cpp.incl"
1941N/A
1941N/A//
1941N/A// class JvmtiTrace
1941N/A//
1941N/A// Support for JVMTI tracing code
1941N/A//
1941N/A// ------------
1941N/A// Usage:
1941N/A// -XX:TraceJVMTI=DESC,DESC,DESC
1941N/A//
1941N/A// DESC is DOMAIN ACTION KIND
1941N/A//
1941N/A// DOMAIN is function name
1941N/A// event name
1941N/A// "all" (all functions and events)
1941N/A// "func" (all functions except boring)
1941N/A// "allfunc" (all functions)
1941N/A// "event" (all events)
1941N/A// "ec" (event controller)
1941N/A//
1941N/A// ACTION is "+" (add)
1941N/A// "-" (remove)
1941N/A//
1941N/A// KIND is
1941N/A// for func
1941N/A// "i" (input params)
1941N/A// "e" (error returns)
1941N/A// "o" (output)
1941N/A// for event
1941N/A// "t" (event triggered aka posted)
1941N/A// "s" (event sent)
1941N/A//
1941N/A// Example:
1941N/A// -XX:TraceJVMTI=ec+,GetCallerFrame+ie,Breakpoint+s
1941N/A
1941N/A#ifdef JVMTI_TRACE
1941N/A
1941N/Abool JvmtiTrace::_initialized = false;
1941N/Abool JvmtiTrace::_on = false;
1941N/Abool JvmtiTrace::_trace_event_controller = false;
1941N/A
1941N/Avoid JvmtiTrace::initialize() {
1941N/A if (_initialized) {
1941N/A return;
1941N/A }
1941N/A SafeResourceMark rm;
1941N/A
1941N/A const char *very_end;
1941N/A const char *curr;
1941N/A if (strlen(TraceJVMTI)) {
1941N/A curr = TraceJVMTI;
1941N/A } else {
1941N/A curr = ""; // hack in fixed tracing here
1941N/A }
1941N/A very_end = curr + strlen(curr);
1941N/A while (curr < very_end) {
1941N/A const char *curr_end = strchr(curr, ',');
1941N/A if (curr_end == NULL) {
1941N/A curr_end = very_end;
1941N/A }
1941N/A const char *op_pos = strchr(curr, '+');
1941N/A const char *minus_pos = strchr(curr, '-');
1941N/A if (minus_pos != NULL && (minus_pos < op_pos || op_pos == NULL)) {
1941N/A op_pos = minus_pos;
1941N/A }
1941N/A char op;
1941N/A const char *flags = op_pos + 1;
1941N/A const char *flags_end = curr_end;
1941N/A if (op_pos == NULL || op_pos > curr_end) {
1941N/A flags = "ies";
1941N/A flags_end = flags + strlen(flags);
1941N/A op_pos = curr_end;
1941N/A op = '+';
1941N/A } else {
1941N/A op = *op_pos;
1941N/A }
1941N/A jbyte bits = 0;
1941N/A for (; flags < flags_end; ++flags) {
1941N/A switch (*flags) {
1941N/A case 'i':
1941N/A bits |= SHOW_IN;
1941N/A break;
1941N/A case 'I':
1941N/A bits |= SHOW_IN_DETAIL;
1941N/A break;
1941N/A case 'e':
1941N/A bits |= SHOW_ERROR;
1941N/A break;
1941N/A case 'o':
1941N/A bits |= SHOW_OUT;
1941N/A break;
1941N/A case 'O':
1941N/A bits |= SHOW_OUT_DETAIL;
1941N/A break;
1941N/A case 't':
1941N/A bits |= SHOW_EVENT_TRIGGER;
1941N/A break;
1941N/A case 's':
1941N/A bits |= SHOW_EVENT_SENT;
1941N/A break;
1941N/A default:
1941N/A tty->print_cr("Invalid trace flag '%c'", *flags);
1941N/A break;
1941N/A }
1941N/A }
1941N/A const int FUNC = 1;
1941N/A const int EXCLUDE = 2;
1941N/A const int ALL_FUNC = 4;
1941N/A const int EVENT = 8;
1941N/A const int ALL_EVENT = 16;
1941N/A int domain = 0;
1941N/A size_t len = op_pos - curr;
1941N/A if (op_pos == curr) {
1941N/A domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT | EXCLUDE;
1941N/A } else if (len==3 && strncmp(curr, "all", 3)==0) {
1941N/A domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT;
1941N/A } else if (len==7 && strncmp(curr, "allfunc", 7)==0) {
1941N/A domain = ALL_FUNC | FUNC;
1941N/A } else if (len==4 && strncmp(curr, "func", 4)==0) {
1941N/A domain = ALL_FUNC | FUNC | EXCLUDE;
1941N/A } else if (len==8 && strncmp(curr, "allevent", 8)==0) {
1941N/A domain = ALL_EVENT | EVENT;
1941N/A } else if (len==5 && strncmp(curr, "event", 5)==0) {
1941N/A domain = ALL_EVENT | EVENT;
1941N/A } else if (len==2 && strncmp(curr, "ec", 2)==0) {
1941N/A _trace_event_controller = true;
1941N/A tty->print_cr("JVMTI Tracing the event controller");
1941N/A } else {
1941N/A domain = FUNC | EVENT; // go searching
1941N/A }
int exclude_index = 0;
if (domain & FUNC) {
if (domain & ALL_FUNC) {
if (domain & EXCLUDE) {
tty->print("JVMTI Tracing all significant functions");
} else {
tty->print_cr("JVMTI Tracing all functions");
}
}
for (int i = 0; i <= _max_function_index; ++i) {
if (domain & EXCLUDE && i == _exclude_functions[exclude_index]) {
++exclude_index;
} else {
bool do_op = false;
if (domain & ALL_FUNC) {
do_op = true;
} else {
const char *fname = function_name(i);
if (fname != NULL) {
size_t fnlen = strlen(fname);
if (len==fnlen && strncmp(curr, fname, fnlen)==0) {
tty->print_cr("JVMTI Tracing the function: %s", fname);
do_op = true;
}
}
}
if (do_op) {
if (op == '+') {
_trace_flags[i] |= bits;
} else {
_trace_flags[i] &= ~bits;
}
_on = true;
}
}
}
}
if (domain & EVENT) {
if (domain & ALL_EVENT) {
tty->print_cr("JVMTI Tracing all events");
}
for (int i = 0; i <= _max_event_index; ++i) {
bool do_op = false;
if (domain & ALL_EVENT) {
do_op = true;
} else {
const char *ename = event_name(i);
if (ename != NULL) {
size_t evtlen = strlen(ename);
if (len==evtlen && strncmp(curr, ename, evtlen)==0) {
tty->print_cr("JVMTI Tracing the event: %s", ename);
do_op = true;
}
}
}
if (do_op) {
if (op == '+') {
_event_trace_flags[i] |= bits;
} else {
_event_trace_flags[i] &= ~bits;
}
_on = true;
}
}
}
if (!_on && (domain & (FUNC|EVENT))) {
tty->print_cr("JVMTI Trace domain not found");
}
curr = curr_end + 1;
}
_initialized = true;
}
void JvmtiTrace::shutdown() {
int i;
_on = false;
_trace_event_controller = false;
for (i = 0; i <= _max_function_index; ++i) {
_trace_flags[i] = 0;
}
for (i = 0; i <= _max_event_index; ++i) {
_event_trace_flags[i] = 0;
}
}
const char* JvmtiTrace::enum_name(const char** names, const jint* values, jint value) {
for (int index = 0; names[index] != 0; ++index) {
if (values[index] == value) {
return names[index];
}
}
return "*INVALID-ENUM-VALUE*";
}
// return a valid string no matter what state the thread is in
const char *JvmtiTrace::safe_get_thread_name(Thread *thread) {
if (thread == NULL) {
return "NULL";
}
if (!thread->is_Java_thread()) {
return thread->name();
}
JavaThread *java_thread = (JavaThread *)thread;
oop threadObj = java_thread->threadObj();
if (threadObj == NULL) {
return "NULL";
}
typeArrayOop name = java_lang_Thread::name(threadObj);
if (name == NULL) {
return "<NOT FILLED IN>";
}
return UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length());
}
// return the name of the current thread
const char *JvmtiTrace::safe_get_current_thread_name() {
if (JvmtiEnv::is_vm_live()) {
return JvmtiTrace::safe_get_thread_name(Thread::current());
} else {
return "VM not live";
}
}
// return a valid string no matter what the state of k_mirror
const char * JvmtiTrace::get_class_name(oop k_mirror) {
if (java_lang_Class::is_primitive(k_mirror)) {
return "primitive";
}
klassOop k_oop = java_lang_Class::as_klassOop(k_mirror);
if (k_oop == NULL) {
return "INVALID";
}
return Klass::cast(k_oop)->external_name();
}
#endif /*JVMTI_TRACE */