# HG changeset patch # User mgronlun # Date 1574703481 -3600 # Node ID 127ca611f19bf5884642b090b30ea9655df59d99 # Parent 4c2557ab304e698735d4c22ec9aa61def7efec08 8233197: Invert JvmtiExport::post_vm_initialized() and Jfr:on_vm_start() start-up order for correct option parsing Reviewed-by: sspitsyn, egahlin diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp --- a/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp Mon Nov 25 18:38:01 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. 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 @@ -32,7 +32,9 @@ #include "jfr/support/jfrEventClass.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvmtiEnvBase.hpp" #include "prims/jvmtiExport.hpp" +#include "prims/jvmtiUtil.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/thread.inline.hpp" #include "utilities/exceptions.hpp" @@ -52,19 +54,17 @@ } } -static jvmtiError set_event_notification_mode(jvmtiEventMode mode, - jvmtiEvent event, - jthread event_thread, - ...) { - if (jfr_jvmti_env == NULL) { - return JVMTI_ERROR_NONE; - } +static bool set_event_notification_mode(jvmtiEventMode mode, + jvmtiEvent event, + jthread event_thread, + ...) { + assert(jfr_jvmti_env != NULL, "invariant"); const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventNotificationMode(mode, event, event_thread); check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventNotificationMode"); - return jvmti_ret_code; + return jvmti_ret_code == JVMTI_ERROR_NONE; } -static jvmtiError update_class_file_load_hook_event(jvmtiEventMode mode) { +static bool update_class_file_load_hook_event(jvmtiEventMode mode) { return set_event_notification_mode(mode, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL); } @@ -117,12 +117,23 @@ return classes; } -static void log_and_throw(TRAPS) { +// caller needs ResourceMark +static void log_and_throw(jvmtiError error, TRAPS) { if (!HAS_PENDING_EXCEPTION) { DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD)); ThreadInVMfromNative tvmfn((JavaThread*)THREAD); - log_error(jfr, system)("JfrJvmtiAgent::retransformClasses failed"); - JfrJavaSupport::throw_class_format_error("JfrJvmtiAgent::retransformClasses failed", THREAD); + const char base_error_msg[] = "JfrJvmtiAgent::retransformClasses failed: "; + size_t length = sizeof base_error_msg; // includes terminating null + const char* const jvmti_error_name = JvmtiUtil::error_name(error); + assert(jvmti_error_name != NULL, "invariant"); + length += strlen(jvmti_error_name); + char* error_msg = NEW_RESOURCE_ARRAY(char, length); + jio_snprintf(error_msg, length, "%s%s", base_error_msg, jvmti_error_name); + if (JVMTI_ERROR_INVALID_CLASS_FORMAT == error) { + JfrJavaSupport::throw_class_format_error(error_msg, THREAD); + } else { + JfrJavaSupport::throw_runtime_exception(error_msg, THREAD); + } } } @@ -137,12 +148,15 @@ } } +static bool is_valid_jvmti_phase() { + return JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE; +} + void JfrJvmtiAgent::retransform_classes(JNIEnv* env, jobjectArray classes_array, TRAPS) { assert(env != NULL, "invariant"); + assert(classes_array != NULL, "invariant"); + assert(is_valid_jvmti_phase(), "invariant"); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD)); - if (classes_array == NULL) { - return; - } const jint classes_count = env->GetArrayLength(classes_array); if (classes_count <= 0) { return; @@ -153,27 +167,27 @@ for (jint i = 0; i < classes_count; i++) { jclass clz = (jclass)env->GetObjectArrayElement(classes_array, i); check_exception_and_log(env, THREAD); - + classes[i] = clz; + } + { // inspecting the oop/klass requires a thread transition - { - ThreadInVMfromNative transition((JavaThread*)THREAD); - if (JdkJfrEvent::is_a(clz)) { - // should have been tagged already - assert(JdkJfrEvent::is_subklass(clz), "invariant"); - } else { + ThreadInVMfromNative transition((JavaThread*)THREAD); + for (jint i = 0; i < classes_count; ++i) { + jclass clz = classes[i]; + if (!JdkJfrEvent::is_a(clz)) { // outside the event hierarchy JdkJfrEvent::tag_as_host(clz); } } - - classes[i] = clz; } - if (jfr_jvmti_env->RetransformClasses(classes_count, classes) != JVMTI_ERROR_NONE) { - log_and_throw(THREAD); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD)); + const jvmtiError result = jfr_jvmti_env->RetransformClasses(classes_count, classes); + if (result != JVMTI_ERROR_NONE) { + log_and_throw(result, THREAD); } } -static jvmtiError register_callbacks(JavaThread* jt) { +static bool register_callbacks(JavaThread* jt) { assert(jfr_jvmti_env != NULL, "invariant"); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt)); jvmtiEventCallbacks callbacks; @@ -182,10 +196,10 @@ callbacks.ClassFileLoadHook = jfr_on_class_file_load_hook; const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks"); - return jvmti_ret_code; + return jvmti_ret_code == JVMTI_ERROR_NONE; } -static jvmtiError register_capabilities(JavaThread* jt) { +static bool register_capabilities(JavaThread* jt) { assert(jfr_jvmti_env != NULL, "invariant"); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt)); jvmtiCapabilities capabilities; @@ -195,7 +209,7 @@ capabilities.can_retransform_any_class = 1; const jvmtiError jvmti_ret_code = jfr_jvmti_env->AddCapabilities(&capabilities); check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "Add Capabilities"); - return jvmti_ret_code; + return jvmti_ret_code == JVMTI_ERROR_NONE; } static jint create_jvmti_env(JavaThread* jt) { @@ -206,16 +220,14 @@ return vm->GetEnv((void **)&jfr_jvmti_env, JVMTI_VERSION); } -static jvmtiError unregister_callbacks(JavaThread* jt) { - if (jfr_jvmti_env == NULL) { - return JVMTI_ERROR_NONE; - } +static bool unregister_callbacks(JavaThread* jt) { + assert(jfr_jvmti_env != NULL, "invariant"); jvmtiEventCallbacks callbacks; /* Set empty callbacks */ memset(&callbacks, 0, sizeof(callbacks)); const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks"); - return jvmti_ret_code; + return jvmti_ret_code == JVMTI_ERROR_NONE; } JfrJvmtiAgent::JfrJvmtiAgent() {} @@ -223,20 +235,17 @@ JfrJvmtiAgent::~JfrJvmtiAgent() { JavaThread* jt = current_java_thread(); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); - ThreadToNativeFromVM transition(jt); - update_class_file_load_hook_event(JVMTI_DISABLE); - unregister_callbacks(jt); if (jfr_jvmti_env != NULL) { + ThreadToNativeFromVM transition(jt); + update_class_file_load_hook_event(JVMTI_DISABLE); + unregister_callbacks(jt); jfr_jvmti_env->DisposeEnvironment(); jfr_jvmti_env = NULL; } - agent = NULL; } -static bool initialize() { - JavaThread* const jt = current_java_thread(); +static bool initialize(JavaThread* jt) { assert(jt != NULL, "invariant"); - assert(jt->thread_state() == _thread_in_vm, "invariant"); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); ThreadToNativeFromVM transition(jt); if (create_jvmti_env(jt) != JNI_OK) { @@ -244,25 +253,36 @@ return false; } assert(jfr_jvmti_env != NULL, "invariant"); - if (register_capabilities(jt) != JVMTI_ERROR_NONE) { + if (!register_capabilities(jt)) { + return false; + } + if (!register_callbacks(jt)) { return false; } - if (register_callbacks(jt) != JVMTI_ERROR_NONE) { - return false; - } - if (update_class_file_load_hook_event(JVMTI_ENABLE) != JVMTI_ERROR_NONE) { - return false; - } - return true; + return update_class_file_load_hook_event(JVMTI_ENABLE); +} + +static void log_and_throw_illegal_state_exception(TRAPS) { + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); + const char* const illegal_state_msg = "An attempt was made to start JFR too early in the VM initialization sequence."; + log_error(jfr, system)(illegal_state_msg); + log_error(jfr, system)("JFR uses JVMTI RetransformClasses and requires the JVMTI state to have entered JVMTI_PHASE_LIVE."); + log_error(jfr, system)("Please initialize JFR in response to event JVMTI_EVENT_VM_INIT instead of JVMTI_EVENT_VM_START."); + JfrJavaSupport::throw_illegal_state_exception(illegal_state_msg, THREAD); } bool JfrJvmtiAgent::create() { - assert(jfr_jvmti_env == NULL, "invariant"); + assert(agent == NULL, "invariant"); + JavaThread* const jt = current_java_thread(); + if (!is_valid_jvmti_phase()) { + log_and_throw_illegal_state_exception(jt); + return false; + } agent = new JfrJvmtiAgent(); if (agent == NULL) { return false; } - if (!initialize()) { + if (!initialize(jt)) { delete agent; agent = NULL; return false; @@ -276,4 +296,3 @@ agent = NULL; } } - diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/jfr.cpp --- a/src/hotspot/share/jfr/jfr.cpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/jfr.cpp Mon Nov 25 18:38:01 2019 +0100 @@ -45,15 +45,21 @@ return JfrRecorder::is_recording(); } -void Jfr::on_vm_init() { - if (!JfrRecorder::on_vm_init()) { - vm_exit_during_initialization("Failure when starting JFR on_vm_init"); +void Jfr::on_create_vm_1() { + if (!JfrRecorder::on_create_vm_1()) { + vm_exit_during_initialization("Failure when starting JFR on_create_vm_1"); } } -void Jfr::on_vm_start() { - if (!JfrRecorder::on_vm_start()) { - vm_exit_during_initialization("Failure when starting JFR on_vm_start"); +void Jfr::on_create_vm_2() { + if (!JfrRecorder::on_create_vm_2()) { + vm_exit_during_initialization("Failure when starting JFR on_create_vm_2"); + } +} + +void Jfr::on_create_vm_3() { + if (!JfrRecorder::on_create_vm_3()) { + vm_exit_during_initialization("Failure when starting JFR on_create_vm_3"); } } diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/jfr.hpp --- a/src/hotspot/share/jfr/jfr.hpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/jfr.hpp Mon Nov 25 18:38:01 2019 +0100 @@ -43,8 +43,9 @@ static bool is_enabled(); static bool is_disabled(); static bool is_recording(); - static void on_vm_init(); - static void on_vm_start(); + static void on_create_vm_1(); + static void on_create_vm_2(); + static void on_create_vm_3(); static void on_unloading_classes(); static void on_thread_start(Thread* thread); static void on_thread_exit(Thread* thread); diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/jni/jfrJavaSupport.cpp --- a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp Mon Nov 25 18:38:01 2019 +0100 @@ -540,6 +540,10 @@ create_and_throw(vmSymbols::java_lang_ClassFormatError(), message, THREAD); } +void JfrJavaSupport::throw_runtime_exception(const char* message, TRAPS) { + create_and_throw(vmSymbols::java_lang_RuntimeException(), message, THREAD); +} + void JfrJavaSupport::abort(jstring errorMsg, Thread* t) { DEBUG_ONLY(check_java_thread_in_vm(t)); diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/jni/jfrJavaSupport.hpp --- a/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp Mon Nov 25 18:38:01 2019 +0100 @@ -84,6 +84,7 @@ static void throw_internal_error(const char* message, TRAPS); static void throw_out_of_memory_error(const char* message, TRAPS); static void throw_class_format_error(const char* message, TRAPS); + static void throw_runtime_exception(const char* message, TRAPS); static bool is_jdk_jfr_module_available(); static bool is_jdk_jfr_module_available(outputStream* stream, TRAPS); diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/jni/jfrJniMethod.cpp --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp Mon Nov 25 18:38:01 2019 +0100 @@ -192,7 +192,9 @@ return JNI_TRUE; } if (!JfrRecorder::create(simulate_failure == JNI_TRUE)) { - JfrJavaSupport::throw_illegal_state_exception("Unable to start Jfr", thread); + if (!thread->has_pending_exception()) { + JfrJavaSupport::throw_illegal_state_exception("Unable to start Jfr", thread); + } return JNI_FALSE; } return JNI_TRUE; diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/recorder/jfrRecorder.cpp --- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp Mon Nov 25 18:38:01 2019 +0100 @@ -46,6 +46,9 @@ #include "runtime/handles.inline.hpp" #include "runtime/globals_extension.hpp" #include "utilities/growableArray.hpp" +#ifdef ASSERT +#include "prims/jvmtiEnvBase.hpp" +#endif bool JfrRecorder::is_disabled() { // True if -XX:-FlightRecorder has been explicitly set on the @@ -57,7 +60,9 @@ static bool enable() { assert(!_enabled, "invariant"); - FLAG_SET_MGMT(FlightRecorder, true); + if (!FlightRecorder) { + FLAG_SET_MGMT(FlightRecorder, true); + } _enabled = FlightRecorder; assert(_enabled, "invariant"); return _enabled; @@ -67,7 +72,7 @@ return _enabled; } -bool JfrRecorder::on_vm_init() { +bool JfrRecorder::on_create_vm_1() { if (!is_disabled()) { if (FlightRecorder || StartFlightRecording != NULL) { enable(); @@ -92,7 +97,7 @@ static void teardown_startup_support() { release_recordings(); - JfrOptionSet::release_startup_recording_options(); + JfrOptionSet::release_start_flight_recording_options(); } // Parsing options here to detect errors as soon as possible @@ -110,7 +115,7 @@ } static bool validate_recording_options(TRAPS) { - const GrowableArray* options = JfrOptionSet::startup_recording_options(); + const GrowableArray* options = JfrOptionSet::start_flight_recording_options(); if (options == NULL) { return true; } @@ -143,7 +148,7 @@ return true; } -static bool launch_recordings(TRAPS) { +static bool launch_command_line_recordings(TRAPS) { bool result = true; if (dcmd_recordings_array != NULL) { const int length = dcmd_recordings_array->length(); @@ -168,7 +173,7 @@ static bool is_cds_dump_requested() { // we will not be able to launch recordings if a cds dump is being requested - if (Arguments::is_dumping_archive() && (JfrOptionSet::startup_recording_options() != NULL)) { + if (Arguments::is_dumping_archive() && (JfrOptionSet::start_flight_recording_options() != NULL)) { warning("JFR will be disabled during CDS dumping"); teardown_startup_support(); return true; @@ -176,7 +181,7 @@ return false; } -bool JfrRecorder::on_vm_start() { +bool JfrRecorder::on_create_vm_2() { if (is_cds_dump_requested()) { return true; } @@ -187,9 +192,7 @@ if (!register_jfr_dcmds()) { return false; } - const bool in_graph = JfrJavaSupport::is_jdk_jfr_module_available(); - if (in_graph) { if (!validate_recording_options(thread)) { return false; @@ -198,17 +201,19 @@ return false; } } - if (!is_enabled()) { return true; } - if (!in_graph) { log_jdk_jfr_module_resolution_error(thread); return false; } + return true; +} - return launch_recordings(thread); +bool JfrRecorder::on_create_vm_3() { + assert(JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE, "invalid init sequence"); + return launch_command_line_recordings(Thread::current()); } static bool _created = false; @@ -277,7 +282,6 @@ } // subsystems -static JfrJvmtiAgent* _jvmti_agent = NULL; static JfrPostBox* _post_box = NULL; static JfrStorage* _storage = NULL; static JfrCheckpointManager* _checkpoint_manager = NULL; diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/recorder/jfrRecorder.hpp --- a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp Mon Nov 25 18:38:01 2019 +0100 @@ -38,6 +38,9 @@ friend class Jfr; friend void recorderthread_entry(JavaThread*, Thread*); private: + static bool on_create_vm_1(); + static bool on_create_vm_2(); + static bool on_create_vm_3(); static bool create_checkpoint_manager(); static bool create_chunk_repository(); static bool create_java_event_writer(); @@ -52,8 +55,6 @@ static bool create_components(); static void destroy_components(); static void on_recorder_thread_exit(); - static bool on_vm_start(); - static bool on_vm_init(); public: static bool is_enabled(); diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp --- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp Mon Nov 25 18:38:01 2019 +0100 @@ -677,7 +677,7 @@ return false; } -static GrowableArray* startup_recording_options_array = NULL; +static GrowableArray* start_flight_recording_options_array = NULL; bool JfrOptionSet::parse_start_flight_recording_option(const JavaVMOption** option, char* delimiter) { assert(option != NULL, "invariant"); @@ -700,28 +700,28 @@ assert(value != NULL, "invariant"); const size_t value_length = strlen(value); - if (startup_recording_options_array == NULL) { - startup_recording_options_array = new (ResourceObj::C_HEAP, mtTracing) GrowableArray(8, true, mtTracing); + if (start_flight_recording_options_array == NULL) { + start_flight_recording_options_array = new (ResourceObj::C_HEAP, mtTracing) GrowableArray(8, true, mtTracing); } - assert(startup_recording_options_array != NULL, "invariant"); + assert(start_flight_recording_options_array != NULL, "invariant"); char* const startup_value = NEW_C_HEAP_ARRAY(char, value_length + 1, mtTracing); strncpy(startup_value, value, value_length + 1); assert(strncmp(startup_value, value, value_length) == 0, "invariant"); - startup_recording_options_array->append(startup_value); + start_flight_recording_options_array->append(startup_value); return false; } -const GrowableArray* JfrOptionSet::startup_recording_options() { - return startup_recording_options_array; +const GrowableArray* JfrOptionSet::start_flight_recording_options() { + return start_flight_recording_options_array; } -void JfrOptionSet::release_startup_recording_options() { - if (startup_recording_options_array != NULL) { - const int length = startup_recording_options_array->length(); +void JfrOptionSet::release_start_flight_recording_options() { + if (start_flight_recording_options_array != NULL) { + const int length = start_flight_recording_options_array->length(); for (int i = 0; i < length; ++i) { - FREE_C_HEAP_ARRAY(char, startup_recording_options_array->at(i)); + FREE_C_HEAP_ARRAY(char, start_flight_recording_options_array->at(i)); } - delete startup_recording_options_array; - startup_recording_options_array = NULL; + delete start_flight_recording_options_array; + start_flight_recording_options_array = NULL; } } diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp --- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp Mon Nov 25 18:38:01 2019 +0100 @@ -80,8 +80,8 @@ static bool parse_flight_recorder_option(const JavaVMOption** option, char* delimiter); static bool parse_start_flight_recording_option(const JavaVMOption** option, char* delimiter); - static const GrowableArray* startup_recording_options(); - static void release_startup_recording_options(); + static const GrowableArray* start_flight_recording_options(); + static void release_start_flight_recording_options(); }; #endif // SHARE_JFR_RECORDER_SERVICE_JFROPTIONSET_HPP diff -r 4c2557ab304e -r 127ca611f19b src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp Mon Nov 25 15:21:44 2019 +0000 +++ b/src/hotspot/share/runtime/thread.cpp Mon Nov 25 18:38:01 2019 +0100 @@ -3887,7 +3887,7 @@ return status; } - JFR_ONLY(Jfr::on_vm_init();) + JFR_ONLY(Jfr::on_create_vm_1();) // Should be done after the heap is fully created main_thread->cache_global_variables(); @@ -4026,6 +4026,8 @@ // loaded until phase 2 completes call_initPhase2(CHECK_JNI_ERR); + JFR_ONLY(Jfr::on_create_vm_2();) + // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution JvmtiExport::enter_start_phase(); @@ -4061,7 +4063,7 @@ // Notify JVMTI agents that VM initialization is complete - nop if no agents. JvmtiExport::post_vm_initialized(); - JFR_ONLY(Jfr::on_vm_start();) + JFR_ONLY(Jfr::on_create_vm_3();) #if INCLUDE_MANAGEMENT Management::initialize(THREAD); diff -r 4c2557ab304e -r 127ca611f19b src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java Mon Nov 25 15:21:44 2019 +0000 +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java Mon Nov 25 18:38:01 2019 +0100 @@ -203,6 +203,8 @@ * Call to invoke event tagging and retransformation of the passed classes * * @param classes + * + * @throws IllegalStateException if wrong JVMTI phase. */ public native synchronized void retransformClasses(Class[] classes); diff -r 4c2557ab304e -r 127ca611f19b src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java Mon Nov 25 15:21:44 2019 +0000 +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java Mon Nov 25 18:38:01 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. 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 @@ -123,6 +123,8 @@ list.add(java.lang.Error.class); Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Retransformed JDK classes"); jvm.retransformClasses(list.toArray(new Class[list.size()])); + } catch (IllegalStateException ise) { + throw ise; } catch (Exception e) { Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not add instrumentation for JDK events. " + e.getMessage()); }