src/share/vm/prims/jvmtiTrace.cpp

Wed, 27 Aug 2014 08:19:12 -0400

author
zgu
date
Wed, 27 Aug 2014 08:19:12 -0400
changeset 7074
833b0f92429a
parent 4278
070d523b96a7
child 6876
710a3c8b516e
child 8288
efe013052465
permissions
-rw-r--r--

8046598: Scalable Native memory tracking development
Summary: Enhance scalability of native memory tracking
Reviewed-by: coleenp, ctornqvi, gtriantafill

duke@435 1 /*
coleenp@4037 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "jvmtifiles/jvmtiEnv.hpp"
stefank@2314 27 #include "prims/jvmtiTrace.hpp"
duke@435 28
duke@435 29 //
duke@435 30 // class JvmtiTrace
duke@435 31 //
duke@435 32 // Support for JVMTI tracing code
duke@435 33 //
duke@435 34 // ------------
duke@435 35 // Usage:
duke@435 36 // -XX:TraceJVMTI=DESC,DESC,DESC
duke@435 37 //
duke@435 38 // DESC is DOMAIN ACTION KIND
duke@435 39 //
duke@435 40 // DOMAIN is function name
duke@435 41 // event name
duke@435 42 // "all" (all functions and events)
duke@435 43 // "func" (all functions except boring)
duke@435 44 // "allfunc" (all functions)
duke@435 45 // "event" (all events)
duke@435 46 // "ec" (event controller)
duke@435 47 //
duke@435 48 // ACTION is "+" (add)
duke@435 49 // "-" (remove)
duke@435 50 //
duke@435 51 // KIND is
duke@435 52 // for func
duke@435 53 // "i" (input params)
duke@435 54 // "e" (error returns)
duke@435 55 // "o" (output)
duke@435 56 // for event
duke@435 57 // "t" (event triggered aka posted)
duke@435 58 // "s" (event sent)
duke@435 59 //
duke@435 60 // Example:
duke@435 61 // -XX:TraceJVMTI=ec+,GetCallerFrame+ie,Breakpoint+s
duke@435 62
duke@435 63 #ifdef JVMTI_TRACE
duke@435 64
duke@435 65 bool JvmtiTrace::_initialized = false;
duke@435 66 bool JvmtiTrace::_on = false;
duke@435 67 bool JvmtiTrace::_trace_event_controller = false;
duke@435 68
duke@435 69 void JvmtiTrace::initialize() {
duke@435 70 if (_initialized) {
duke@435 71 return;
duke@435 72 }
duke@435 73 SafeResourceMark rm;
duke@435 74
duke@435 75 const char *very_end;
duke@435 76 const char *curr;
never@805 77 if (TraceJVMTI != NULL) {
duke@435 78 curr = TraceJVMTI;
duke@435 79 } else {
duke@435 80 curr = ""; // hack in fixed tracing here
duke@435 81 }
duke@435 82 very_end = curr + strlen(curr);
duke@435 83 while (curr < very_end) {
duke@435 84 const char *curr_end = strchr(curr, ',');
duke@435 85 if (curr_end == NULL) {
duke@435 86 curr_end = very_end;
duke@435 87 }
duke@435 88 const char *op_pos = strchr(curr, '+');
duke@435 89 const char *minus_pos = strchr(curr, '-');
duke@435 90 if (minus_pos != NULL && (minus_pos < op_pos || op_pos == NULL)) {
duke@435 91 op_pos = minus_pos;
duke@435 92 }
duke@435 93 char op;
duke@435 94 const char *flags = op_pos + 1;
duke@435 95 const char *flags_end = curr_end;
duke@435 96 if (op_pos == NULL || op_pos > curr_end) {
duke@435 97 flags = "ies";
duke@435 98 flags_end = flags + strlen(flags);
duke@435 99 op_pos = curr_end;
duke@435 100 op = '+';
duke@435 101 } else {
duke@435 102 op = *op_pos;
duke@435 103 }
duke@435 104 jbyte bits = 0;
duke@435 105 for (; flags < flags_end; ++flags) {
duke@435 106 switch (*flags) {
duke@435 107 case 'i':
duke@435 108 bits |= SHOW_IN;
duke@435 109 break;
duke@435 110 case 'I':
duke@435 111 bits |= SHOW_IN_DETAIL;
duke@435 112 break;
duke@435 113 case 'e':
duke@435 114 bits |= SHOW_ERROR;
duke@435 115 break;
duke@435 116 case 'o':
duke@435 117 bits |= SHOW_OUT;
duke@435 118 break;
duke@435 119 case 'O':
duke@435 120 bits |= SHOW_OUT_DETAIL;
duke@435 121 break;
duke@435 122 case 't':
duke@435 123 bits |= SHOW_EVENT_TRIGGER;
duke@435 124 break;
duke@435 125 case 's':
duke@435 126 bits |= SHOW_EVENT_SENT;
duke@435 127 break;
duke@435 128 default:
duke@435 129 tty->print_cr("Invalid trace flag '%c'", *flags);
duke@435 130 break;
duke@435 131 }
duke@435 132 }
duke@435 133 const int FUNC = 1;
duke@435 134 const int EXCLUDE = 2;
duke@435 135 const int ALL_FUNC = 4;
duke@435 136 const int EVENT = 8;
duke@435 137 const int ALL_EVENT = 16;
duke@435 138 int domain = 0;
duke@435 139 size_t len = op_pos - curr;
duke@435 140 if (op_pos == curr) {
duke@435 141 domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT | EXCLUDE;
duke@435 142 } else if (len==3 && strncmp(curr, "all", 3)==0) {
duke@435 143 domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT;
duke@435 144 } else if (len==7 && strncmp(curr, "allfunc", 7)==0) {
duke@435 145 domain = ALL_FUNC | FUNC;
duke@435 146 } else if (len==4 && strncmp(curr, "func", 4)==0) {
duke@435 147 domain = ALL_FUNC | FUNC | EXCLUDE;
duke@435 148 } else if (len==8 && strncmp(curr, "allevent", 8)==0) {
duke@435 149 domain = ALL_EVENT | EVENT;
duke@435 150 } else if (len==5 && strncmp(curr, "event", 5)==0) {
duke@435 151 domain = ALL_EVENT | EVENT;
duke@435 152 } else if (len==2 && strncmp(curr, "ec", 2)==0) {
duke@435 153 _trace_event_controller = true;
duke@435 154 tty->print_cr("JVMTI Tracing the event controller");
duke@435 155 } else {
duke@435 156 domain = FUNC | EVENT; // go searching
duke@435 157 }
duke@435 158
duke@435 159 int exclude_index = 0;
duke@435 160 if (domain & FUNC) {
duke@435 161 if (domain & ALL_FUNC) {
duke@435 162 if (domain & EXCLUDE) {
duke@435 163 tty->print("JVMTI Tracing all significant functions");
duke@435 164 } else {
duke@435 165 tty->print_cr("JVMTI Tracing all functions");
duke@435 166 }
duke@435 167 }
duke@435 168 for (int i = 0; i <= _max_function_index; ++i) {
duke@435 169 if (domain & EXCLUDE && i == _exclude_functions[exclude_index]) {
duke@435 170 ++exclude_index;
duke@435 171 } else {
duke@435 172 bool do_op = false;
duke@435 173 if (domain & ALL_FUNC) {
duke@435 174 do_op = true;
duke@435 175 } else {
duke@435 176 const char *fname = function_name(i);
duke@435 177 if (fname != NULL) {
duke@435 178 size_t fnlen = strlen(fname);
duke@435 179 if (len==fnlen && strncmp(curr, fname, fnlen)==0) {
duke@435 180 tty->print_cr("JVMTI Tracing the function: %s", fname);
duke@435 181 do_op = true;
duke@435 182 }
duke@435 183 }
duke@435 184 }
duke@435 185 if (do_op) {
duke@435 186 if (op == '+') {
duke@435 187 _trace_flags[i] |= bits;
duke@435 188 } else {
duke@435 189 _trace_flags[i] &= ~bits;
duke@435 190 }
duke@435 191 _on = true;
duke@435 192 }
duke@435 193 }
duke@435 194 }
duke@435 195 }
duke@435 196 if (domain & EVENT) {
duke@435 197 if (domain & ALL_EVENT) {
duke@435 198 tty->print_cr("JVMTI Tracing all events");
duke@435 199 }
duke@435 200 for (int i = 0; i <= _max_event_index; ++i) {
duke@435 201 bool do_op = false;
duke@435 202 if (domain & ALL_EVENT) {
duke@435 203 do_op = true;
duke@435 204 } else {
duke@435 205 const char *ename = event_name(i);
duke@435 206 if (ename != NULL) {
duke@435 207 size_t evtlen = strlen(ename);
duke@435 208 if (len==evtlen && strncmp(curr, ename, evtlen)==0) {
duke@435 209 tty->print_cr("JVMTI Tracing the event: %s", ename);
duke@435 210 do_op = true;
duke@435 211 }
duke@435 212 }
duke@435 213 }
duke@435 214 if (do_op) {
duke@435 215 if (op == '+') {
duke@435 216 _event_trace_flags[i] |= bits;
duke@435 217 } else {
duke@435 218 _event_trace_flags[i] &= ~bits;
duke@435 219 }
duke@435 220 _on = true;
duke@435 221 }
duke@435 222 }
duke@435 223 }
duke@435 224 if (!_on && (domain & (FUNC|EVENT))) {
duke@435 225 tty->print_cr("JVMTI Trace domain not found");
duke@435 226 }
duke@435 227 curr = curr_end + 1;
duke@435 228 }
duke@435 229 _initialized = true;
duke@435 230 }
duke@435 231
duke@435 232
duke@435 233 void JvmtiTrace::shutdown() {
duke@435 234 int i;
duke@435 235 _on = false;
duke@435 236 _trace_event_controller = false;
duke@435 237 for (i = 0; i <= _max_function_index; ++i) {
duke@435 238 _trace_flags[i] = 0;
duke@435 239 }
duke@435 240 for (i = 0; i <= _max_event_index; ++i) {
duke@435 241 _event_trace_flags[i] = 0;
duke@435 242 }
duke@435 243 }
duke@435 244
duke@435 245
duke@435 246 const char* JvmtiTrace::enum_name(const char** names, const jint* values, jint value) {
duke@435 247 for (int index = 0; names[index] != 0; ++index) {
duke@435 248 if (values[index] == value) {
duke@435 249 return names[index];
duke@435 250 }
duke@435 251 }
duke@435 252 return "*INVALID-ENUM-VALUE*";
duke@435 253 }
duke@435 254
duke@435 255
duke@435 256 // return a valid string no matter what state the thread is in
duke@435 257 const char *JvmtiTrace::safe_get_thread_name(Thread *thread) {
duke@435 258 if (thread == NULL) {
duke@435 259 return "NULL";
duke@435 260 }
duke@435 261 if (!thread->is_Java_thread()) {
duke@435 262 return thread->name();
duke@435 263 }
duke@435 264 JavaThread *java_thread = (JavaThread *)thread;
duke@435 265 oop threadObj = java_thread->threadObj();
duke@435 266 if (threadObj == NULL) {
duke@435 267 return "NULL";
duke@435 268 }
duke@435 269 typeArrayOop name = java_lang_Thread::name(threadObj);
duke@435 270 if (name == NULL) {
duke@435 271 return "<NOT FILLED IN>";
duke@435 272 }
duke@435 273 return UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length());
duke@435 274 }
duke@435 275
duke@435 276
duke@435 277 // return the name of the current thread
duke@435 278 const char *JvmtiTrace::safe_get_current_thread_name() {
duke@435 279 if (JvmtiEnv::is_vm_live()) {
duke@435 280 return JvmtiTrace::safe_get_thread_name(Thread::current());
duke@435 281 } else {
duke@435 282 return "VM not live";
duke@435 283 }
duke@435 284 }
duke@435 285
duke@435 286 // return a valid string no matter what the state of k_mirror
duke@435 287 const char * JvmtiTrace::get_class_name(oop k_mirror) {
duke@435 288 if (java_lang_Class::is_primitive(k_mirror)) {
duke@435 289 return "primitive";
duke@435 290 }
coleenp@4037 291 Klass* k_oop = java_lang_Class::as_Klass(k_mirror);
duke@435 292 if (k_oop == NULL) {
duke@435 293 return "INVALID";
duke@435 294 }
hseigel@4278 295 return k_oop->external_name();
duke@435 296 }
duke@435 297
duke@435 298 #endif /*JVMTI_TRACE */

mercurial