src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp
author mgronlun
Mon, 25 Nov 2019 18:38:01 +0100
changeset 59259 127ca611f19b
parent 50113 caf115bb98ad
permissions -rw-r--r--
8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing Reviewed-by: sspitsyn, egahlin
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     1
/*
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
     2
 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
50113
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"
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    35
#include "prims/jvmtiEnvBase.hpp"
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    36
#include "prims/jvmtiExport.hpp"
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    37
#include "prims/jvmtiUtil.hpp"
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    38
#include "runtime/interfaceSupport.inline.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    39
#include "runtime/thread.inline.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    40
#include "utilities/exceptions.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    41
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    42
static const size_t ERROR_MSG_BUFFER_SIZE = 256;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    43
static JfrJvmtiAgent* agent = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    44
static jvmtiEnv* jfr_jvmti_env = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    45
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    46
static void check_jvmti_error(jvmtiEnv* jvmti, jvmtiError errnum, const char* str) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    47
  if (errnum != JVMTI_ERROR_NONE) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    48
    char* errnum_str = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    49
    jvmti->GetErrorName(errnum, &errnum_str);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    50
    log_error(jfr, system)("ERROR: JfrJvmtiAgent: " INT32_FORMAT " (%s): %s\n",
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    51
                           errnum,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    52
                           NULL == errnum_str ? "Unknown" : errnum_str,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    53
                           NULL == str ? "" : str);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    54
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    55
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    56
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    57
static bool set_event_notification_mode(jvmtiEventMode mode,
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    58
                                        jvmtiEvent event,
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    59
                                        jthread event_thread,
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    60
                                        ...) {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    61
  assert(jfr_jvmti_env != NULL, "invariant");
50113
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");
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    64
  return jvmti_ret_code == JVMTI_ERROR_NONE;
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    65
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    66
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
    67
static bool update_class_file_load_hook_event(jvmtiEventMode mode) {
50113
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
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   120
// caller needs ResourceMark
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   121
static void log_and_throw(jvmtiError error, TRAPS) {
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   122
  if (!HAS_PENDING_EXCEPTION) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   123
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   124
    ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   125
    const char base_error_msg[] = "JfrJvmtiAgent::retransformClasses failed: ";
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   126
    size_t length = sizeof base_error_msg; // includes terminating null
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   127
    const char* const jvmti_error_name = JvmtiUtil::error_name(error);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   128
    assert(jvmti_error_name != NULL, "invariant");
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   129
    length += strlen(jvmti_error_name);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   130
    char* error_msg = NEW_RESOURCE_ARRAY(char, length);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   131
    jio_snprintf(error_msg, length, "%s%s", base_error_msg, jvmti_error_name);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   132
    if (JVMTI_ERROR_INVALID_CLASS_FORMAT == error) {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   133
      JfrJavaSupport::throw_class_format_error(error_msg, THREAD);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   134
    } else {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   135
      JfrJavaSupport::throw_runtime_exception(error_msg, THREAD);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   136
    }
50113
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
static void check_exception_and_log(JNIEnv* env, TRAPS) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   141
  assert(env != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   142
  if (env->ExceptionOccurred()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   143
    // array index out of bound
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   144
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   145
    ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   146
    log_error(jfr, system)("GetObjectArrayElement threw an exception");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   147
    return;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   148
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   149
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   150
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   151
static bool is_valid_jvmti_phase() {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   152
  return JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE;
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   153
}
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   154
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   155
void JfrJvmtiAgent::retransform_classes(JNIEnv* env, jobjectArray classes_array, TRAPS) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   156
  assert(env != NULL, "invariant");
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   157
  assert(classes_array != NULL, "invariant");
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   158
  assert(is_valid_jvmti_phase(), "invariant");
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   159
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   160
  const jint classes_count = env->GetArrayLength(classes_array);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   161
  if (classes_count <= 0) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   162
    return;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   163
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   164
  ResourceMark rm(THREAD);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   165
  jclass* const classes = create_classes_array(classes_count, CHECK);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   166
  assert(classes != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   167
  for (jint i = 0; i < classes_count; i++) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   168
    jclass clz = (jclass)env->GetObjectArrayElement(classes_array, i);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   169
    check_exception_and_log(env, THREAD);
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   170
    classes[i] = clz;
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   171
  }
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   172
  {
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   173
    // inspecting the oop/klass requires a thread transition
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   174
    ThreadInVMfromNative transition((JavaThread*)THREAD);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   175
    for (jint i = 0; i < classes_count; ++i) {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   176
      jclass clz = classes[i];
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   177
      if (!JdkJfrEvent::is_a(clz)) {
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   178
        // outside the event hierarchy
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   179
        JdkJfrEvent::tag_as_host(clz);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   180
      }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   181
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   182
  }
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   183
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   184
  const jvmtiError result = jfr_jvmti_env->RetransformClasses(classes_count, classes);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   185
  if (result != JVMTI_ERROR_NONE) {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   186
    log_and_throw(result, THREAD);
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   187
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   188
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   189
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   190
static bool register_callbacks(JavaThread* jt) {
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   191
  assert(jfr_jvmti_env != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   192
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   193
  jvmtiEventCallbacks callbacks;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   194
  /* Set callbacks */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   195
  memset(&callbacks, 0, sizeof(callbacks));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   196
  callbacks.ClassFileLoadHook = jfr_on_class_file_load_hook;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   197
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   198
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   199
  return jvmti_ret_code == JVMTI_ERROR_NONE;
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   200
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   201
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   202
static bool register_capabilities(JavaThread* jt) {
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   203
  assert(jfr_jvmti_env != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   204
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   205
  jvmtiCapabilities capabilities;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   206
  /* Add JVMTI capabilities */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   207
  (void)memset(&capabilities, 0, sizeof(capabilities));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   208
  capabilities.can_retransform_classes = 1;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   209
  capabilities.can_retransform_any_class = 1;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   210
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->AddCapabilities(&capabilities);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   211
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "Add Capabilities");
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   212
  return jvmti_ret_code == JVMTI_ERROR_NONE;
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   213
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   214
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   215
static jint create_jvmti_env(JavaThread* jt) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   216
  assert(jfr_jvmti_env == NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   217
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   218
  extern struct JavaVM_ main_vm;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   219
  JavaVM* vm = &main_vm;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   220
  return vm->GetEnv((void **)&jfr_jvmti_env, JVMTI_VERSION);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   221
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   222
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   223
static bool unregister_callbacks(JavaThread* jt) {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   224
  assert(jfr_jvmti_env != NULL, "invariant");
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   225
  jvmtiEventCallbacks callbacks;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   226
  /* Set empty callbacks */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   227
  memset(&callbacks, 0, sizeof(callbacks));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   228
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   229
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   230
  return jvmti_ret_code == JVMTI_ERROR_NONE;
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   231
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   232
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   233
JfrJvmtiAgent::JfrJvmtiAgent() {}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   234
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   235
JfrJvmtiAgent::~JfrJvmtiAgent() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   236
  JavaThread* jt = current_java_thread();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   237
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   238
  if (jfr_jvmti_env != NULL) {
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   239
    ThreadToNativeFromVM transition(jt);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   240
    update_class_file_load_hook_event(JVMTI_DISABLE);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   241
    unregister_callbacks(jt);
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   242
    jfr_jvmti_env->DisposeEnvironment();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   243
    jfr_jvmti_env = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   244
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   245
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   246
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   247
static bool initialize(JavaThread* jt) {
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   248
  assert(jt != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   249
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   250
  ThreadToNativeFromVM transition(jt);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   251
  if (create_jvmti_env(jt) != JNI_OK) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   252
    assert(jfr_jvmti_env == NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   253
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   254
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   255
  assert(jfr_jvmti_env != NULL, "invariant");
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   256
  if (!register_capabilities(jt)) {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   257
    return false;
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   258
  }
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   259
  if (!register_callbacks(jt)) {
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   260
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   261
  }
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   262
  return update_class_file_load_hook_event(JVMTI_ENABLE);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   263
}
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   264
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   265
static void log_and_throw_illegal_state_exception(TRAPS) {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   266
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   267
  const char* const illegal_state_msg = "An attempt was made to start JFR too early in the VM initialization sequence.";
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   268
  log_error(jfr, system)(illegal_state_msg);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   269
  log_error(jfr, system)("JFR uses JVMTI RetransformClasses and requires the JVMTI state to have entered JVMTI_PHASE_LIVE.");
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   270
  log_error(jfr, system)("Please initialize JFR in response to event JVMTI_EVENT_VM_INIT instead of JVMTI_EVENT_VM_START.");
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   271
  JfrJavaSupport::throw_illegal_state_exception(illegal_state_msg, THREAD);
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   272
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   273
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   274
bool JfrJvmtiAgent::create() {
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   275
  assert(agent == NULL, "invariant");
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   276
  JavaThread* const jt = current_java_thread();
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   277
  if (!is_valid_jvmti_phase()) {
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   278
    log_and_throw_illegal_state_exception(jt);
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   279
    return false;
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   280
  }
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   281
  agent = new JfrJvmtiAgent();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   282
  if (agent == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   283
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   284
  }
59259
127ca611f19b 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing
mgronlun
parents: 50113
diff changeset
   285
  if (!initialize(jt)) {
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   286
    delete agent;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   287
    agent = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   288
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   289
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   290
  return true;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   291
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   292
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   293
void JfrJvmtiAgent::destroy() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   294
  if (agent != NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   295
    delete agent;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   296
    agent = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   297
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   298
}