src/share/vm/jfr/recorder/jfrRecorder.cpp

Mon, 12 Aug 2019 18:30:40 +0300

author
apetushkov
date
Mon, 12 Aug 2019 18:30:40 +0300
changeset 9858
b985cbb00e68
child 9879
d2b51a10084d
permissions
-rw-r--r--

8223147: JFR Backport
8199712: Flight Recorder
8203346: JFR: Inconsistent signature of jfr_add_string_constant
8195817: JFR.stop should require name of recording
8195818: JFR.start should increase autogenerated name by one
8195819: Remove recording=x from jcmd JFR.check output
8203921: JFR thread sampling is missing fixes from JDK-8194552
8203929: Limit amount of data for JFR.dump
8203664: JFR start failure after AppCDS archive created with JFR StartFlightRecording
8003209: JFR events for network utilization
8207392: [PPC64] Implement JFR profiling
8202835: jfr/event/os/TestSystemProcess.java fails on missing events
Summary: Backport JFR from JDK11. Initial integration
Reviewed-by: neugens

     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  */
    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 "memory/resourceArea.hpp"
    44 #include "runtime/handles.inline.hpp"
    45 #include "runtime/globals.hpp"
    46 #include "utilities/growableArray.hpp"
    48 bool JfrRecorder::_shutting_down = false;
    50 static bool is_disabled_on_command_line() {
    51   static const size_t length = strlen("FlightRecorder");
    52   static Flag* const flight_recorder_flag = Flag::find_flag("FlightRecorder", length);
    53   assert(flight_recorder_flag != NULL, "invariant");
    54   return flight_recorder_flag->is_command_line() ? !FlightRecorder : false;
    55 }
    57 bool JfrRecorder::is_disabled() {
    58   return is_disabled_on_command_line();
    59 }
    61 static bool set_flight_recorder_flag(bool flag_value) {
    62   CommandLineFlags::boolAtPut((char*)"FlightRecorder", &flag_value, Flag::MANAGEMENT);
    63   return FlightRecorder;
    64 }
    66 static bool _enabled = false;
    68 static bool enable() {
    69   assert(!_enabled, "invariant");
    70   _enabled = set_flight_recorder_flag(true);
    71   return _enabled;
    72 }
    74 bool JfrRecorder::is_enabled() {
    75   return _enabled;
    76 }
    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 }
    88 static GrowableArray<JfrStartFlightRecordingDCmd*>* dcmd_recordings_array = NULL;
    90 static void release_recordings() {
    91   if (dcmd_recordings_array != NULL) {
    92     const int length = dcmd_recordings_array->length();
    93     for (int i = 0; i < length; ++i) {
    94       delete dcmd_recordings_array->at(i);
    95     }
    96     delete dcmd_recordings_array;
    97     dcmd_recordings_array = NULL;
    98   }
    99 }
   101 static void teardown_startup_support() {
   102   release_recordings();
   103   JfrOptionSet::release_startup_recording_options();
   104 }
   106 // Parsing options here to detect errors as soon as possible
   107 static bool parse_recording_options(const char* options, JfrStartFlightRecordingDCmd* dcmd_recording, TRAPS) {
   108   assert(options != NULL, "invariant");
   109   assert(dcmd_recording != NULL, "invariant");
   110   CmdLine cmdline(options, strlen(options), true);
   111   dcmd_recording->parse(&cmdline, ',', THREAD);
   112   if (HAS_PENDING_EXCEPTION) {
   113     java_lang_Throwable::print(PENDING_EXCEPTION, tty);
   114     CLEAR_PENDING_EXCEPTION;
   115     return false;
   116   }
   117   return true;
   118 }
   120 static bool validate_recording_options(TRAPS) {
   121   const GrowableArray<const char*>* options = JfrOptionSet::startup_recording_options();
   122   if (options == NULL) {
   123     return true;
   124   }
   125   const int length = options->length();
   126   assert(length >= 1, "invariant");
   127   assert(dcmd_recordings_array == NULL, "invariant");
   128   dcmd_recordings_array = new (ResourceObj::C_HEAP, mtTracing)GrowableArray<JfrStartFlightRecordingDCmd*>(length, true, mtTracing);
   129   assert(dcmd_recordings_array != NULL, "invariant");
   130   for (int i = 0; i < length; ++i) {
   131     JfrStartFlightRecordingDCmd* const dcmd_recording = new(ResourceObj::C_HEAP, mtTracing) JfrStartFlightRecordingDCmd(tty, true);
   132     assert(dcmd_recording != NULL, "invariant");
   133     dcmd_recordings_array->append(dcmd_recording);
   134     if (!parse_recording_options(options->at(i), dcmd_recording, THREAD)) {
   135       return false;
   136     }
   137   }
   138   return true;
   139 }
   141 static bool launch_recording(JfrStartFlightRecordingDCmd* dcmd_recording, TRAPS) {
   142   assert(dcmd_recording != NULL, "invariant");
   143   if (LogJFR && Verbose) tty->print_cr("Starting a recording");
   144   dcmd_recording->execute(DCmd_Source_Internal, THREAD);
   145   if (HAS_PENDING_EXCEPTION) {
   146     if (LogJFR) tty->print_cr("Exception while starting a recording");
   147     CLEAR_PENDING_EXCEPTION;
   148     return false;
   149   }
   150   if (LogJFR && Verbose) tty->print_cr("Finished starting a recording");
   151   return true;
   152 }
   154 static bool launch_recordings(TRAPS) {
   155   bool result = true;
   156   if (dcmd_recordings_array != NULL) {
   157     const int length = dcmd_recordings_array->length();
   158     assert(length >= 1, "invariant");
   159     for (int i = 0; i < length; ++i) {
   160       if (!launch_recording(dcmd_recordings_array->at(i), THREAD)) {
   161         result = false;
   162         break;
   163       }
   164     }
   165   }
   166   teardown_startup_support();
   167   return result;
   168 }
   170 static bool is_cds_dump_requested() {
   171   // we will not be able to launch recordings if a cds dump is being requested
   172   if (DumpSharedSpaces && (JfrOptionSet::startup_recording_options() != NULL)) {
   173     warning("JFR will be disabled during CDS dumping");
   174     teardown_startup_support();
   175     return true;
   176   }
   177   return false;
   178 }
   180 bool JfrRecorder::on_vm_start() {
   181   if (is_cds_dump_requested()) {
   182     return true;
   183   }
   184   Thread* const thread = Thread::current();
   185   if (!JfrJavaEventWriter::has_required_classes(thread)) {
   186     // assume it is compact profile of jfr.jar is missed for some reasons
   187     // skip further initialization.
   188     return true;
   189   }
   190   if (!JfrOptionSet::initialize(thread)) {
   191     return false;
   192   }
   193   if (!register_jfr_dcmds()) {
   194     return false;
   195   }
   197   if (!validate_recording_options(thread)) {
   198     return false;
   199   }
   200   if (!JfrJavaEventWriter::initialize()) {
   201     return false;
   202   }
   203   if (!JfrOptionSet::configure(thread)) {
   204     return false;
   205   }
   207   if (!is_enabled()) {
   208     return true;
   209   }
   211   return launch_recordings(thread);
   212 }
   214 static bool _created = false;
   216 //
   217 // Main entry point for starting Jfr functionality.
   218 // Non-protected initializations assume single-threaded setup.
   219 //
   220 bool JfrRecorder::create(bool simulate_failure) {
   221   assert(!is_disabled(), "invariant");
   222   assert(!is_created(), "invariant");
   223   if (!is_enabled()) {
   224     enable();
   225   }
   226   if (!create_components() || simulate_failure) {
   227     destroy_components();
   228     return false;
   229   }
   230   if (!create_recorder_thread()) {
   231     destroy_components();
   232     return false;
   233   }
   234   _created = true;
   235   return true;
   236 }
   238 bool JfrRecorder::is_created() {
   239   return _created;
   240 }
   242 bool JfrRecorder::create_components() {
   243   ResourceMark rm;
   244   HandleMark hm;
   246   if (!create_jvmti_agent()) {
   247     return false;
   248   }
   249   if (!create_post_box()) {
   250     return false;
   251   }
   252   if (!create_chunk_repository()) {
   253     return false;
   254   }
   255   if (!create_storage()) {
   256     return false;
   257   }
   258   if (!create_checkpoint_manager()) {
   259     return false;
   260   }
   261   if (!create_stacktrace_repository()) {
   262     return false;
   263   }
   264   if (!create_os_interface()) {
   265     return false;
   266   }
   267   if (!create_stringpool()) {
   268     return false;
   269   }
   270   if (!create_thread_sampling()) {
   271     return false;
   272   }
   273   return true;
   274 }
   276 // subsystems
   277 static JfrJvmtiAgent* _jvmti_agent = NULL;
   278 static JfrPostBox* _post_box = NULL;
   279 static JfrStorage* _storage = NULL;
   280 static JfrCheckpointManager* _checkpoint_manager = NULL;
   281 static JfrRepository* _repository = NULL;
   282 static JfrStackTraceRepository* _stack_trace_repository;
   283 static JfrStringPool* _stringpool = NULL;
   284 static JfrOSInterface* _os_interface = NULL;
   285 static JfrThreadSampling* _thread_sampling = NULL;
   287 bool JfrRecorder::create_jvmti_agent() {
   288   return JfrOptionSet::allow_retransforms() ? JfrJvmtiAgent::create() : true;
   289 }
   291 bool JfrRecorder::create_post_box() {
   292   assert(_post_box == NULL, "invariant");
   293   _post_box = JfrPostBox::create();
   294   return _post_box != NULL;
   295 }
   297 bool JfrRecorder::create_chunk_repository() {
   298   assert(_repository == NULL, "invariant");
   299   assert(_post_box != NULL, "invariant");
   300   _repository = JfrRepository::create(*_post_box);
   301   return _repository != NULL && _repository->initialize();
   302 }
   304 bool JfrRecorder::create_os_interface() {
   305   assert(_os_interface == NULL, "invariant");
   306   _os_interface = JfrOSInterface::create();
   307   return _os_interface != NULL && _os_interface->initialize();
   308 }
   310 bool JfrRecorder::create_storage() {
   311   assert(_repository != NULL, "invariant");
   312   assert(_post_box != NULL, "invariant");
   313   _storage = JfrStorage::create(_repository->chunkwriter(), *_post_box);
   314   return _storage != NULL && _storage->initialize();
   315 }
   317 bool JfrRecorder::create_checkpoint_manager() {
   318   assert(_checkpoint_manager == NULL, "invariant");
   319   assert(_repository != NULL, "invariant");
   320   _checkpoint_manager = JfrCheckpointManager::create(_repository->chunkwriter());
   321   return _checkpoint_manager != NULL && _checkpoint_manager->initialize();
   322 }
   324 bool JfrRecorder::create_stacktrace_repository() {
   325   assert(_stack_trace_repository == NULL, "invariant");
   326   _stack_trace_repository = JfrStackTraceRepository::create();
   327   return _stack_trace_repository != NULL && _stack_trace_repository->initialize();
   328 }
   330 bool JfrRecorder::create_stringpool() {
   331   assert(_stringpool == NULL, "invariant");
   332   assert(_repository != NULL, "invariant");
   333   _stringpool = JfrStringPool::create(_repository->chunkwriter());
   334   return _stringpool != NULL && _stringpool->initialize();
   335 }
   337 bool JfrRecorder::create_thread_sampling() {
   338   assert(_thread_sampling == NULL, "invariant");
   339   _thread_sampling = JfrThreadSampling::create();
   340   return _thread_sampling != NULL;
   341 }
   343 void JfrRecorder::destroy_components() {
   344   JfrJvmtiAgent::destroy();
   345   if (_post_box != NULL) {
   346     JfrPostBox::destroy();
   347     _post_box = NULL;
   348   }
   349   if (_repository != NULL) {
   350     JfrRepository::destroy();
   351     _repository = NULL;
   352   }
   353   if (_storage != NULL) {
   354     JfrStorage::destroy();
   355     _storage = NULL;
   356   }
   357   if (_checkpoint_manager != NULL) {
   358     JfrCheckpointManager::destroy();
   359     _checkpoint_manager = NULL;
   360   }
   361   if (_stack_trace_repository != NULL) {
   362     JfrStackTraceRepository::destroy();
   363     _stack_trace_repository = NULL;
   364   }
   365   if (_stringpool != NULL) {
   366     JfrStringPool::destroy();
   367     _stringpool = NULL;
   368   }
   369   if (_os_interface != NULL) {
   370     JfrOSInterface::destroy();
   371     _os_interface = NULL;
   372   }
   373   if (_thread_sampling != NULL) {
   374     JfrThreadSampling::destroy();
   375     _thread_sampling = NULL;
   376   }
   377 }
   379 bool JfrRecorder::create_recorder_thread() {
   380   return JfrRecorderThread::start(_checkpoint_manager, _post_box, Thread::current());
   381 }
   383 void JfrRecorder::destroy() {
   384   assert(is_created(), "invariant");
   385   _post_box->post(MSG_SHUTDOWN);
   386   JfrJvmtiAgent::destroy();
   387 }
   389 void JfrRecorder::on_recorder_thread_exit() {
   390   assert(!is_recording(), "invariant");
   391   // intent is to destroy the recorder instance and components,
   392   // but need sensitive coordination not yet in place
   393   //
   394   // destroy_components();
   395   //
   396   if (LogJFR) tty->print_cr("Recorder thread STOPPED");
   397 }
   399 void JfrRecorder::start_recording() {
   400   _post_box->post(MSG_START);
   401 }
   403 bool JfrRecorder::is_recording() {
   404   return JfrRecorderService::is_recording();
   405 }
   407 void JfrRecorder::stop_recording() {
   408   _post_box->post(MSG_STOP);
   409 }

mercurial