src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp
author egahlin
Tue, 15 May 2018 20:24:34 +0200
changeset 50113 caf115bb98ad
child 59259 127ca611f19b
permissions -rw-r--r--
8199712: Flight Recorder Reviewed-by: coleenp, ihse, erikj, dsamersoff, mseledtsov, egahlin, mgronlun Contributed-by: erik.gahlin@oracle.com, markus.gronlund@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     1
/*
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     2
 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     4
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     7
 * published by the Free Software Foundation.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     8
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    13
 * accompanied this code).
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    14
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    18
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    21
 * questions.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    22
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    23
 */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    24
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    25
#include "precompiled.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    26
#include "jvm.h"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    27
#include "jfr/instrumentation/jfrJvmtiAgent.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    28
#include "jfr/jni/jfrJavaSupport.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    29
#include "jfr/jni/jfrUpcalls.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    30
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    31
#include "jfr/recorder/service/jfrOptionSet.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    32
#include "jfr/support/jfrEventClass.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    33
#include "logging/log.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    34
#include "memory/resourceArea.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    35
#include "prims/jvmtiExport.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    36
#include "runtime/interfaceSupport.inline.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    37
#include "runtime/thread.inline.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    38
#include "utilities/exceptions.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    39
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    40
static const size_t ERROR_MSG_BUFFER_SIZE = 256;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    41
static JfrJvmtiAgent* agent = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    42
static jvmtiEnv* jfr_jvmti_env = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    43
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    44
static void check_jvmti_error(jvmtiEnv* jvmti, jvmtiError errnum, const char* str) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    45
  if (errnum != JVMTI_ERROR_NONE) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    46
    char* errnum_str = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    47
    jvmti->GetErrorName(errnum, &errnum_str);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    48
    log_error(jfr, system)("ERROR: JfrJvmtiAgent: " INT32_FORMAT " (%s): %s\n",
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    49
                           errnum,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    50
                           NULL == errnum_str ? "Unknown" : errnum_str,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    51
                           NULL == str ? "" : str);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    52
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    53
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    54
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    55
static jvmtiError set_event_notification_mode(jvmtiEventMode mode,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    56
                                              jvmtiEvent event,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    57
                                              jthread event_thread,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    58
                                              ...) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    59
  if (jfr_jvmti_env == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    60
    return JVMTI_ERROR_NONE;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    61
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    62
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventNotificationMode(mode, event, event_thread);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    63
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventNotificationMode");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    64
  return jvmti_ret_code;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    65
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    66
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    67
static jvmtiError update_class_file_load_hook_event(jvmtiEventMode mode) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    68
  return set_event_notification_mode(mode, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    69
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    70
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    71
static JavaThread* current_java_thread() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    72
  Thread* this_thread = Thread::current();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    73
  assert(this_thread != NULL && this_thread->is_Java_thread(), "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    74
  return static_cast<JavaThread*>(this_thread);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    75
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    76
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    77
// jvmti event callbacks require C linkage
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    78
extern "C" void JNICALL jfr_on_class_file_load_hook(jvmtiEnv *jvmti_env,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    79
                                                    JNIEnv* jni_env,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    80
                                                    jclass class_being_redefined,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    81
                                                    jobject loader,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    82
                                                    const char* name,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    83
                                                    jobject protection_domain,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    84
                                                    jint class_data_len,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    85
                                                    const unsigned char* class_data,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    86
                                                    jint* new_class_data_len,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    87
                                                    unsigned char** new_class_data) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    88
  if (class_being_redefined == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    89
    return;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    90
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    91
  JavaThread* jt = JavaThread::thread_from_jni_environment(jni_env);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    92
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    93
  ThreadInVMfromNative tvmfn(jt);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    94
  JfrUpcalls::on_retransform(JfrTraceId::get(class_being_redefined),
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    95
                             class_being_redefined,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    96
                             class_data_len,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    97
                             class_data,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    98
                             new_class_data_len,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    99
                             new_class_data,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   100
                             jt);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   101
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   102
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   103
// caller needs ResourceMark
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   104
static jclass* create_classes_array(jint classes_count, TRAPS) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   105
  assert(classes_count > 0, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   106
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   107
  ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   108
  jclass* const classes = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jclass, classes_count);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   109
  if (NULL == classes) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   110
    char error_buffer[ERROR_MSG_BUFFER_SIZE];
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   111
    jio_snprintf(error_buffer, ERROR_MSG_BUFFER_SIZE,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   112
      "Thread local allocation (native) of " SIZE_FORMAT " bytes failed "
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   113
      "in retransform classes", sizeof(jclass) * classes_count);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   114
    log_error(jfr, system)("%s", error_buffer);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   115
    JfrJavaSupport::throw_out_of_memory_error(error_buffer, CHECK_NULL);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   116
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   117
  return classes;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   118
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   119
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   120
static void log_and_throw(TRAPS) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   121
  if (!HAS_PENDING_EXCEPTION) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   122
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   123
    ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   124
    log_error(jfr, system)("JfrJvmtiAgent::retransformClasses failed");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   125
    JfrJavaSupport::throw_class_format_error("JfrJvmtiAgent::retransformClasses failed", THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   126
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   127
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   128
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   129
static void check_exception_and_log(JNIEnv* env, TRAPS) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   130
  assert(env != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   131
  if (env->ExceptionOccurred()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   132
    // array index out of bound
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   133
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   134
    ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   135
    log_error(jfr, system)("GetObjectArrayElement threw an exception");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   136
    return;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   137
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   138
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   139
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   140
void JfrJvmtiAgent::retransform_classes(JNIEnv* env, jobjectArray classes_array, TRAPS) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   141
  assert(env != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   142
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   143
  if (classes_array == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   144
    return;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   145
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   146
  const jint classes_count = env->GetArrayLength(classes_array);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   147
  if (classes_count <= 0) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   148
    return;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   149
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   150
  ResourceMark rm(THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   151
  jclass* const classes = create_classes_array(classes_count, CHECK);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   152
  assert(classes != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   153
  for (jint i = 0; i < classes_count; i++) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   154
    jclass clz = (jclass)env->GetObjectArrayElement(classes_array, i);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   155
    check_exception_and_log(env, THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   156
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   157
    // inspecting the oop/klass requires a thread transition
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   158
    {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   159
      ThreadInVMfromNative transition((JavaThread*)THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   160
      if (JdkJfrEvent::is_a(clz)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   161
        // should have been tagged already
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   162
        assert(JdkJfrEvent::is_subklass(clz), "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   163
      } else {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   164
        // outside the event hierarchy
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   165
        JdkJfrEvent::tag_as_host(clz);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   166
      }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   167
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   168
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   169
    classes[i] = clz;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   170
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   171
  if (jfr_jvmti_env->RetransformClasses(classes_count, classes) != JVMTI_ERROR_NONE) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   172
    log_and_throw(THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   173
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   174
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   175
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   176
static jvmtiError register_callbacks(JavaThread* jt) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   177
  assert(jfr_jvmti_env != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   178
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   179
  jvmtiEventCallbacks callbacks;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   180
  /* Set callbacks */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   181
  memset(&callbacks, 0, sizeof(callbacks));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   182
  callbacks.ClassFileLoadHook = jfr_on_class_file_load_hook;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   183
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   184
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   185
  return jvmti_ret_code;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   186
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   187
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   188
static jvmtiError register_capabilities(JavaThread* jt) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   189
  assert(jfr_jvmti_env != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   190
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   191
  jvmtiCapabilities capabilities;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   192
  /* Add JVMTI capabilities */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   193
  (void)memset(&capabilities, 0, sizeof(capabilities));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   194
  capabilities.can_retransform_classes = 1;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   195
  capabilities.can_retransform_any_class = 1;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   196
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->AddCapabilities(&capabilities);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   197
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "Add Capabilities");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   198
  return jvmti_ret_code;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   199
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   200
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   201
static jint create_jvmti_env(JavaThread* jt) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   202
  assert(jfr_jvmti_env == NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   203
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   204
  extern struct JavaVM_ main_vm;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   205
  JavaVM* vm = &main_vm;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   206
  return vm->GetEnv((void **)&jfr_jvmti_env, JVMTI_VERSION);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   207
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   208
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   209
static jvmtiError unregister_callbacks(JavaThread* jt) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   210
  if (jfr_jvmti_env == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   211
    return JVMTI_ERROR_NONE;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   212
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   213
  jvmtiEventCallbacks callbacks;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   214
  /* Set empty callbacks */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   215
  memset(&callbacks, 0, sizeof(callbacks));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   216
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   217
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   218
  return jvmti_ret_code;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   219
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   220
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   221
JfrJvmtiAgent::JfrJvmtiAgent() {}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   222
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   223
JfrJvmtiAgent::~JfrJvmtiAgent() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   224
  JavaThread* jt = current_java_thread();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   225
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   226
  ThreadToNativeFromVM transition(jt);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   227
  update_class_file_load_hook_event(JVMTI_DISABLE);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   228
  unregister_callbacks(jt);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   229
  if (jfr_jvmti_env != NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   230
    jfr_jvmti_env->DisposeEnvironment();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   231
    jfr_jvmti_env = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   232
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   233
  agent = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   234
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   235
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   236
static bool initialize() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   237
  JavaThread* const jt = current_java_thread();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   238
  assert(jt != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   239
  assert(jt->thread_state() == _thread_in_vm, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   240
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   241
  ThreadToNativeFromVM transition(jt);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   242
  if (create_jvmti_env(jt) != JNI_OK) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   243
    assert(jfr_jvmti_env == NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   244
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   245
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   246
  assert(jfr_jvmti_env != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   247
  if (register_capabilities(jt) != JVMTI_ERROR_NONE) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   248
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   249
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   250
  if (register_callbacks(jt) != JVMTI_ERROR_NONE) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   251
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   252
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   253
  if (update_class_file_load_hook_event(JVMTI_ENABLE) != JVMTI_ERROR_NONE) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   254
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   255
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   256
  return true;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   257
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   258
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   259
bool JfrJvmtiAgent::create() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   260
  assert(jfr_jvmti_env == NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   261
  agent = new JfrJvmtiAgent();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   262
  if (agent == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   263
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   264
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   265
  if (!initialize()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   266
    delete agent;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   267
    agent = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   268
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   269
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   270
  return true;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   271
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   272
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   273
void JfrJvmtiAgent::destroy() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   274
  if (agent != NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   275
    delete agent;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   276
    agent = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   277
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   278
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   279