1 /*
2 * Copyright (c) 2012, 2025, 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 "classfile/javaClasses.inline.hpp"
26 #include "classfile/vmSymbols.hpp"
27 #include "jfr/dcmd/jfrDcmds.hpp"
28 #include "jfr/jfr.hpp"
29 #include "jfr/jni/jfrJavaSupport.hpp"
30 #include "jfr/recorder/jfrRecorder.hpp"
31 #include "jfr/recorder/service/jfrOptionSet.hpp"
32 #include "jfr/support/jfrThreadLocal.hpp"
33 #include "logging/log.hpp"
34 #include "logging/logConfiguration.hpp"
35 #include "logging/logMessage.hpp"
36 #include "memory/arena.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "oops/objArrayOop.inline.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "oops/symbol.hpp"
41 #include "runtime/handles.inline.hpp"
42 #include "runtime/jniHandles.hpp"
43 #include "services/diagnosticArgument.hpp"
44 #include "services/diagnosticFramework.hpp"
45 #include "utilities/globalDefinitions.hpp"
46
47
48 bool register_jfr_dcmds() {
49 uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean;
50 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrCheckFlightRecordingDCmd>(full_export));
51 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrDumpFlightRecordingDCmd>(full_export));
52 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStartFlightRecordingDCmd>(full_export));
53 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStopFlightRecordingDCmd>(full_export));
54 // JFR.query Uncomment when developing new queries for the JFR.view command
55 // DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrQueryFlightRecordingDCmd>(full_export, /*hidden=*/true));
56 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrViewFlightRecordingDCmd>(full_export));
57 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrConfigureFlightRecorderDCmd>(full_export));
58 return true;
59 }
95 }
96
97 static void handle_pending_exception(outputStream* output, bool startup, oop throwable) {
98 assert(throwable != nullptr, "invariant");
99
100 oop msg = java_lang_Throwable::message(throwable);
101 if (msg == nullptr) {
102 return;
103 }
104 char* text = java_lang_String::as_utf8_string(msg);
105 if (text != nullptr) {
106 if (startup) {
107 log_error(jfr,startup)("%s", text);
108 } else {
109 output->print_cr("%s", text);
110 }
111 }
112 }
113
114 static void print_message(outputStream* output, oop content, TRAPS) {
115 objArrayOop lines = objArrayOop(content);
116 assert(lines != nullptr, "invariant");
117 assert(lines->is_array(), "must be array");
118 const int length = lines->length();
119 for (int i = 0; i < length; ++i) {
120 const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD);
121 if (text == nullptr) {
122 // An oome has been thrown and is pending.
123 break;
124 }
125 output->print_cr("%s", text);
126 }
127 }
128
129 static void log(oop content, TRAPS) {
130 LogMessage(jfr,startup) msg;
131 objArrayOop lines = objArrayOop(content);
132 assert(lines != nullptr, "invariant");
133 assert(lines->is_array(), "must be array");
134 const int length = lines->length();
135 for (int i = 0; i < length; ++i) {
136 const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD);
137 if (text == nullptr) {
138 // An oome has been thrown and is pending.
139 break;
140 }
141 msg.info("%s", text);
142 }
143 }
144
145 static void handle_dcmd_result(outputStream* output,
146 const oop result,
147 const DCmdSource source,
148 TRAPS) {
149 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
150 assert(output != nullptr, "invariant");
151 ResourceMark rm(THREAD);
152 const bool startup = DCmd_Source_Internal == source;
153 if (HAS_PENDING_EXCEPTION) {
335
336 GrowableArray<DCmdArgumentInfo*>* JfrDCmd::argument_info_array() const {
337 static const char signature[] = "()[Ljdk/jfr/internal/dcmd/Argument;";
338 JavaThread* thread = JavaThread::current();
339 GrowableArray<DCmdArgumentInfo*>* const array = new GrowableArray<DCmdArgumentInfo*>(_num_arguments);
340 JavaValue result(T_OBJECT);
341 JfrJavaArguments getArgumentInfos(&result, javaClass(), "getArgumentInfos", signature, thread);
342 invoke(getArgumentInfos, thread);
343 if (thread->has_pending_exception()) {
344 // Most likely an OOME, but the DCmdFramework is not the best place to handle it.
345 // We handle it locally by clearing the exception and returning an array with dummy descriptors.
346 // This lets the MBean server initialization routine complete successfully,
347 // but this particular command will have no argument descriptors exposed.
348 // Hence we postpone, or delegate, handling of OOME's to code that is better suited.
349 log_debug(jfr, system)("Exception in DCmd getArgumentInfos");
350 thread->clear_pending_exception();
351 initialize_dummy_descriptors(array);
352 assert(array->length() == _num_arguments, "invariant");
353 return array;
354 }
355 objArrayOop arguments = objArrayOop(result.get_oop());
356 assert(arguments != nullptr, "invariant");
357 assert(arguments->is_array(), "must be array");
358 const int num_arguments = arguments->length();
359 assert(num_arguments == _num_arguments, "invariant");
360 prepare_dcmd_string_arena(thread);
361 for (int i = 0; i < num_arguments; ++i) {
362 DCmdArgumentInfo* const dai = create_info(arguments->obj_at(i), thread);
363 assert(dai != nullptr, "invariant");
364 array->append(dai);
365 }
366 return array;
367 }
368
369 GrowableArray<const char*>* JfrDCmd::argument_name_array() const {
370 GrowableArray<DCmdArgumentInfo*>* argument_infos = argument_info_array();
371 GrowableArray<const char*>* array = new GrowableArray<const char*>(argument_infos->length());
372 for (int i = 0; i < argument_infos->length(); i++) {
373 array->append(argument_infos->at(i)->name());
374 }
375 return array;
376 }
377
|
1 /*
2 * Copyright (c) 2012, 2026, 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 "classfile/javaClasses.inline.hpp"
26 #include "classfile/vmSymbols.hpp"
27 #include "jfr/dcmd/jfrDcmds.hpp"
28 #include "jfr/jfr.hpp"
29 #include "jfr/jni/jfrJavaSupport.hpp"
30 #include "jfr/recorder/jfrRecorder.hpp"
31 #include "jfr/recorder/service/jfrOptionSet.hpp"
32 #include "jfr/support/jfrThreadLocal.hpp"
33 #include "logging/log.hpp"
34 #include "logging/logConfiguration.hpp"
35 #include "logging/logMessage.hpp"
36 #include "memory/arena.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "oops/objArrayOop.inline.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "oops/oopCast.inline.hpp"
41 #include "oops/symbol.hpp"
42 #include "runtime/handles.inline.hpp"
43 #include "runtime/jniHandles.hpp"
44 #include "services/diagnosticArgument.hpp"
45 #include "services/diagnosticFramework.hpp"
46 #include "utilities/globalDefinitions.hpp"
47
48
49 bool register_jfr_dcmds() {
50 uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean;
51 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrCheckFlightRecordingDCmd>(full_export));
52 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrDumpFlightRecordingDCmd>(full_export));
53 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStartFlightRecordingDCmd>(full_export));
54 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStopFlightRecordingDCmd>(full_export));
55 // JFR.query Uncomment when developing new queries for the JFR.view command
56 // DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrQueryFlightRecordingDCmd>(full_export, /*hidden=*/true));
57 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrViewFlightRecordingDCmd>(full_export));
58 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrConfigureFlightRecorderDCmd>(full_export));
59 return true;
60 }
96 }
97
98 static void handle_pending_exception(outputStream* output, bool startup, oop throwable) {
99 assert(throwable != nullptr, "invariant");
100
101 oop msg = java_lang_Throwable::message(throwable);
102 if (msg == nullptr) {
103 return;
104 }
105 char* text = java_lang_String::as_utf8_string(msg);
106 if (text != nullptr) {
107 if (startup) {
108 log_error(jfr,startup)("%s", text);
109 } else {
110 output->print_cr("%s", text);
111 }
112 }
113 }
114
115 static void print_message(outputStream* output, oop content, TRAPS) {
116 assert(content != nullptr, "invariant");
117 refArrayOop lines = oop_cast<refArrayOop>(content);
118 const int length = lines->length();
119 for (int i = 0; i < length; ++i) {
120 const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD);
121 if (text == nullptr) {
122 // An oome has been thrown and is pending.
123 break;
124 }
125 output->print_cr("%s", text);
126 }
127 }
128
129 static void log(oop content, TRAPS) {
130 LogMessage(jfr,startup) msg;
131 assert(content != nullptr, "invariant");
132 refArrayOop lines = oop_cast<refArrayOop>(content);
133 const int length = lines->length();
134 for (int i = 0; i < length; ++i) {
135 const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD);
136 if (text == nullptr) {
137 // An oome has been thrown and is pending.
138 break;
139 }
140 msg.info("%s", text);
141 }
142 }
143
144 static void handle_dcmd_result(outputStream* output,
145 const oop result,
146 const DCmdSource source,
147 TRAPS) {
148 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
149 assert(output != nullptr, "invariant");
150 ResourceMark rm(THREAD);
151 const bool startup = DCmd_Source_Internal == source;
152 if (HAS_PENDING_EXCEPTION) {
334
335 GrowableArray<DCmdArgumentInfo*>* JfrDCmd::argument_info_array() const {
336 static const char signature[] = "()[Ljdk/jfr/internal/dcmd/Argument;";
337 JavaThread* thread = JavaThread::current();
338 GrowableArray<DCmdArgumentInfo*>* const array = new GrowableArray<DCmdArgumentInfo*>(_num_arguments);
339 JavaValue result(T_OBJECT);
340 JfrJavaArguments getArgumentInfos(&result, javaClass(), "getArgumentInfos", signature, thread);
341 invoke(getArgumentInfos, thread);
342 if (thread->has_pending_exception()) {
343 // Most likely an OOME, but the DCmdFramework is not the best place to handle it.
344 // We handle it locally by clearing the exception and returning an array with dummy descriptors.
345 // This lets the MBean server initialization routine complete successfully,
346 // but this particular command will have no argument descriptors exposed.
347 // Hence we postpone, or delegate, handling of OOME's to code that is better suited.
348 log_debug(jfr, system)("Exception in DCmd getArgumentInfos");
349 thread->clear_pending_exception();
350 initialize_dummy_descriptors(array);
351 assert(array->length() == _num_arguments, "invariant");
352 return array;
353 }
354 oop oop_args = result.get_oop();
355 assert(oop_args != nullptr, "invariant");
356 refArrayOop arguments = oop_cast<refArrayOop>(oop_args);
357 const int num_arguments = arguments->length();
358 assert(num_arguments == _num_arguments, "invariant");
359 prepare_dcmd_string_arena(thread);
360 for (int i = 0; i < num_arguments; ++i) {
361 DCmdArgumentInfo* const dai = create_info(arguments->obj_at(i), thread);
362 assert(dai != nullptr, "invariant");
363 array->append(dai);
364 }
365 return array;
366 }
367
368 GrowableArray<const char*>* JfrDCmd::argument_name_array() const {
369 GrowableArray<DCmdArgumentInfo*>* argument_infos = argument_info_array();
370 GrowableArray<const char*>* array = new GrowableArray<const char*>(argument_infos->length());
371 for (int i = 0; i < argument_infos->length(); i++) {
372 array->append(argument_infos->at(i)->name());
373 }
374 return array;
375 }
376
|