jvmtiEventController.cpp 39.0 KB
Newer Older
D
duke 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
/*
 * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

# include "incls/_precompiled.incl"
# include "incls/_jvmtiEventController.cpp.incl"

#ifdef JVMTI_TRACE
#define EC_TRACE(out) if (JvmtiTrace::trace_event_controller()) { SafeResourceMark rm; tty->print_cr out; } while (0)
#else
#define EC_TRACE(out)
#endif /*JVMTI_TRACE */

// bits for standard events

static const jlong  SINGLE_STEP_BIT = (((jlong)1) << (JVMTI_EVENT_SINGLE_STEP - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  FRAME_POP_BIT = (((jlong)1) << (JVMTI_EVENT_FRAME_POP - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  BREAKPOINT_BIT = (((jlong)1) << (JVMTI_EVENT_BREAKPOINT - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  FIELD_ACCESS_BIT = (((jlong)1) << (JVMTI_EVENT_FIELD_ACCESS - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  FIELD_MODIFICATION_BIT = (((jlong)1) << (JVMTI_EVENT_FIELD_MODIFICATION - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  METHOD_ENTRY_BIT = (((jlong)1) << (JVMTI_EVENT_METHOD_ENTRY - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  METHOD_EXIT_BIT = (((jlong)1) << (JVMTI_EVENT_METHOD_EXIT - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  CLASS_FILE_LOAD_HOOK_BIT = (((jlong)1) << (JVMTI_EVENT_CLASS_FILE_LOAD_HOOK - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  NATIVE_METHOD_BIND_BIT = (((jlong)1) << (JVMTI_EVENT_NATIVE_METHOD_BIND - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  VM_START_BIT = (((jlong)1) << (JVMTI_EVENT_VM_START - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  VM_INIT_BIT = (((jlong)1) << (JVMTI_EVENT_VM_INIT - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  VM_DEATH_BIT = (((jlong)1) << (JVMTI_EVENT_VM_DEATH - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  CLASS_LOAD_BIT = (((jlong)1) << (JVMTI_EVENT_CLASS_LOAD - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  CLASS_PREPARE_BIT = (((jlong)1) << (JVMTI_EVENT_CLASS_PREPARE - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  THREAD_START_BIT = (((jlong)1) << (JVMTI_EVENT_THREAD_START - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  THREAD_END_BIT = (((jlong)1) << (JVMTI_EVENT_THREAD_END - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  EXCEPTION_THROW_BIT = (((jlong)1) << (JVMTI_EVENT_EXCEPTION - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  EXCEPTION_CATCH_BIT = (((jlong)1) << (JVMTI_EVENT_EXCEPTION_CATCH - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  MONITOR_CONTENDED_ENTER_BIT = (((jlong)1) << (JVMTI_EVENT_MONITOR_CONTENDED_ENTER - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  MONITOR_CONTENDED_ENTERED_BIT = (((jlong)1) << (JVMTI_EVENT_MONITOR_CONTENDED_ENTERED - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  MONITOR_WAIT_BIT = (((jlong)1) << (JVMTI_EVENT_MONITOR_WAIT - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  MONITOR_WAITED_BIT = (((jlong)1) << (JVMTI_EVENT_MONITOR_WAITED - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  DYNAMIC_CODE_GENERATED_BIT = (((jlong)1) << (JVMTI_EVENT_DYNAMIC_CODE_GENERATED - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  DATA_DUMP_BIT = (((jlong)1) << (JVMTI_EVENT_DATA_DUMP_REQUEST - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  COMPILED_METHOD_LOAD_BIT = (((jlong)1) << (JVMTI_EVENT_COMPILED_METHOD_LOAD - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  COMPILED_METHOD_UNLOAD_BIT = (((jlong)1) << (JVMTI_EVENT_COMPILED_METHOD_UNLOAD - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  GARBAGE_COLLECTION_START_BIT = (((jlong)1) << (JVMTI_EVENT_GARBAGE_COLLECTION_START - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  GARBAGE_COLLECTION_FINISH_BIT = (((jlong)1) << (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  OBJECT_FREE_BIT = (((jlong)1) << (JVMTI_EVENT_OBJECT_FREE - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  RESOURCE_EXHAUSTED_BIT = (((jlong)1) << (JVMTI_EVENT_RESOURCE_EXHAUSTED - TOTAL_MIN_EVENT_TYPE_VAL));
static const jlong  VM_OBJECT_ALLOC_BIT = (((jlong)1) << (JVMTI_EVENT_VM_OBJECT_ALLOC - TOTAL_MIN_EVENT_TYPE_VAL));

// bits for extension events
static const jlong  CLASS_UNLOAD_BIT = (((jlong)1) << (EXT_EVENT_CLASS_UNLOAD - TOTAL_MIN_EVENT_TYPE_VAL));


static const jlong  MONITOR_BITS = MONITOR_CONTENDED_ENTER_BIT | MONITOR_CONTENDED_ENTERED_BIT |
                          MONITOR_WAIT_BIT | MONITOR_WAITED_BIT;
static const jlong  EXCEPTION_BITS = EXCEPTION_THROW_BIT | EXCEPTION_CATCH_BIT;
static const jlong  INTERP_EVENT_BITS =  SINGLE_STEP_BIT | METHOD_ENTRY_BIT | METHOD_EXIT_BIT |
                                FRAME_POP_BIT | FIELD_ACCESS_BIT | FIELD_MODIFICATION_BIT;
static const jlong  THREAD_FILTERED_EVENT_BITS = INTERP_EVENT_BITS | EXCEPTION_BITS | MONITOR_BITS |
                                        BREAKPOINT_BIT | CLASS_LOAD_BIT | CLASS_PREPARE_BIT | THREAD_END_BIT;
static const jlong  NEED_THREAD_LIFE_EVENTS = THREAD_FILTERED_EVENT_BITS | THREAD_START_BIT;
static const jlong  EARLY_EVENT_BITS = CLASS_FILE_LOAD_HOOK_BIT |
                               VM_START_BIT | VM_INIT_BIT | VM_DEATH_BIT | NATIVE_METHOD_BIND_BIT |
                               THREAD_START_BIT | THREAD_END_BIT |
                               DYNAMIC_CODE_GENERATED_BIT;
static const jlong  GLOBAL_EVENT_BITS = ~THREAD_FILTERED_EVENT_BITS;


///////////////////////////////////////////////////////////////
//
// JvmtiEventEnabled
//

JvmtiEventEnabled::JvmtiEventEnabled() {
  clear();
}


void JvmtiEventEnabled::clear() {
  _enabled_bits = 0;
#ifndef PRODUCT
  _init_guard = JEE_INIT_GUARD;
#endif
}

void JvmtiEventEnabled::set_enabled(jvmtiEvent event_type, bool enabled) {
  jlong bits = get_bits();
  jlong mask = bit_for(event_type);
  if (enabled) {
    bits |= mask;
  } else {
    bits &= ~mask;
  }
  set_bits(bits);
}


///////////////////////////////////////////////////////////////
//
// JvmtiEnvThreadEventEnable
//

JvmtiEnvThreadEventEnable::JvmtiEnvThreadEventEnable() {
  _event_user_enabled.clear();
  _event_enabled.clear();
}


JvmtiEnvThreadEventEnable::~JvmtiEnvThreadEventEnable() {
  _event_user_enabled.clear();
  _event_enabled.clear();
}


///////////////////////////////////////////////////////////////
//
// JvmtiThreadEventEnable
//

JvmtiThreadEventEnable::JvmtiThreadEventEnable() {
  _event_enabled.clear();
}


JvmtiThreadEventEnable::~JvmtiThreadEventEnable() {
  _event_enabled.clear();
}


///////////////////////////////////////////////////////////////
//
// JvmtiEnvEventEnable
//

JvmtiEnvEventEnable::JvmtiEnvEventEnable() {
  _event_user_enabled.clear();
  _event_callback_enabled.clear();
  _event_enabled.clear();
}


JvmtiEnvEventEnable::~JvmtiEnvEventEnable() {
  _event_user_enabled.clear();
  _event_callback_enabled.clear();
  _event_enabled.clear();
}


///////////////////////////////////////////////////////////////
//
// VM_EnterInterpOnlyMode
//

class VM_EnterInterpOnlyMode : public VM_Operation {
private:
  JvmtiThreadState *_state;

public:
  VM_EnterInterpOnlyMode(JvmtiThreadState *state);

  bool allow_nested_vm_operations() const        { return true; }
  VMOp_Type type() const { return VMOp_EnterInterpOnlyMode; }
  void doit();

  // to do: this same function is in jvmtiImpl - should be in one place
  bool can_be_deoptimized(vframe* vf) {
    return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized());
  }
};

VM_EnterInterpOnlyMode::VM_EnterInterpOnlyMode(JvmtiThreadState *state)
  : _state(state)
{
}


void VM_EnterInterpOnlyMode::doit() {
  // Set up the current stack depth for later tracking
  _state->invalidate_cur_stack_depth();

  _state->enter_interp_only_mode();

  JavaThread *thread = _state->get_thread();
  if (thread->has_last_Java_frame()) {
    // If running in fullspeed mode, single stepping is implemented
    // as follows: first, the interpreter does not dispatch to
    // compiled code for threads that have single stepping enabled;
    // second, we deoptimize all methods on the thread's stack when
    // interpreted-only mode is enabled the first time for a given
    // thread (nothing to do if no Java frames yet).
    int num_marked = 0;
    ResourceMark resMark;
    RegisterMap rm(thread, false);
    for (vframe* vf = thread->last_java_vframe(&rm); vf; vf = vf->sender()) {
      if (can_be_deoptimized(vf)) {
        ((compiledVFrame*) vf)->code()->mark_for_deoptimization();
        ++num_marked;
      }
    }
    if (num_marked > 0) {
      VM_Deoptimize op;
      VMThread::execute(&op);
    }
  }
}


///////////////////////////////////////////////////////////////
//
// VM_ChangeSingleStep
//

class VM_ChangeSingleStep : public VM_Operation {
private:
  bool _on;

public:
  VM_ChangeSingleStep(bool on);
  VMOp_Type type() const                         { return VMOp_ChangeSingleStep; }
  bool allow_nested_vm_operations() const        { return true; }
  void doit();   // method definition is after definition of JvmtiEventControllerPrivate because of scoping
};


VM_ChangeSingleStep::VM_ChangeSingleStep(bool on)
  : _on(on != 0)
{
}




///////////////////////////////////////////////////////////////
//
// JvmtiEventControllerPrivate
//
// Private internal implementation methods for JvmtiEventController.
//
// These methods are thread safe either because they are called
// in early VM initialization which is single threaded, or they
// hold the JvmtiThreadState_lock.
//

class JvmtiEventControllerPrivate : public AllStatic {
  static bool _initialized;
public:
  static void set_should_post_single_step(bool on);
  static void enter_interp_only_mode(JvmtiThreadState *state);
  static void leave_interp_only_mode(JvmtiThreadState *state);
  static void recompute_enabled();
  static jlong recompute_env_enabled(JvmtiEnvBase* env);
  static jlong recompute_env_thread_enabled(JvmtiEnvThreadState* ets, JvmtiThreadState* state);
  static jlong recompute_thread_enabled(JvmtiThreadState *state);
  static void event_init();

  static void set_user_enabled(JvmtiEnvBase *env, JavaThread *thread,
                        jvmtiEvent event_type, bool enabled);
  static void set_event_callbacks(JvmtiEnvBase *env,
                                  const jvmtiEventCallbacks* callbacks,
                                  jint size_of_callbacks);

  static void set_extension_event_callback(JvmtiEnvBase *env,
                                           jint extension_event_index,
                                           jvmtiExtensionEvent callback);

  static void set_frame_pop(JvmtiEnvThreadState *env_thread, JvmtiFramePop fpop);
  static void clear_frame_pop(JvmtiEnvThreadState *env_thread, JvmtiFramePop fpop);
  static void clear_to_frame_pop(JvmtiEnvThreadState *env_thread, JvmtiFramePop fpop);
  static void change_field_watch(jvmtiEvent event_type, bool added);

  static void thread_started(JavaThread *thread);
  static void thread_ended(JavaThread *thread);

  static void env_initialize(JvmtiEnvBase *env);
  static void env_dispose(JvmtiEnvBase *env);

  static void vm_start();
  static void vm_init();
  static void vm_death();

  static void trace_changed(JvmtiThreadState *state, jlong now_enabled, jlong changed);
  static void trace_changed(jlong now_enabled, jlong changed);
};

bool JvmtiEventControllerPrivate::_initialized = false;

void JvmtiEventControllerPrivate::set_should_post_single_step(bool on) {
  // we have permission to do this, VM op doesn't
  JvmtiExport::set_should_post_single_step(on);
}


// This change must always be occur when at a safepoint.
// Being at a safepoint causes the interpreter to use the
// safepoint dispatch table which we overload to find single
// step points.  Just to be sure that it has been set, we
// call notice_safepoints when turning on single stepping.
// When we leave our current safepoint, should_post_single_step
// will be checked by the interpreter, and the table kept
// or changed accordingly.
void VM_ChangeSingleStep::doit() {
  JvmtiEventControllerPrivate::set_should_post_single_step(_on);
  if (_on) {
    Interpreter::notice_safepoints();
  }
}


void JvmtiEventControllerPrivate::enter_interp_only_mode(JvmtiThreadState *state) {
  EC_TRACE(("JVMTI [%s] # Entering interpreter only mode",
            JvmtiTrace::safe_get_thread_name(state->get_thread())));

  VM_EnterInterpOnlyMode op(state);
  VMThread::execute(&op);
}


void
JvmtiEventControllerPrivate::leave_interp_only_mode(JvmtiThreadState *state) {
  EC_TRACE(("JVMTI [%s] # Leaving interpreter only mode",
            JvmtiTrace::safe_get_thread_name(state->get_thread())));
  state->leave_interp_only_mode();
}


void
JvmtiEventControllerPrivate::trace_changed(JvmtiThreadState *state, jlong now_enabled, jlong changed) {
#ifdef JVMTI_TRACE
  if (JvmtiTrace::trace_event_controller()) {
    SafeResourceMark rm;
    // traces standard events only
    for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) {
      jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei);
      if (changed & bit) {
        // it changed, print it
        tty->print_cr("JVMTI [%s] # %s event %s",
                      JvmtiTrace::safe_get_thread_name(state->get_thread()),
                      (now_enabled & bit)? "Enabling" : "Disabling", JvmtiTrace::event_name((jvmtiEvent)ei));
      }
    }
  }
#endif /*JVMTI_TRACE */
}


void
JvmtiEventControllerPrivate::trace_changed(jlong now_enabled, jlong changed) {
#ifdef JVMTI_TRACE
  if (JvmtiTrace::trace_event_controller()) {
    SafeResourceMark rm;
    // traces standard events only
    for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) {
      jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei);
      if (changed & bit) {
        // it changed, print it
        tty->print_cr("JVMTI [-] # %s event %s",
                      (now_enabled & bit)? "Enabling" : "Disabling", JvmtiTrace::event_name((jvmtiEvent)ei));
      }
    }
  }
#endif /*JVMTI_TRACE */
}


// For the specified env: compute the currently truly enabled events
// set external state accordingly.
// Return value and set value must include all events.
// But outside this class, only non-thread-filtered events can be queried..
jlong
JvmtiEventControllerPrivate::recompute_env_enabled(JvmtiEnvBase* env) {
  jlong was_enabled = env->env_event_enable()->_event_enabled.get_bits();
  jlong now_enabled =
    env->env_event_enable()->_event_callback_enabled.get_bits() &
    env->env_event_enable()->_event_user_enabled.get_bits();

  switch (JvmtiEnv::get_phase()) {
  case JVMTI_PHASE_PRIMORDIAL:
  case JVMTI_PHASE_ONLOAD:
    // only these events allowed in primordial or onload phase
    now_enabled &= (EARLY_EVENT_BITS & ~THREAD_FILTERED_EVENT_BITS);
    break;
  case JVMTI_PHASE_START:
    // only these events allowed in start phase
    now_enabled &= EARLY_EVENT_BITS;
    break;
  case JVMTI_PHASE_LIVE:
    // all events allowed during live phase
    break;
  case JVMTI_PHASE_DEAD:
    // no events allowed when dead
    now_enabled = 0;
    break;
  default:
    assert(false, "no other phases - sanity check");
    break;
  }

  // will we really send these events to this env
  env->env_event_enable()->_event_enabled.set_bits(now_enabled);

  trace_changed(now_enabled, (now_enabled ^ was_enabled)  & ~THREAD_FILTERED_EVENT_BITS);

  return now_enabled;
}


// For the specified env and thread: compute the currently truly enabled events
// set external state accordingly.  Only thread-filtered events are included.
jlong
JvmtiEventControllerPrivate::recompute_env_thread_enabled(JvmtiEnvThreadState* ets, JvmtiThreadState* state) {
  JvmtiEnv *env = ets->get_env();

  jlong was_enabled = ets->event_enable()->_event_enabled.get_bits();
  jlong now_enabled =  THREAD_FILTERED_EVENT_BITS &
    env->env_event_enable()->_event_callback_enabled.get_bits() &
    (env->env_event_enable()->_event_user_enabled.get_bits() |
     ets->event_enable()->_event_user_enabled.get_bits());

  // for frame pops and field watchs, computed enabled state
  // is only true if an event has been requested
  if (!ets->has_frame_pops()) {
    now_enabled &= ~FRAME_POP_BIT;
  }
  if (*((int *)JvmtiExport::get_field_access_count_addr()) == 0) {
    now_enabled &= ~FIELD_ACCESS_BIT;
  }
  if (*((int *)JvmtiExport::get_field_modification_count_addr()) == 0) {
    now_enabled &= ~FIELD_MODIFICATION_BIT;
  }

  switch (JvmtiEnv::get_phase()) {
  case JVMTI_PHASE_DEAD:
    // no events allowed when dead
    now_enabled = 0;
    break;
  }

  // if anything changed do update
  if (now_enabled != was_enabled) {

    // will we really send these events to this thread x env
    ets->event_enable()->_event_enabled.set_bits(now_enabled);

    // If the enabled status of the single step or breakpoint events changed,
    // the location status may need to change as well.
    jlong changed = now_enabled ^ was_enabled;
    if (changed & SINGLE_STEP_BIT) {
      ets->reset_current_location(JVMTI_EVENT_SINGLE_STEP, (now_enabled & SINGLE_STEP_BIT) != 0);
    }
    if (changed & BREAKPOINT_BIT) {
      ets->reset_current_location(JVMTI_EVENT_BREAKPOINT,  (now_enabled & BREAKPOINT_BIT) != 0);
    }
    trace_changed(state, now_enabled, changed);
  }
  return now_enabled;
}


// For the specified thread: compute the currently truly enabled events
// set external state accordingly.  Only thread-filtered events are included.
jlong
JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState *state) {
481 482 483 484 485
  if (state == NULL) {
    // associated JavaThread is exiting
    return (jlong)0;
  }

D
duke 已提交
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
  jlong was_any_env_enabled = state->thread_event_enable()->_event_enabled.get_bits();
  jlong any_env_enabled = 0;

  {
    // This iteration will include JvmtiEnvThreadStates whoses environments
    // have been disposed.  These JvmtiEnvThreadStates must not be filtered
    // as recompute must be called on them to disable their events,
    JvmtiEnvThreadStateIterator it(state);
    for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
      any_env_enabled |= recompute_env_thread_enabled(ets, state);
    }
  }

  if (any_env_enabled != was_any_env_enabled) {
    // mark if event is truly enabled on this thread in any environment
    state->thread_event_enable()->_event_enabled.set_bits(any_env_enabled);

    // compute interp_only mode
    bool should_be_interp = (any_env_enabled & INTERP_EVENT_BITS) != 0;
    bool is_now_interp = state->is_interp_only_mode();

    if (should_be_interp != is_now_interp) {
      if (should_be_interp) {
        enter_interp_only_mode(state);
      } else {
        leave_interp_only_mode(state);
      }
    }
  }
  return any_env_enabled;
}


// Compute truly enabled events - meaning if the event can and could be
// sent.  An event is truly enabled if it is user enabled on the thread
// or globally user enabled, but only if there is a callback or event hook
// for it and, for field watch and frame pop, one has been set.
// Compute if truly enabled, per thread, per environment, per combination
// (thread x environment), and overall.  These merges are true if any is true.
// True per thread if some environment has callback set and the event is globally
// enabled or enabled for this thread.
// True per environment if the callback is set and the event is globally
// enabled in this environment or enabled for any thread in this environment.
// True per combination if the environment has the callback set and the
// event is globally enabled in this environment or the event is enabled
// for this thread and environment.
//
// All states transitions dependent on these transitions are also handled here.
void
JvmtiEventControllerPrivate::recompute_enabled() {
  assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");

  // event enabled for any thread in any environment
  jlong was_any_env_thread_enabled = JvmtiEventController::_universal_global_event_enabled.get_bits();
  jlong any_env_thread_enabled = 0;

  EC_TRACE(("JVMTI [-] # recompute enabled - before %llx", was_any_env_thread_enabled));

  // compute non-thread-filters events.
  // This must be done separately from thread-filtered events, since some
  // events can occur before any threads exist.
  JvmtiEnvIterator it;
  for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
    any_env_thread_enabled |= recompute_env_enabled(env);
  }

  // We need to create any missing jvmti_thread_state if there are globally set thread
  // filtered events and there weren't last time
  if (    (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
      (was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
    assert(JvmtiEnv::is_vm_live() || (JvmtiEnv::get_phase()==JVMTI_PHASE_START),
      "thread filtered events should not be enabled when VM not in start or live phase");
    {
      MutexLocker mu(Threads_lock);   //hold the Threads_lock for the iteration
      for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) {
561
        // state_for_while_locked() makes tp->is_exiting() check
D
duke 已提交
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
        JvmtiThreadState::state_for_while_locked(tp);  // create the thread state if missing
      }
    }// release Threads_lock
  }

  // compute and set thread-filtered events
  for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) {
    any_env_thread_enabled |= recompute_thread_enabled(state);
  }

  // set universal state (across all envs and threads)
  jlong delta = any_env_thread_enabled ^ was_any_env_thread_enabled;
  if (delta != 0) {
    JvmtiExport::set_should_post_field_access((any_env_thread_enabled & FIELD_ACCESS_BIT) != 0);
    JvmtiExport::set_should_post_field_modification((any_env_thread_enabled & FIELD_MODIFICATION_BIT) != 0);
    JvmtiExport::set_should_post_class_load((any_env_thread_enabled & CLASS_LOAD_BIT) != 0);
    JvmtiExport::set_should_post_class_file_load_hook((any_env_thread_enabled & CLASS_FILE_LOAD_HOOK_BIT) != 0);
    JvmtiExport::set_should_post_native_method_bind((any_env_thread_enabled & NATIVE_METHOD_BIND_BIT) != 0);
    JvmtiExport::set_should_post_dynamic_code_generated((any_env_thread_enabled & DYNAMIC_CODE_GENERATED_BIT) != 0);
    JvmtiExport::set_should_post_data_dump((any_env_thread_enabled & DATA_DUMP_BIT) != 0);
    JvmtiExport::set_should_post_class_prepare((any_env_thread_enabled & CLASS_PREPARE_BIT) != 0);
    JvmtiExport::set_should_post_class_unload((any_env_thread_enabled & CLASS_UNLOAD_BIT) != 0);
    JvmtiExport::set_should_post_monitor_contended_enter((any_env_thread_enabled & MONITOR_CONTENDED_ENTER_BIT) != 0);
    JvmtiExport::set_should_post_monitor_contended_entered((any_env_thread_enabled & MONITOR_CONTENDED_ENTERED_BIT) != 0);
    JvmtiExport::set_should_post_monitor_wait((any_env_thread_enabled & MONITOR_WAIT_BIT) != 0);
    JvmtiExport::set_should_post_monitor_waited((any_env_thread_enabled & MONITOR_WAITED_BIT) != 0);
    JvmtiExport::set_should_post_garbage_collection_start((any_env_thread_enabled & GARBAGE_COLLECTION_START_BIT) != 0);
    JvmtiExport::set_should_post_garbage_collection_finish((any_env_thread_enabled & GARBAGE_COLLECTION_FINISH_BIT) != 0);
    JvmtiExport::set_should_post_object_free((any_env_thread_enabled & OBJECT_FREE_BIT) != 0);
    JvmtiExport::set_should_post_resource_exhausted((any_env_thread_enabled & RESOURCE_EXHAUSTED_BIT) != 0);
    JvmtiExport::set_should_post_compiled_method_load((any_env_thread_enabled & COMPILED_METHOD_LOAD_BIT) != 0);
    JvmtiExport::set_should_post_compiled_method_unload((any_env_thread_enabled & COMPILED_METHOD_UNLOAD_BIT) != 0);
    JvmtiExport::set_should_post_vm_object_alloc((any_env_thread_enabled & VM_OBJECT_ALLOC_BIT) != 0);

    // need this if we want thread events or we need them to init data
    JvmtiExport::set_should_post_thread_life((any_env_thread_enabled & NEED_THREAD_LIFE_EVENTS) != 0);

    // If single stepping is turned on or off, execute the VM op to change it.
    if (delta & SINGLE_STEP_BIT) {
      switch (JvmtiEnv::get_phase()) {
      case JVMTI_PHASE_DEAD:
        // If the VM is dying we can't execute VM ops
        break;
      case JVMTI_PHASE_LIVE: {
        VM_ChangeSingleStep op((any_env_thread_enabled & SINGLE_STEP_BIT) != 0);
        VMThread::execute(&op);
        break;
      }
      default:
        assert(false, "should never come here before live phase");
        break;
      }
    }

    // set global truly enabled, that is, any thread in any environment
    JvmtiEventController::_universal_global_event_enabled.set_bits(any_env_thread_enabled);
  }

  EC_TRACE(("JVMTI [-] # recompute enabled - after %llx", any_env_thread_enabled));
}


void
JvmtiEventControllerPrivate::thread_started(JavaThread *thread) {
  assert(thread->is_Java_thread(), "Must be JavaThread");
  assert(thread == Thread::current(), "must be current thread");
  assert(JvmtiEnvBase::environments_might_exist(), "to enter event controller, JVM TI environments must exist");

  EC_TRACE(("JVMTI [%s] # thread started", JvmtiTrace::safe_get_thread_name(thread)));

  // if we have any thread filtered events globally enabled, create/update the thread state
  if ((JvmtiEventController::_universal_global_event_enabled.get_bits() & THREAD_FILTERED_EVENT_BITS) != 0) {
    MutexLocker mu(JvmtiThreadState_lock);
    // create the thread state if missing
    JvmtiThreadState *state = JvmtiThreadState::state_for_while_locked(thread);
    if (state != NULL) {    // skip threads with no JVMTI thread state
      recompute_thread_enabled(state);
    }
  }
}


void
JvmtiEventControllerPrivate::thread_ended(JavaThread *thread) {
  // Removes the JvmtiThreadState associated with the specified thread.
  // May be called after all environments have been disposed.

  EC_TRACE(("JVMTI [%s] # thread ended", JvmtiTrace::safe_get_thread_name(thread)));

  JvmtiThreadState *state = thread->jvmti_thread_state();
  if (state != NULL) {
    MutexLocker mu(JvmtiThreadState_lock);
    delete state;
  }
}

void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env,
                                                      const jvmtiEventCallbacks* callbacks,
                                                      jint size_of_callbacks) {
  assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
  EC_TRACE(("JVMTI [*] # set event callbacks"));

  env->set_event_callbacks(callbacks, size_of_callbacks);
  jlong enabled_bits = 0;
  for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) {
    jvmtiEvent evt_t = (jvmtiEvent)ei;
    if (env->has_callback(evt_t)) {
      enabled_bits |= JvmtiEventEnabled::bit_for(evt_t);
    }
  }
  env->env_event_enable()->_event_callback_enabled.set_bits(enabled_bits);
  recompute_enabled();
}

void
JvmtiEventControllerPrivate::set_extension_event_callback(JvmtiEnvBase *env,
                                                          jint extension_event_index,
                                                          jvmtiExtensionEvent callback)
{
  assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
  EC_TRACE(("JVMTI [*] # set extension event callback"));

  // extension events are allocated below JVMTI_MIN_EVENT_TYPE_VAL
  assert(extension_event_index >= (jint)EXT_MIN_EVENT_TYPE_VAL &&
         extension_event_index <= (jint)EXT_MAX_EVENT_TYPE_VAL, "sanity check");


  // As the bits for both standard (jvmtiEvent) and extension
  // (jvmtiExtEvents) are stored in the same word we cast here to
  // jvmtiEvent to set/clear the bit for this extension event.
  jvmtiEvent event_type = (jvmtiEvent)extension_event_index;

  // Prevent a possible race condition where events are re-enabled by a call to
  // set event callbacks, where the DisposeEnvironment occurs after the boiler-plate
  // environment check and before the lock is acquired.
  // We can safely do the is_valid check now, as JvmtiThreadState_lock is held.
  bool enabling = (callback != NULL) && (env->is_valid());
  env->env_event_enable()->set_user_enabled(event_type, enabling);

  // update the callback
  jvmtiExtEventCallbacks* ext_callbacks = env->ext_callbacks();
  switch (extension_event_index) {
    case EXT_EVENT_CLASS_UNLOAD :
      ext_callbacks->ClassUnload = callback;
      break;
    default:
      ShouldNotReachHere();
  }

  // update the callback enable/disable bit
  jlong enabled_bits = env->env_event_enable()->_event_callback_enabled.get_bits();
  jlong bit_for = JvmtiEventEnabled::bit_for(event_type);
  if (enabling) {
    enabled_bits |= bit_for;
  } else {
    enabled_bits &= ~bit_for;
  }
  env->env_event_enable()->_event_callback_enabled.set_bits(enabled_bits);

  recompute_enabled();
}


void
JvmtiEventControllerPrivate::env_initialize(JvmtiEnvBase *env) {
  assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
  EC_TRACE(("JVMTI [*] # env initialize"));

  if (JvmtiEnvBase::is_vm_live()) {
    // if we didn't initialize event info already (this is a late
    // launched environment), do it now.
    event_init();
  }

  env->initialize();

  // add the JvmtiEnvThreadState to each JvmtiThreadState
  for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) {
    state->add_env(env);
    assert((JvmtiEnv*)(state->env_thread_state(env)->get_env()) == env, "sanity check");
  }
  JvmtiEventControllerPrivate::recompute_enabled();
}


void
JvmtiEventControllerPrivate::env_dispose(JvmtiEnvBase *env) {
  assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
  EC_TRACE(("JVMTI [*] # env dispose"));

  // Before the environment is marked disposed, disable all events on this
  // environment (by zapping the callbacks).  As a result, the disposed
  // environment will not call event handlers.
  set_event_callbacks(env, NULL, 0);
  for (jint extension_event_index = EXT_MIN_EVENT_TYPE_VAL;
       extension_event_index <= EXT_MAX_EVENT_TYPE_VAL;
       ++extension_event_index) {
    set_extension_event_callback(env, extension_event_index, NULL);
  }

  // Let the environment finish disposing itself.
  env->env_dispose();
}


void
JvmtiEventControllerPrivate::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread,
                                          jvmtiEvent event_type, bool enabled) {
  assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");

  EC_TRACE(("JVMTI [%s] # user %s event %s",
            thread==NULL? "ALL": JvmtiTrace::safe_get_thread_name(thread),
            enabled? "enabled" : "disabled", JvmtiTrace::event_name(event_type)));

  if (thread == NULL) {
    env->env_event_enable()->set_user_enabled(event_type, enabled);
  } else {
    // create the thread state (if it didn't exist before)
    JvmtiThreadState *state = JvmtiThreadState::state_for_while_locked(thread);
    if (state != NULL) {
      state->env_thread_state(env)->event_enable()->set_user_enabled(event_type, enabled);
    }
  }
  recompute_enabled();
}


void
JvmtiEventControllerPrivate::set_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
  EC_TRACE(("JVMTI [%s] # set frame pop - frame=%d",
            JvmtiTrace::safe_get_thread_name(ets->get_thread()),
            fpop.frame_number() ));

  ets->get_frame_pops()->set(fpop);
  recompute_thread_enabled(ets->get_thread()->jvmti_thread_state());
}


void
JvmtiEventControllerPrivate::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
  EC_TRACE(("JVMTI [%s] # clear frame pop - frame=%d",
            JvmtiTrace::safe_get_thread_name(ets->get_thread()),
            fpop.frame_number() ));

  ets->get_frame_pops()->clear(fpop);
  recompute_thread_enabled(ets->get_thread()->jvmti_thread_state());
}


void
JvmtiEventControllerPrivate::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
  int cleared_cnt = ets->get_frame_pops()->clear_to(fpop);

  EC_TRACE(("JVMTI [%s] # clear to frame pop - frame=%d, count=%d",
            JvmtiTrace::safe_get_thread_name(ets->get_thread()),
            fpop.frame_number(),
            cleared_cnt ));

  if (cleared_cnt > 0) {
    recompute_thread_enabled(ets->get_thread()->jvmti_thread_state());
  }
}

void
JvmtiEventControllerPrivate::change_field_watch(jvmtiEvent event_type, bool added) {
  int *count_addr;

  switch (event_type) {
  case JVMTI_EVENT_FIELD_MODIFICATION:
    count_addr = (int *)JvmtiExport::get_field_modification_count_addr();
    break;
  case JVMTI_EVENT_FIELD_ACCESS:
    count_addr = (int *)JvmtiExport::get_field_access_count_addr();
    break;
  default:
    assert(false, "incorrect event");
    return;
  }

  EC_TRACE(("JVMTI [-] # change field watch - %s %s count=%d",
            event_type==JVMTI_EVENT_FIELD_MODIFICATION? "modification" : "access",
            added? "add" : "remove",
            *count_addr));

  if (added) {
    (*count_addr)++;
    if (*count_addr == 1) {
      recompute_enabled();
    }
  } else {
    if (*count_addr > 0) {
      (*count_addr)--;
      if (*count_addr == 0) {
        recompute_enabled();
      }
    } else {
      assert(false, "field watch out of phase");
    }
  }
}

void
JvmtiEventControllerPrivate::event_init() {
  assert(JvmtiThreadState_lock->is_locked(), "sanity check");

  if (_initialized) {
    return;
  }

  EC_TRACE(("JVMTI [-] # VM live"));

#ifdef ASSERT
  // check that our idea and the spec's idea of threaded events match
  for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) {
    jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei);
    assert(((THREAD_FILTERED_EVENT_BITS & bit) != 0) == JvmtiUtil::event_threaded(ei),
           "thread filtered event list does not match");
  }
#endif

  _initialized = true;
}

void
JvmtiEventControllerPrivate::vm_start() {
  // some events are now able to be enabled (phase has changed)
  JvmtiEventControllerPrivate::recompute_enabled();
}


void
JvmtiEventControllerPrivate::vm_init() {
  event_init();

  // all the events are now able to be enabled (phase has changed)
  JvmtiEventControllerPrivate::recompute_enabled();
}


void
JvmtiEventControllerPrivate::vm_death() {
  // events are disabled (phase has changed)
  JvmtiEventControllerPrivate::recompute_enabled();
}


///////////////////////////////////////////////////////////////
//
// JvmtiEventController
//

JvmtiEventEnabled JvmtiEventController::_universal_global_event_enabled;

bool
JvmtiEventController::is_global_event(jvmtiEvent event_type) {
  assert(is_valid_event_type(event_type), "invalid event type");
  jlong bit_for = ((jlong)1) << (event_type - TOTAL_MIN_EVENT_TYPE_VAL);
  return((bit_for & GLOBAL_EVENT_BITS)!=0);
}

void
JvmtiEventController::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, jvmtiEvent event_type, bool enabled) {
  if (Threads::number_of_threads() == 0) {
    // during early VM start-up locks don't exist, but we are safely single threaded,
    // call the functionality without holding the JvmtiThreadState_lock.
    JvmtiEventControllerPrivate::set_user_enabled(env, thread, event_type, enabled);
  } else {
    MutexLocker mu(JvmtiThreadState_lock);
    JvmtiEventControllerPrivate::set_user_enabled(env, thread, event_type, enabled);
  }
}


void
JvmtiEventController::set_event_callbacks(JvmtiEnvBase *env,
                                          const jvmtiEventCallbacks* callbacks,
                                          jint size_of_callbacks) {
  if (Threads::number_of_threads() == 0) {
    // during early VM start-up locks don't exist, but we are safely single threaded,
    // call the functionality without holding the JvmtiThreadState_lock.
    JvmtiEventControllerPrivate::set_event_callbacks(env, callbacks, size_of_callbacks);
  } else {
    MutexLocker mu(JvmtiThreadState_lock);
    JvmtiEventControllerPrivate::set_event_callbacks(env, callbacks, size_of_callbacks);
  }
}

void
JvmtiEventController::set_extension_event_callback(JvmtiEnvBase *env,
                                                   jint extension_event_index,
                                                   jvmtiExtensionEvent callback) {
  if (Threads::number_of_threads() == 0) {
    JvmtiEventControllerPrivate::set_extension_event_callback(env, extension_event_index, callback);
  } else {
    MutexLocker mu(JvmtiThreadState_lock);
    JvmtiEventControllerPrivate::set_extension_event_callback(env, extension_event_index, callback);
  }
}




void
JvmtiEventController::set_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
  MutexLocker mu(JvmtiThreadState_lock);
  JvmtiEventControllerPrivate::set_frame_pop(ets, fpop);
}


void
JvmtiEventController::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
  MutexLocker mu(JvmtiThreadState_lock);
  JvmtiEventControllerPrivate::clear_frame_pop(ets, fpop);
}


void
JvmtiEventController::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
  MutexLocker mu(JvmtiThreadState_lock);
  JvmtiEventControllerPrivate::clear_to_frame_pop(ets, fpop);
}

void
JvmtiEventController::change_field_watch(jvmtiEvent event_type, bool added) {
  MutexLocker mu(JvmtiThreadState_lock);
  JvmtiEventControllerPrivate::change_field_watch(event_type, added);
}

void
JvmtiEventController::thread_started(JavaThread *thread) {
  // operates only on the current thread
  // JvmtiThreadState_lock grabbed only if needed.
  JvmtiEventControllerPrivate::thread_started(thread);
}

void
JvmtiEventController::thread_ended(JavaThread *thread) {
  // operates only on the current thread
  // JvmtiThreadState_lock grabbed only if needed.
  JvmtiEventControllerPrivate::thread_ended(thread);
}

void
JvmtiEventController::env_initialize(JvmtiEnvBase *env) {
  if (Threads::number_of_threads() == 0) {
    // during early VM start-up locks don't exist, but we are safely single threaded,
    // call the functionality without holding the JvmtiThreadState_lock.
    JvmtiEventControllerPrivate::env_initialize(env);
  } else {
    MutexLocker mu(JvmtiThreadState_lock);
    JvmtiEventControllerPrivate::env_initialize(env);
  }
}

void
JvmtiEventController::env_dispose(JvmtiEnvBase *env) {
  if (Threads::number_of_threads() == 0) {
    // during early VM start-up locks don't exist, but we are safely single threaded,
    // call the functionality without holding the JvmtiThreadState_lock.
    JvmtiEventControllerPrivate::env_dispose(env);
  } else {
    MutexLocker mu(JvmtiThreadState_lock);
    JvmtiEventControllerPrivate::env_dispose(env);
  }
}


void
JvmtiEventController::vm_start() {
  if (JvmtiEnvBase::environments_might_exist()) {
    MutexLocker mu(JvmtiThreadState_lock);
    JvmtiEventControllerPrivate::vm_start();
  }
}

void
JvmtiEventController::vm_init() {
  if (JvmtiEnvBase::environments_might_exist()) {
    MutexLocker mu(JvmtiThreadState_lock);
    JvmtiEventControllerPrivate::vm_init();
  }
}

void
JvmtiEventController::vm_death() {
  if (JvmtiEnvBase::environments_might_exist()) {
    MutexLocker mu(JvmtiThreadState_lock);
    JvmtiEventControllerPrivate::vm_death();
  }
}