1 /*
   2  * Copyright (c) 2012, 2019, 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/access/jfrOptionSet.hpp"
  33 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
  34 #include "jfr/recorder/repository/jfrRepository.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/jfrTraceTime.hpp"
  42 #include "jfr/writers/jfrJavaEventWriter.hpp"
  43 #include "jfr/utilities/jfrLog.hpp"
  44 #include "memory/resourceArea.hpp"
  45 #include "runtime/handles.inline.hpp"
  46 #include "runtime/globals.hpp"
  47 #include "utilities/defaultStream.hpp"
  48 
  49 static bool is_disabled_on_command_line() {
  50   static const size_t length = strlen("FlightRecorder");
  51   static Flag* const flight_recorder_flag = Flag::find_flag("FlightRecorder", length);
  52   assert(flight_recorder_flag != NULL, "invariant");
  53   return flight_recorder_flag->is_command_line() ? !FlightRecorder : false;
  54 }
  55 
  56 bool JfrRecorder::is_disabled() {
  57   return is_disabled_on_command_line();
  58 }
  59 
  60 static bool set_flight_recorder_flag(bool flag_value) {
  61   CommandLineFlags::boolAtPut((char*)"FlightRecorder", &flag_value, Flag::MANAGEMENT);
  62   return FlightRecorder;
  63 }
  64 
  65 static bool _enabled = false;
  66 
  67 static bool enable() {
  68   assert(EnableJFR, "invariant");
  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 JfrTraceTime::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 }
 130 
 131 bool JfrRecorder::on_vm_start() {
 132   const bool in_graph = true;
 133   Thread* const thread = Thread::current();
 134   if (!JfrOptionSet::initialize(thread)) {
 135     return false;
 136   }
 137   if (!register_jfr_dcmds()) {
 138     return false;
 139   }
 140   if (!initialize_startup_recording(thread)) {
 141     return false;
 142   }
 143   if (in_graph) {
 144     if (!JfrJavaEventWriter::initialize()) {
 145       return false;
 146     }
 147     if (!JfrOptionSet::configure(thread)) {
 148       return false;
 149     }
 150   }
 151   if (!is_enabled()) {
 152     return true;
 153   }
 154   if (!in_graph) {
 155     log_jdk_jfr_module_resolution_error(thread);
 156     return false;
 157   }
 158   return startup_recording(thread);
 159 }
 160 
 161 static bool _created = false;
 162 
 163 //
 164 // Main entry point for starting Jfr functionality.
 165 // Non-protected initializations assume single-threaded setup.
 166 //
 167 bool JfrRecorder::create(bool simulate_failure) {
 168   assert(!is_disabled(), "invariant");
 169   assert(!is_created(), "invariant");
 170   if (!EnableJFR) {
 171     jio_fprintf(defaultStream::error_stream(), "Can't create JFR if EnableJFR is false.");
 172     return false;
 173   }
 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 }