1 /*
  2  * Copyright (c) 2012, 2021, 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 "classfile/javaClasses.hpp"
 27 #include "jfr/dcmd/jfrDcmds.hpp"
 28 #include "jfr/instrumentation/jfrJvmtiAgent.hpp"
 29 #include "jfr/jni/jfrJavaSupport.hpp"
 30 #include "jfr/leakprofiler/sampling/objectSampler.hpp"
 31 #include "jfr/periodic/jfrOSInterface.hpp"
 32 #include "jfr/periodic/sampling/jfrThreadSampler.hpp"
 33 #include "jfr/recorder/jfrRecorder.hpp"
 34 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
 35 #include "jfr/recorder/repository/jfrRepository.hpp"
 36 #include "jfr/recorder/service/jfrEventThrottler.hpp"
 37 #include "jfr/recorder/service/jfrOptionSet.hpp"
 38 #include "jfr/recorder/service/jfrPostBox.hpp"
 39 #include "jfr/recorder/service/jfrRecorderService.hpp"
 40 #include "jfr/recorder/service/jfrRecorderThread.hpp"
 41 #include "jfr/recorder/storage/jfrStorage.hpp"
 42 #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
 43 #include "jfr/recorder/stringpool/jfrStringPool.hpp"
 44 #include "jfr/utilities/jfrTime.hpp"
 45 #include "jfr/writers/jfrJavaEventWriter.hpp"
 46 #include "logging/log.hpp"
 47 #include "logging/logStream.hpp"
 48 #include "memory/resourceArea.inline.hpp"
 49 #include "runtime/handles.inline.hpp"
 50 #include "runtime/globals_extension.hpp"
 51 #include "utilities/growableArray.hpp"
 52 #ifdef ASSERT
 53 #include "prims/jvmtiEnvBase.hpp"
 54 #endif
 55 
 56 bool JfrRecorder::is_disabled() {
 57   // True if -XX:-FlightRecorder has been explicitly set on the
 58   // command line
 59   return FLAG_IS_CMDLINE(FlightRecorder) ? !FlightRecorder : false;
 60 }
 61 
 62 static bool _enabled = false;
 63 
 64 static bool enable() {
 65   assert(!_enabled, "invariant");
 66   if (!FlightRecorder) {
 67     FLAG_SET_MGMT(FlightRecorder, true);
 68   }
 69   _enabled = FlightRecorder;
 70   assert(_enabled, "invariant");
 71   return _enabled;
 72 }
 73 
 74 bool JfrRecorder::is_enabled() {
 75   return _enabled;
 76 }
 77 
 78 bool JfrRecorder::create_oop_storages() {
 79   // currently only a single weak oop storage for Leak Profiler
 80   return ObjectSampler::create_oop_storage();
 81 }
 82 
 83 bool JfrRecorder::on_create_vm_1() {
 84   if (!is_disabled()) {
 85     if (FlightRecorder || StartFlightRecording != NULL) {
 86       enable();
 87     }
 88   }
 89   if (!create_oop_storages()) {
 90     return false;
 91   }
 92   // fast time initialization
 93   return JfrTime::initialize();
 94 }
 95 
 96 static GrowableArray<JfrStartFlightRecordingDCmd*>* dcmd_recordings_array = NULL;
 97 
 98 static void release_recordings() {
 99   if (dcmd_recordings_array != NULL) {
100     const int length = dcmd_recordings_array->length();
101     for (int i = 0; i < length; ++i) {
102       delete dcmd_recordings_array->at(i);
103     }
104     delete dcmd_recordings_array;
105     dcmd_recordings_array = NULL;
106   }
107 }
108 
109 static void teardown_startup_support() {
110   release_recordings();
111   JfrOptionSet::release_start_flight_recording_options();
112 }
113 
114 // Parsing options here to detect errors as soon as possible
115 static bool parse_recording_options(const char* options, JfrStartFlightRecordingDCmd* dcmd_recording, TRAPS) {
116   assert(options != NULL, "invariant");
117   assert(dcmd_recording != NULL, "invariant");
118   CmdLine cmdline(options, strlen(options), true);
119   dcmd_recording->parse(&cmdline, ',', THREAD);
120   if (HAS_PENDING_EXCEPTION) {
121     java_lang_Throwable::print(PENDING_EXCEPTION, tty);
122     CLEAR_PENDING_EXCEPTION;
123     return false;
124   }
125   return true;
126 }
127 
128 static bool validate_recording_options(TRAPS) {
129   const GrowableArray<const char*>* options = JfrOptionSet::start_flight_recording_options();
130   if (options == NULL) {
131     return true;
132   }
133   const int length = options->length();
134   assert(length >= 1, "invariant");
135   assert(dcmd_recordings_array == NULL, "invariant");
136   dcmd_recordings_array = new (ResourceObj::C_HEAP, mtTracing)GrowableArray<JfrStartFlightRecordingDCmd*>(length, mtTracing);
137   assert(dcmd_recordings_array != NULL, "invariant");
138   for (int i = 0; i < length; ++i) {
139     JfrStartFlightRecordingDCmd* const dcmd_recording = new(ResourceObj::C_HEAP, mtTracing) JfrStartFlightRecordingDCmd(tty, true);
140     assert(dcmd_recording != NULL, "invariant");
141     dcmd_recordings_array->append(dcmd_recording);
142     if (!parse_recording_options(options->at(i), dcmd_recording, THREAD)) {
143       return false;
144     }
145   }
146   return true;
147 }
148 
149 static bool launch_recording(JfrStartFlightRecordingDCmd* dcmd_recording, TRAPS) {
150   assert(dcmd_recording != NULL, "invariant");
151   log_trace(jfr, system)("Starting a recording");
152   dcmd_recording->execute(DCmd_Source_Internal, THREAD);
153   if (HAS_PENDING_EXCEPTION) {
154     log_debug(jfr, system)("Exception while starting a recording");
155     CLEAR_PENDING_EXCEPTION;
156     return false;
157   }
158   log_trace(jfr, system)("Finished starting a recording");
159   return true;
160 }
161 
162 static bool launch_command_line_recordings(TRAPS) {
163   bool result = true;
164   if (dcmd_recordings_array != NULL) {
165     const int length = dcmd_recordings_array->length();
166     assert(length >= 1, "invariant");
167     for (int i = 0; i < length; ++i) {
168       if (!launch_recording(dcmd_recordings_array->at(i), THREAD)) {
169         result = false;
170         break;
171       }
172     }
173   }
174   teardown_startup_support();
175   return result;
176 }
177 
178 static void log_jdk_jfr_module_resolution_error(TRAPS) {
179   LogTarget(Error, jfr, system) lt_error;
180   LogTargetHandle handle(lt_error);
181   LogStream stream(handle);
182   JfrJavaSupport::is_jdk_jfr_module_available(&stream, THREAD);
183 }
184 
185 static bool is_cds_dump_requested() {
186   // we will not be able to launch recordings on startup if a cds dump is being requested
187   if (Arguments::is_dumping_archive() && JfrOptionSet::start_flight_recording_options() != NULL) {
188     warning("JFR will be disabled during CDS dumping");
189     teardown_startup_support();
190     return true;
191   }
192   return false;
193 }
194 
195 bool JfrRecorder::on_create_vm_2() {
196   if (is_cds_dump_requested()) {
197     return true;
198   }
199   JavaThread* const thread = JavaThread::current();
200   if (!JfrOptionSet::initialize(thread)) {
201     return false;
202   }
203   if (!register_jfr_dcmds()) {
204     return false;
205   }
206   const bool in_graph = JfrJavaSupport::is_jdk_jfr_module_available();
207   if (in_graph) {
208     if (!validate_recording_options(thread)) {
209       return false;
210     }
211     if (!JfrOptionSet::configure(thread)) {
212       return false;
213     }
214   }
215   if (!is_enabled()) {
216     return true;
217   }
218   if (!in_graph) {
219     log_jdk_jfr_module_resolution_error(thread);
220     return false;
221   }
222   return true;
223 }
224 
225 bool JfrRecorder::on_create_vm_3() {
226   assert(JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE, "invalid init sequence");
227   return Arguments::is_dumping_archive() || launch_command_line_recordings(JavaThread::current());
228 }
229 
230 static bool _created = false;
231 
232 //
233 // Main entry point for starting Jfr functionality.
234 // Non-protected initializations assume single-threaded setup.
235 //
236 bool JfrRecorder::create(bool simulate_failure) {
237   assert(!is_disabled(), "invariant");
238   assert(!is_created(), "invariant");
239   if (!is_enabled()) {
240     enable();
241   }
242   if (!create_components() || simulate_failure) {
243     destroy_components();
244     return false;
245   }
246   if (!create_recorder_thread()) {
247     destroy_components();
248     return false;
249   }
250   _created = true;
251   return true;
252 }
253 
254 bool JfrRecorder::is_created() {
255   return _created;
256 }
257 
258 bool JfrRecorder::create_components() {
259   // Move these down into the functions that might create handles!
260   ResourceMark rm(Thread::current());
261   HandleMark hm(Thread::current());
262 
263   if (!create_java_event_writer()) {
264     return false;
265   }
266   if (!create_jvmti_agent()) {
267     return false;
268   }
269   if (!create_post_box()) {
270     return false;
271   }
272   if (!create_chunk_repository()) {
273     return false;
274   }
275   if (!create_storage()) {
276     return false;
277   }
278   if (!create_checkpoint_manager()) {
279     return false;
280   }
281   if (!create_stacktrace_repository()) {
282     return false;
283   }
284   if (!create_os_interface()) {
285     return false;
286   }
287   if (!create_stringpool()) {
288     return false;
289   }
290   if (!create_thread_sampling()) {
291     return false;
292   }
293   if (!create_event_throttler()) {
294     return false;
295   }
296   return true;
297 }
298 
299 // subsystems
300 static JfrPostBox* _post_box = NULL;
301 static JfrStorage* _storage = NULL;
302 static JfrCheckpointManager* _checkpoint_manager = NULL;
303 static JfrRepository* _repository = NULL;
304 static JfrStackTraceRepository* _stack_trace_repository;
305 static JfrStringPool* _stringpool = NULL;
306 static JfrOSInterface* _os_interface = NULL;
307 static JfrThreadSampling* _thread_sampling = NULL;
308 
309 bool JfrRecorder::create_java_event_writer() {
310   return JfrJavaEventWriter::initialize();
311 }
312 
313 bool JfrRecorder::create_jvmti_agent() {
314   return JfrOptionSet::allow_retransforms() ? JfrJvmtiAgent::create() : true;
315 }
316 
317 bool JfrRecorder::create_post_box() {
318   assert(_post_box == NULL, "invariant");
319   _post_box = JfrPostBox::create();
320   return _post_box != NULL;
321 }
322 
323 bool JfrRecorder::create_chunk_repository() {
324   assert(_repository == NULL, "invariant");
325   assert(_post_box != NULL, "invariant");
326   _repository = JfrRepository::create(*_post_box);
327   return _repository != NULL && _repository->initialize();
328 }
329 
330 bool JfrRecorder::create_os_interface() {
331   assert(_os_interface == NULL, "invariant");
332   _os_interface = JfrOSInterface::create();
333   return _os_interface != NULL && _os_interface->initialize();
334 }
335 
336 bool JfrRecorder::create_storage() {
337   assert(_repository != NULL, "invariant");
338   assert(_post_box != NULL, "invariant");
339   _storage = JfrStorage::create(_repository->chunkwriter(), *_post_box);
340   return _storage != NULL && _storage->initialize();
341 }
342 
343 bool JfrRecorder::create_checkpoint_manager() {
344   assert(_checkpoint_manager == NULL, "invariant");
345   assert(_repository != NULL, "invariant");
346   _checkpoint_manager = JfrCheckpointManager::create(_repository->chunkwriter());
347   return _checkpoint_manager != NULL && _checkpoint_manager->initialize();
348 }
349 
350 bool JfrRecorder::create_stacktrace_repository() {
351   assert(_stack_trace_repository == NULL, "invariant");
352   _stack_trace_repository = JfrStackTraceRepository::create();
353   return _stack_trace_repository != NULL && _stack_trace_repository->initialize();
354 }
355 
356 bool JfrRecorder::create_stringpool() {
357   assert(_stringpool == NULL, "invariant");
358   assert(_repository != NULL, "invariant");
359   _stringpool = JfrStringPool::create(_repository->chunkwriter());
360   return _stringpool != NULL && _stringpool->initialize();
361 }
362 
363 bool JfrRecorder::create_thread_sampling() {
364   assert(_thread_sampling == NULL, "invariant");
365   _thread_sampling = JfrThreadSampling::create();
366   return _thread_sampling != NULL;
367 }
368 
369 bool JfrRecorder::create_event_throttler() {
370   return JfrEventThrottler::create();
371 }
372 
373 void JfrRecorder::destroy_components() {
374   JfrJvmtiAgent::destroy();
375   if (_post_box != NULL) {
376     JfrPostBox::destroy();
377     _post_box = NULL;
378   }
379   if (_repository != NULL) {
380     JfrRepository::destroy();
381     _repository = NULL;
382   }
383   if (_storage != NULL) {
384     JfrStorage::destroy();
385     _storage = NULL;
386   }
387   if (_checkpoint_manager != NULL) {
388     JfrCheckpointManager::destroy();
389     _checkpoint_manager = NULL;
390   }
391   if (_stack_trace_repository != NULL) {
392     JfrStackTraceRepository::destroy();
393     _stack_trace_repository = NULL;
394   }
395   if (_stringpool != NULL) {
396     JfrStringPool::destroy();
397     _stringpool = NULL;
398   }
399   if (_os_interface != NULL) {
400     JfrOSInterface::destroy();
401     _os_interface = NULL;
402   }
403   if (_thread_sampling != NULL) {
404     JfrThreadSampling::destroy();
405     _thread_sampling = NULL;
406   }
407   JfrEventThrottler::destroy();
408 }
409 
410 bool JfrRecorder::create_recorder_thread() {
411   return JfrRecorderThread::start(_checkpoint_manager, _post_box, JavaThread::current());
412 }
413 
414 void JfrRecorder::destroy() {
415   assert(is_created(), "invariant");
416   _post_box->post(MSG_SHUTDOWN);
417   JfrJvmtiAgent::destroy();
418 }
419 
420 void JfrRecorder::on_recorder_thread_exit() {
421   assert(!is_recording(), "invariant");
422   // intent is to destroy the recorder instance and components,
423   // but need sensitive coordination not yet in place
424   //
425   // destroy_components();
426   //
427   log_debug(jfr, system)("Recorder thread STOPPED");
428 }
429 
430 void JfrRecorder::start_recording() {
431   _post_box->post(MSG_START);
432 }
433 
434 bool JfrRecorder::is_recording() {
435   return JfrRecorderService::is_recording();
436 }
437 
438 void JfrRecorder::stop_recording() {
439   _post_box->post(MSG_STOP);
440 }