src/hotspot/share/jfr/recorder/jfrRecorder.cpp
changeset 50873 ce53844224b6
parent 50851 b1b5306fadea
child 53303 65a1d49d1718
equal deleted inserted replaced
50872:308410473abe 50873:ce53844224b6
    44 #include "logging/logStream.hpp"
    44 #include "logging/logStream.hpp"
    45 #include "memory/resourceArea.inline.hpp"
    45 #include "memory/resourceArea.inline.hpp"
    46 #include "runtime/handles.inline.hpp"
    46 #include "runtime/handles.inline.hpp"
    47 #include "runtime/flags/jvmFlag.hpp"
    47 #include "runtime/flags/jvmFlag.hpp"
    48 #include "runtime/globals.hpp"
    48 #include "runtime/globals.hpp"
       
    49 #include "utilities/growableArray.hpp"
    49 
    50 
    50 static bool is_disabled_on_command_line() {
    51 static bool is_disabled_on_command_line() {
    51   static const size_t length = strlen("FlightRecorder");
    52   static const size_t length = strlen("FlightRecorder");
    52   static JVMFlag* const flight_recorder_flag = JVMFlag::find_flag("FlightRecorder", length);
    53   static JVMFlag* const flight_recorder_flag = JVMFlag::find_flag("FlightRecorder", length);
    53   assert(flight_recorder_flag != NULL, "invariant");
    54   assert(flight_recorder_flag != NULL, "invariant");
    83   }
    84   }
    84   // fast time initialization
    85   // fast time initialization
    85   return JfrTime::initialize();
    86   return JfrTime::initialize();
    86 }
    87 }
    87 
    88 
    88 static JfrStartFlightRecordingDCmd* _startup_recording = NULL;
    89 static GrowableArray<JfrStartFlightRecordingDCmd*>* dcmd_recordings_array = NULL;
    89 
    90 
    90 static void release_startup_recording() {
    91 static void release_recordings() {
    91   if (_startup_recording != NULL) {
    92   if (dcmd_recordings_array != NULL) {
    92     delete _startup_recording;
    93     const int length = dcmd_recordings_array->length();
    93     _startup_recording = NULL;
    94     for (int i = 0; i < length; ++i) {
       
    95       delete dcmd_recordings_array->at(i);
       
    96     }
       
    97     delete dcmd_recordings_array;
       
    98     dcmd_recordings_array = NULL;
    94   }
    99   }
    95 }
   100 }
    96 
   101 
    97 static void teardown_startup_support() {
   102 static void teardown_startup_support() {
    98   release_startup_recording();
   103   release_recordings();
    99   JfrOptionSet::release_startup_recordings();
   104   JfrOptionSet::release_startup_recording_options();
   100 }
   105 }
   101 
       
   102 
   106 
   103 // Parsing options here to detect errors as soon as possible
   107 // Parsing options here to detect errors as soon as possible
   104 static bool parse_recording_options(const char* options, TRAPS) {
   108 static bool parse_recording_options(const char* options, JfrStartFlightRecordingDCmd* dcmd_recording, TRAPS) {
   105   assert(options != NULL, "invariant");
   109   assert(options != NULL, "invariant");
   106   if (_startup_recording != NULL) {
   110   assert(dcmd_recording != NULL, "invariant");
   107     delete _startup_recording;
       
   108   }
       
   109   CmdLine cmdline(options, strlen(options), true);
   111   CmdLine cmdline(options, strlen(options), true);
   110   _startup_recording = new (ResourceObj::C_HEAP, mtTracing) JfrStartFlightRecordingDCmd(tty, true);
   112   dcmd_recording->parse(&cmdline, ',', THREAD);
   111   assert(_startup_recording != NULL, "invariant");
       
   112   _startup_recording->parse(&cmdline, ',', THREAD);
       
   113   if (HAS_PENDING_EXCEPTION) {
   113   if (HAS_PENDING_EXCEPTION) {
   114     java_lang_Throwable::print(PENDING_EXCEPTION, tty);
   114     java_lang_Throwable::print(PENDING_EXCEPTION, tty);
   115     CLEAR_PENDING_EXCEPTION;
   115     CLEAR_PENDING_EXCEPTION;
   116     return false;
   116     return false;
   117   }
   117   }
   118   return true;
   118   return true;
   119 }
   119 }
   120 
   120 
   121 static bool validate_recording_options(TRAPS) {
   121 static bool validate_recording_options(TRAPS) {
   122   const GrowableArray<const char*>* startup_options = JfrOptionSet::startup_recordings();
   122   const GrowableArray<const char*>* options = JfrOptionSet::startup_recording_options();
   123   if (startup_options == NULL) {
   123   if (options == NULL) {
   124     return true;
   124     return true;
   125   }
   125   }
   126   const int length = startup_options->length();
   126   const int length = options->length();
   127   assert(length >= 1, "invariant");
   127   assert(length >= 1, "invariant");
       
   128   assert(dcmd_recordings_array == NULL, "invariant");
       
   129   dcmd_recordings_array = new (ResourceObj::C_HEAP, mtTracing)GrowableArray<JfrStartFlightRecordingDCmd*>(length, true, mtTracing);
       
   130   assert(dcmd_recordings_array != NULL, "invariant");
   128   for (int i = 0; i < length; ++i) {
   131   for (int i = 0; i < length; ++i) {
   129     if (!parse_recording_options(startup_options->at(i), THREAD)) {
   132     JfrStartFlightRecordingDCmd* const dcmd_recording = new(ResourceObj::C_HEAP, mtTracing) JfrStartFlightRecordingDCmd(tty, true);
       
   133     assert(dcmd_recording != NULL, "invariant");
       
   134     dcmd_recordings_array->append(dcmd_recording);
       
   135     if (!parse_recording_options(options->at(i), dcmd_recording, THREAD)) {
   130       return false;
   136       return false;
   131     }
   137     }
   132   }
   138   }
   133   return true;
   139   return true;
   134 }
   140 }
   135 
   141 
   136 static bool launch_recording(TRAPS) {
   142 static bool launch_recording(JfrStartFlightRecordingDCmd* dcmd_recording, TRAPS) {
   137   assert(_startup_recording != NULL, "invariant");
   143   assert(dcmd_recording != NULL, "invariant");
   138   log_trace(jfr, system)("Starting a recording");
   144   log_trace(jfr, system)("Starting a recording");
   139   _startup_recording->execute(DCmd_Source_Internal, Thread::current());
   145   dcmd_recording->execute(DCmd_Source_Internal, THREAD);
   140   if (HAS_PENDING_EXCEPTION) {
   146   if (HAS_PENDING_EXCEPTION) {
   141     log_debug(jfr, system)("Exception while starting a recording");
   147     log_debug(jfr, system)("Exception while starting a recording");
   142     CLEAR_PENDING_EXCEPTION;
   148     CLEAR_PENDING_EXCEPTION;
   143     return false;
   149     return false;
   144   }
   150   }
   145   log_trace(jfr, system)("Finished starting a recording");
   151   log_trace(jfr, system)("Finished starting a recording");
   146   return true;
   152   return true;
   147 }
   153 }
   148 
   154 
   149 static bool launch_recordings(const GrowableArray<const char*>* startup_options, TRAPS) {
   155 static bool launch_recordings(TRAPS) {
   150   assert(startup_options != NULL, "invariant");
   156   bool result = true;
   151   const int length = startup_options->length();
   157   if (dcmd_recordings_array != NULL) {
   152   assert(length >= 1, "invariant");
   158     const int length = dcmd_recordings_array->length();
   153   if (length == 1) {
   159     assert(length >= 1, "invariant");
   154     // already parsed and ready, launch it
   160     for (int i = 0; i < length; ++i) {
   155     return launch_recording(THREAD);
   161       if (!launch_recording(dcmd_recordings_array->at(i), THREAD)) {
   156   }
   162         result = false;
   157   for (int i = 0; i < length; ++i) {
   163         break;
   158     parse_recording_options(startup_options->at(i), THREAD);
   164       }
   159     if (!launch_recording(THREAD)) {
   165     }
   160       return false;
   166   }
   161     }
       
   162   }
       
   163   return true;
       
   164 }
       
   165 
       
   166 static bool startup_recordings(TRAPS) {
       
   167   const GrowableArray<const char*>* startup_options = JfrOptionSet::startup_recordings();
       
   168   if (startup_options == NULL) {
       
   169     return true;
       
   170   }
       
   171   const bool ret = launch_recordings(startup_options, THREAD);
       
   172   teardown_startup_support();
   167   teardown_startup_support();
   173   return ret;
   168   return result;
   174 }
   169 }
   175 
   170 
   176 static void log_jdk_jfr_module_resolution_error(TRAPS) {
   171 static void log_jdk_jfr_module_resolution_error(TRAPS) {
   177   LogTarget(Error, jfr, system) lt_error;
   172   LogTarget(Error, jfr, system) lt_error;
   178   LogTargetHandle handle(lt_error);
   173   LogTargetHandle handle(lt_error);
   179   LogStream stream(handle);
   174   LogStream stream(handle);
   180   JfrJavaSupport::is_jdk_jfr_module_available(&stream, THREAD);
   175   JfrJavaSupport::is_jdk_jfr_module_available(&stream, THREAD);
   181 }
   176 }
   182 
   177 
   183 bool JfrRecorder::on_vm_start() {
   178 static bool is_cds_dump_requested() {
   184   if (DumpSharedSpaces && (JfrOptionSet::startup_recordings() != NULL)) {
   179   // we will not be able to launch recordings if a cds dump is being requested
       
   180   if (DumpSharedSpaces && (JfrOptionSet::startup_recording_options() != NULL)) {
   185     warning("JFR will be disabled during CDS dumping");
   181     warning("JFR will be disabled during CDS dumping");
   186     teardown_startup_support();
   182     teardown_startup_support();
   187     return true;
   183     return true;
   188   }
   184   }
   189   const bool in_graph = JfrJavaSupport::is_jdk_jfr_module_available();
   185   return false;
       
   186 }
       
   187 
       
   188 bool JfrRecorder::on_vm_start() {
       
   189   if (is_cds_dump_requested()) {
       
   190     return true;
       
   191   }
   190   Thread* const thread = Thread::current();
   192   Thread* const thread = Thread::current();
   191   if (!JfrOptionSet::initialize(thread)) {
   193   if (!JfrOptionSet::initialize(thread)) {
   192     return false;
   194     return false;
   193   }
   195   }
   194   if (!register_jfr_dcmds()) {
   196   if (!register_jfr_dcmds()) {
   195     return false;
   197     return false;
   196   }
   198   }
   197   if (!validate_recording_options(thread)) {
   199 
   198     return false;
   200   const bool in_graph = JfrJavaSupport::is_jdk_jfr_module_available();
   199   }
   201 
   200   if (in_graph) {
   202   if (in_graph) {
       
   203     if (!validate_recording_options(thread)) {
       
   204       return false;
       
   205     }
   201     if (!JfrJavaEventWriter::initialize()) {
   206     if (!JfrJavaEventWriter::initialize()) {
   202       return false;
   207       return false;
   203     }
   208     }
   204     if (!JfrOptionSet::configure(thread)) {
   209     if (!JfrOptionSet::configure(thread)) {
   205       return false;
   210       return false;
   206     }
   211     }
   207   }
   212   }
       
   213 
   208   if (!is_enabled()) {
   214   if (!is_enabled()) {
   209     return true;
   215     return true;
   210   }
   216   }
       
   217 
   211   if (!in_graph) {
   218   if (!in_graph) {
   212     log_jdk_jfr_module_resolution_error(thread);
   219     log_jdk_jfr_module_resolution_error(thread);
   213     return false;
   220     return false;
   214   }
   221   }
   215   return startup_recordings(thread);
   222 
       
   223   return launch_recordings(thread);
   216 }
   224 }
   217 
   225 
   218 static bool _created = false;
   226 static bool _created = false;
   219 
   227 
   220 //
   228 //