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/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 "logging/log.hpp"
  44 #include "logging/logStream.hpp"
  45 #include "memory/resourceArea.inline.hpp"
  46 #include "runtime/handles.inline.hpp"
  47 #include "runtime/globals.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(!_enabled, "invariant");
  69   _enabled = set_flight_recorder_flag(true);
  70   return _enabled;
  71 }
  72 
  73 bool JfrRecorder::is_enabled() {
  74   return _enabled;
  75 }
  76 
  77 bool JfrRecorder::on_vm_init() {
  78   if (!is_disabled()) {
  79     if (FlightRecorder || StartFlightRecording != NULL) {
  80       enable();
  81     }
  82   }
  83   // fast time initialization
  84   return JfrTraceTime::initialize();
  85 }
  86 
  87 static JfrStartFlightRecordingDCmd* _startup_recording = NULL;
  88 
  89 // Parsing options here to detect errors as soon as possible
  90 static bool parse_startup_recording(TRAPS) {
  91   assert(StartFlightRecording != NULL, "invariant");
  92   CmdLine cmdline(StartFlightRecording, strlen(StartFlightRecording), true);
  93   _startup_recording->parse(&cmdline, ',', THREAD);
  94   if (HAS_PENDING_EXCEPTION) {
  95     java_lang_Throwable::print(PENDING_EXCEPTION, tty);
  96     CLEAR_PENDING_EXCEPTION;
  97     return false;
  98   }
  99   return true;
 100 }
 101 
 102 static bool initialize_startup_recording(TRAPS) {
 103   if (StartFlightRecording != NULL) {
 104     _startup_recording = new (ResourceObj::C_HEAP, mtTracing) JfrStartFlightRecordingDCmd(tty, true);
 105     return _startup_recording != NULL && parse_startup_recording(THREAD);
 106   }
 107   return true;
 108 }
 109 
 110 static bool startup_recording(TRAPS) {
 111   if (_startup_recording == NULL) {
 112     return true;
 113   }
 114   log_trace(jfr, system)("Starting up Jfr startup recording");
 115   _startup_recording->execute(DCmd_Source_Internal, Thread::current());
 116   delete _startup_recording;
 117   _startup_recording = NULL;
 118   if (HAS_PENDING_EXCEPTION) {
 119     log_debug(jfr, system)("Exception while starting Jfr startup recording");
 120     CLEAR_PENDING_EXCEPTION;
 121     return false;
 122   }
 123   log_trace(jfr, system)("Finished starting Jfr startup recording");
 124   return true;
 125 }
 126 
 127 static void log_jdk_jfr_module_resolution_error(TRAPS) {
 128   LogTarget(Error, jfr, system) lt_error;
 129   LogTargetHandle handle(lt_error);
 130   LogStream stream(handle);
 131   JfrJavaSupport::is_jdk_jfr_module_available(&stream, THREAD);
 132 }
 133 
 134 bool JfrRecorder::on_vm_start() {
 135   const bool in_graph = JfrJavaSupport::is_jdk_jfr_module_available();
 136   Thread* const thread = Thread::current();
 137   if (!JfrOptionSet::initialize(thread)) {
 138     return false;
 139   }
 140   if (!register_jfr_dcmds()) {
 141     return false;
 142   }
 143   if (!initialize_startup_recording(thread)) {
 144     return false;
 145   }
 146   if (in_graph) {
 147     if (!JfrJavaEventWriter::initialize()) {
 148       return false;
 149     }
 150     if (!JfrOptionSet::configure(thread)) {
 151       return false;
 152     }
 153   }
 154   if (!is_enabled()) {
 155     return true;
 156   }
 157   if (!in_graph) {
 158     log_jdk_jfr_module_resolution_error(thread);
 159     return false;
 160   }
 161   return startup_recording(thread);
 162 }
 163 
 164 static bool _created = false;
 165 
 166 //
 167 // Main entry point for starting Jfr functionality.
 168 // Non-protected initializations assume single-threaded setup.
 169 //
 170 bool JfrRecorder::create(bool simulate_failure) {
 171   assert(!is_disabled(), "invariant");
 172   assert(!is_created(), "invariant");
 173   if (!is_enabled()) {
 174     enable();
 175   }
 176   if (!create_components() || simulate_failure) {
 177     destroy_components();
 178     return false;
 179   }
 180   if (!create_recorder_thread()) {
 181     destroy_components();
 182     return false;
 183   }
 184   _created = true;
 185   return true;
 186 }
 187 
 188 bool JfrRecorder::is_created() {
 189   return _created;
 190 }
 191 
 192 bool JfrRecorder::create_components() {
 193   ResourceMark rm;
 194   HandleMark hm;
 195 
 196   if (!create_jvmti_agent()) {
 197     return false;
 198   }
 199   if (!create_post_box()) {
 200     return false;
 201   }
 202   if (!create_chunk_repository()) {
 203     return false;
 204   }
 205   if (!create_storage()) {
 206     return false;
 207   }
 208   if (!create_checkpoint_manager()) {
 209     return false;
 210   }
 211   if (!create_stacktrace_repository()) {
 212     return false;
 213   }
 214   if (!create_os_interface()) {
 215     return false;
 216   }
 217   if (!create_stringpool()) {
 218     return false;
 219   }
 220   if (!create_thread_sampling()) {
 221     return false;
 222   }
 223   return true;
 224 }
 225 
 226 // subsystems
 227 static JfrJvmtiAgent* _jvmti_agent = NULL;
 228 static JfrPostBox* _post_box = NULL;
 229 static JfrStorage* _storage = NULL;
 230 static JfrCheckpointManager* _checkpoint_manager = NULL;
 231 static JfrRepository* _repository = NULL;
 232 static JfrStackTraceRepository* _stack_trace_repository;
 233 static JfrStringPool* _stringpool = NULL;
 234 static JfrOSInterface* _os_interface = NULL;
 235 static JfrThreadSampling* _thread_sampling = NULL;
 236 
 237 bool JfrRecorder::create_jvmti_agent() {
 238   return JfrOptionSet::allow_retransforms() ? JfrJvmtiAgent::create() : true;
 239 }
 240 
 241 bool JfrRecorder::create_post_box() {
 242   assert(_post_box == NULL, "invariant");
 243   _post_box = JfrPostBox::create();
 244   return _post_box != NULL;
 245 }
 246 
 247 bool JfrRecorder::create_chunk_repository() {
 248   assert(_repository == NULL, "invariant");
 249   assert(_post_box != NULL, "invariant");
 250   _repository = JfrRepository::create(*_post_box);
 251   return _repository != NULL && _repository->initialize();
 252 }
 253 
 254 bool JfrRecorder::create_os_interface() {
 255   assert(_os_interface == NULL, "invariant");
 256   _os_interface = JfrOSInterface::create();
 257   return _os_interface != NULL && _os_interface->initialize();
 258 }
 259 
 260 bool JfrRecorder::create_storage() {
 261   assert(_repository != NULL, "invariant");
 262   assert(_post_box != NULL, "invariant");
 263   _storage = JfrStorage::create(_repository->chunkwriter(), *_post_box);
 264   return _storage != NULL && _storage->initialize();
 265 }
 266 
 267 bool JfrRecorder::create_checkpoint_manager() {
 268   assert(_checkpoint_manager == NULL, "invariant");
 269   assert(_repository != NULL, "invariant");
 270   _checkpoint_manager = JfrCheckpointManager::create(_repository->chunkwriter());
 271   return _checkpoint_manager != NULL && _checkpoint_manager->initialize();
 272 }
 273 
 274 bool JfrRecorder::create_stacktrace_repository() {
 275   assert(_stack_trace_repository == NULL, "invariant");
 276   _stack_trace_repository = JfrStackTraceRepository::create();
 277   return _stack_trace_repository != NULL && _stack_trace_repository->initialize();
 278 }
 279 
 280 bool JfrRecorder::create_stringpool() {
 281   assert(_stringpool == NULL, "invariant");
 282   assert(_repository != NULL, "invariant");
 283   _stringpool = JfrStringPool::create(_repository->chunkwriter());
 284   return _stringpool != NULL && _stringpool->initialize();
 285 }
 286 
 287 bool JfrRecorder::create_thread_sampling() {
 288   assert(_thread_sampling == NULL, "invariant");
 289   _thread_sampling = JfrThreadSampling::create();
 290   return _thread_sampling != NULL;
 291 }
 292 
 293 void JfrRecorder::destroy_components() {
 294   JfrJvmtiAgent::destroy();
 295   if (_post_box != NULL) {
 296     JfrPostBox::destroy();
 297     _post_box = NULL;
 298   }
 299   if (_repository != NULL) {
 300     JfrRepository::destroy();
 301     _repository = NULL;
 302   }
 303   if (_storage != NULL) {
 304     JfrStorage::destroy();
 305     _storage = NULL;
 306   }
 307   if (_checkpoint_manager != NULL) {
 308     JfrCheckpointManager::destroy();
 309     _checkpoint_manager = NULL;
 310   }
 311   if (_stack_trace_repository != NULL) {
 312     JfrStackTraceRepository::destroy();
 313     _stack_trace_repository = NULL;
 314   }
 315   if (_stringpool != NULL) {
 316     JfrStringPool::destroy();
 317     _stringpool = NULL;
 318   }
 319   if (_os_interface != NULL) {
 320     JfrOSInterface::destroy();
 321     _os_interface = NULL;
 322   }
 323   if (_thread_sampling != NULL) {
 324     JfrThreadSampling::destroy();
 325     _thread_sampling = NULL;
 326   }
 327 }
 328 
 329 bool JfrRecorder::create_recorder_thread() {
 330   return JfrRecorderThread::start(_checkpoint_manager, _post_box, Thread::current());
 331 }
 332 
 333 void JfrRecorder::destroy() {
 334   assert(is_created(), "invariant");
 335   _post_box->post(MSG_SHUTDOWN);
 336   JfrJvmtiAgent::destroy();
 337 }
 338 
 339 void JfrRecorder::on_recorder_thread_exit() {
 340   assert(!is_recording(), "invariant");
 341   // intent is to destroy the recorder instance and components,
 342   // but need sensitive coordination not yet in place
 343   //
 344   // destroy_components();
 345   //
 346   log_debug(jfr, system)("Recorder thread STOPPED");
 347 }
 348 
 349 void JfrRecorder::start_recording() {
 350   _post_box->post(MSG_START);
 351 }
 352 
 353 bool JfrRecorder::is_recording() {
 354   return JfrRecorderService::is_recording();
 355 }
 356 
 357 void JfrRecorder::stop_recording() {
 358   _post_box->post(MSG_STOP);
 359 }