src/hotspot/share/jfr/recorder/jfrRecorder.cpp
changeset 50113 caf115bb98ad
child 50664 857ce291c70c
equal deleted inserted replaced
50112:7a2a740815b7 50113:caf115bb98ad
       
     1 /*
       
     2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "jfr/dcmd/jfrDcmds.hpp"
       
    27 #include "jfr/instrumentation/jfrJvmtiAgent.hpp"
       
    28 #include "jfr/jni/jfrJavaSupport.hpp"
       
    29 #include "jfr/periodic/jfrOSInterface.hpp"
       
    30 #include "jfr/periodic/sampling/jfrThreadSampler.hpp"
       
    31 #include "jfr/recorder/jfrRecorder.hpp"
       
    32 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
       
    33 #include "jfr/recorder/repository/jfrRepository.hpp"
       
    34 #include "jfr/recorder/service/jfrOptionSet.hpp"
       
    35 #include "jfr/recorder/service/jfrPostBox.hpp"
       
    36 #include "jfr/recorder/service/jfrRecorderService.hpp"
       
    37 #include "jfr/recorder/service/jfrRecorderThread.hpp"
       
    38 #include "jfr/recorder/storage/jfrStorage.hpp"
       
    39 #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
       
    40 #include "jfr/recorder/stringpool/jfrStringPool.hpp"
       
    41 #include "jfr/utilities/jfrTime.hpp"
       
    42 #include "jfr/writers/jfrJavaEventWriter.hpp"
       
    43 #include "logging/log.hpp"
       
    44 #include "logging/logStream.hpp"
       
    45 #include "memory/resourceArea.inline.hpp"
       
    46 #include "runtime/handles.inline.hpp"
       
    47 #include "runtime/flags/jvmFlag.hpp"
       
    48 #include "runtime/globals.hpp"
       
    49 
       
    50 static bool is_disabled_on_command_line() {
       
    51   static const size_t length = strlen("FlightRecorder");
       
    52   static JVMFlag* const flight_recorder_flag = JVMFlag::find_flag("FlightRecorder", length);
       
    53   assert(flight_recorder_flag != NULL, "invariant");
       
    54   return flight_recorder_flag->is_command_line() ? !FlightRecorder : false;
       
    55 }
       
    56 
       
    57 bool JfrRecorder::is_disabled() {
       
    58   return is_disabled_on_command_line();
       
    59 }
       
    60 
       
    61 static bool set_flight_recorder_flag(bool flag_value) {
       
    62   JVMFlag::boolAtPut((char*)"FlightRecorder", &flag_value, JVMFlag::MANAGEMENT);
       
    63   return FlightRecorder;
       
    64 }
       
    65 
       
    66 static bool _enabled = false;
       
    67 
       
    68 static bool enable() {
       
    69   assert(!_enabled, "invariant");
       
    70   _enabled = set_flight_recorder_flag(true);
       
    71   return _enabled;
       
    72 }
       
    73 
       
    74 bool JfrRecorder::is_enabled() {
       
    75   return _enabled;
       
    76 }
       
    77 
       
    78 bool JfrRecorder::on_vm_init() {
       
    79   if (!is_disabled()) {
       
    80     if (FlightRecorder || StartFlightRecording != NULL) {
       
    81       enable();
       
    82     }
       
    83   }
       
    84   // fast time initialization
       
    85   return JfrTime::initialize();
       
    86 }
       
    87 
       
    88 static JfrStartFlightRecordingDCmd* _startup_recording = NULL;
       
    89 
       
    90 // Parsing options here to detect errors as soon as possible
       
    91 static bool parse_startup_recording(TRAPS) {
       
    92   assert(StartFlightRecording != NULL, "invariant");
       
    93   CmdLine cmdline(StartFlightRecording, strlen(StartFlightRecording), true);
       
    94   _startup_recording->parse(&cmdline, ',', THREAD);
       
    95   if (HAS_PENDING_EXCEPTION) {
       
    96     java_lang_Throwable::print(PENDING_EXCEPTION, tty);
       
    97     CLEAR_PENDING_EXCEPTION;
       
    98     return false;
       
    99   }
       
   100   return true;
       
   101 }
       
   102 
       
   103 static bool initialize_startup_recording(TRAPS) {
       
   104   if (StartFlightRecording != NULL) {
       
   105     _startup_recording = new (ResourceObj::C_HEAP, mtTracing) JfrStartFlightRecordingDCmd(tty, true);
       
   106     return _startup_recording != NULL && parse_startup_recording(THREAD);
       
   107   }
       
   108   return true;
       
   109 }
       
   110 
       
   111 static bool startup_recording(TRAPS) {
       
   112   if (_startup_recording == NULL) {
       
   113     return true;
       
   114   }
       
   115   log_trace(jfr, system)("Starting up Jfr startup recording");
       
   116   _startup_recording->execute(DCmd_Source_Internal, Thread::current());
       
   117   delete _startup_recording;
       
   118   _startup_recording = NULL;
       
   119   if (HAS_PENDING_EXCEPTION) {
       
   120     log_debug(jfr, system)("Exception while starting Jfr startup recording");
       
   121     CLEAR_PENDING_EXCEPTION;
       
   122     return false;
       
   123   }
       
   124   log_trace(jfr, system)("Finished starting Jfr startup recording");
       
   125   return true;
       
   126 }
       
   127 
       
   128 static void log_jdk_jfr_module_resolution_error(TRAPS) {
       
   129   LogTarget(Error, jfr, system) lt_error;
       
   130   LogTargetHandle handle(lt_error);
       
   131   LogStream stream(handle);
       
   132   JfrJavaSupport::is_jdk_jfr_module_available(&stream, THREAD);
       
   133 }
       
   134 
       
   135 bool JfrRecorder::on_vm_start() {
       
   136   const bool in_graph = JfrJavaSupport::is_jdk_jfr_module_available();
       
   137   Thread* const thread = Thread::current();
       
   138   if (!JfrOptionSet::initialize(thread)) {
       
   139     return false;
       
   140   }
       
   141   if (!register_jfr_dcmds()) {
       
   142     return false;
       
   143   }
       
   144   if (!initialize_startup_recording(thread)) {
       
   145     return false;
       
   146   }
       
   147   if (in_graph) {
       
   148     if (!JfrJavaEventWriter::initialize()) {
       
   149       return false;
       
   150     }
       
   151     if (!JfrOptionSet::configure(thread)) {
       
   152       return false;
       
   153     }
       
   154   }
       
   155   if (!is_enabled()) {
       
   156     return true;
       
   157   }
       
   158   if (!in_graph) {
       
   159     log_jdk_jfr_module_resolution_error(thread);
       
   160     return false;
       
   161   }
       
   162   return startup_recording(thread);
       
   163 }
       
   164 
       
   165 static bool _created = false;
       
   166 
       
   167 //
       
   168 // Main entry point for starting Jfr functionality.
       
   169 // Non-protected initializations assume single-threaded setup.
       
   170 //
       
   171 bool JfrRecorder::create(bool simulate_failure) {
       
   172   assert(!is_disabled(), "invariant");
       
   173   assert(!is_created(), "invariant");
       
   174   if (!is_enabled()) {
       
   175     enable();
       
   176   }
       
   177   if (!create_components() || simulate_failure) {
       
   178     destroy_components();
       
   179     return false;
       
   180   }
       
   181   if (!create_recorder_thread()) {
       
   182     destroy_components();
       
   183     return false;
       
   184   }
       
   185   _created = true;
       
   186   return true;
       
   187 }
       
   188 
       
   189 bool JfrRecorder::is_created() {
       
   190   return _created;
       
   191 }
       
   192 
       
   193 bool JfrRecorder::create_components() {
       
   194   ResourceMark rm;
       
   195   HandleMark hm;
       
   196 
       
   197   if (!create_jvmti_agent()) {
       
   198     return false;
       
   199   }
       
   200   if (!create_post_box()) {
       
   201     return false;
       
   202   }
       
   203   if (!create_chunk_repository()) {
       
   204     return false;
       
   205   }
       
   206   if (!create_storage()) {
       
   207     return false;
       
   208   }
       
   209   if (!create_checkpoint_manager()) {
       
   210     return false;
       
   211   }
       
   212   if (!create_stacktrace_repository()) {
       
   213     return false;
       
   214   }
       
   215   if (!create_os_interface()) {
       
   216     return false;
       
   217   }
       
   218   if (!create_stringpool()) {
       
   219     return false;
       
   220   }
       
   221   if (!create_thread_sampling()) {
       
   222     return false;
       
   223   }
       
   224   return true;
       
   225 }
       
   226 
       
   227 // subsystems
       
   228 static JfrJvmtiAgent* _jvmti_agent = NULL;
       
   229 static JfrPostBox* _post_box = NULL;
       
   230 static JfrStorage* _storage = NULL;
       
   231 static JfrCheckpointManager* _checkpoint_manager = NULL;
       
   232 static JfrRepository* _repository = NULL;
       
   233 static JfrStackTraceRepository* _stack_trace_repository;
       
   234 static JfrStringPool* _stringpool = NULL;
       
   235 static JfrOSInterface* _os_interface = NULL;
       
   236 static JfrThreadSampling* _thread_sampling = NULL;
       
   237 
       
   238 bool JfrRecorder::create_jvmti_agent() {
       
   239   return JfrOptionSet::allow_retransforms() ? JfrJvmtiAgent::create() : true;
       
   240 }
       
   241 
       
   242 bool JfrRecorder::create_post_box() {
       
   243   assert(_post_box == NULL, "invariant");
       
   244   _post_box = JfrPostBox::create();
       
   245   return _post_box != NULL;
       
   246 }
       
   247 
       
   248 bool JfrRecorder::create_chunk_repository() {
       
   249   assert(_repository == NULL, "invariant");
       
   250   assert(_post_box != NULL, "invariant");
       
   251   _repository = JfrRepository::create(*_post_box);
       
   252   return _repository != NULL && _repository->initialize();
       
   253 }
       
   254 
       
   255 bool JfrRecorder::create_os_interface() {
       
   256   assert(_os_interface == NULL, "invariant");
       
   257   _os_interface = JfrOSInterface::create();
       
   258   return _os_interface != NULL && _os_interface->initialize();
       
   259 }
       
   260 
       
   261 bool JfrRecorder::create_storage() {
       
   262   assert(_repository != NULL, "invariant");
       
   263   assert(_post_box != NULL, "invariant");
       
   264   _storage = JfrStorage::create(_repository->chunkwriter(), *_post_box);
       
   265   return _storage != NULL && _storage->initialize();
       
   266 }
       
   267 
       
   268 bool JfrRecorder::create_checkpoint_manager() {
       
   269   assert(_checkpoint_manager == NULL, "invariant");
       
   270   assert(_repository != NULL, "invariant");
       
   271   _checkpoint_manager = JfrCheckpointManager::create(_repository->chunkwriter());
       
   272   return _checkpoint_manager != NULL && _checkpoint_manager->initialize();
       
   273 }
       
   274 
       
   275 bool JfrRecorder::create_stacktrace_repository() {
       
   276   assert(_stack_trace_repository == NULL, "invariant");
       
   277   _stack_trace_repository = JfrStackTraceRepository::create();
       
   278   return _stack_trace_repository != NULL && _stack_trace_repository->initialize();
       
   279 }
       
   280 
       
   281 bool JfrRecorder::create_stringpool() {
       
   282   assert(_stringpool == NULL, "invariant");
       
   283   assert(_repository != NULL, "invariant");
       
   284   _stringpool = JfrStringPool::create(_repository->chunkwriter());
       
   285   return _stringpool != NULL && _stringpool->initialize();
       
   286 }
       
   287 
       
   288 bool JfrRecorder::create_thread_sampling() {
       
   289   assert(_thread_sampling == NULL, "invariant");
       
   290   _thread_sampling = JfrThreadSampling::create();
       
   291   return _thread_sampling != NULL;
       
   292 }
       
   293 
       
   294 void JfrRecorder::destroy_components() {
       
   295   JfrJvmtiAgent::destroy();
       
   296   if (_post_box != NULL) {
       
   297     JfrPostBox::destroy();
       
   298     _post_box = NULL;
       
   299   }
       
   300   if (_repository != NULL) {
       
   301     JfrRepository::destroy();
       
   302     _repository = NULL;
       
   303   }
       
   304   if (_storage != NULL) {
       
   305     JfrStorage::destroy();
       
   306     _storage = NULL;
       
   307   }
       
   308   if (_checkpoint_manager != NULL) {
       
   309     JfrCheckpointManager::destroy();
       
   310     _checkpoint_manager = NULL;
       
   311   }
       
   312   if (_stack_trace_repository != NULL) {
       
   313     JfrStackTraceRepository::destroy();
       
   314     _stack_trace_repository = NULL;
       
   315   }
       
   316   if (_stringpool != NULL) {
       
   317     JfrStringPool::destroy();
       
   318     _stringpool = NULL;
       
   319   }
       
   320   if (_os_interface != NULL) {
       
   321     JfrOSInterface::destroy();
       
   322     _os_interface = NULL;
       
   323   }
       
   324   if (_thread_sampling != NULL) {
       
   325     JfrThreadSampling::destroy();
       
   326     _thread_sampling = NULL;
       
   327   }
       
   328 }
       
   329 
       
   330 bool JfrRecorder::create_recorder_thread() {
       
   331   return JfrRecorderThread::start(_checkpoint_manager, _post_box, Thread::current());
       
   332 }
       
   333 
       
   334 void JfrRecorder::destroy() {
       
   335   assert(is_created(), "invariant");
       
   336   _post_box->post(MSG_SHUTDOWN);
       
   337   JfrJvmtiAgent::destroy();
       
   338 }
       
   339 
       
   340 void JfrRecorder::on_recorder_thread_exit() {
       
   341   assert(!is_recording(), "invariant");
       
   342   // intent is to destroy the recorder instance and components,
       
   343   // but need sensitive coordination not yet in place
       
   344   //
       
   345   // destroy_components();
       
   346   //
       
   347   log_debug(jfr, system)("Recorder thread STOPPED");
       
   348 }
       
   349 
       
   350 void JfrRecorder::start_recording() {
       
   351   _post_box->post(MSG_START);
       
   352 }
       
   353 
       
   354 bool JfrRecorder::is_recording() {
       
   355   return JfrRecorderService::is_recording();
       
   356 }
       
   357 
       
   358 void JfrRecorder::stop_recording() {
       
   359   _post_box->post(MSG_STOP);
       
   360 }