< prev index next >

src/hotspot/share/jfr/dcmd/jfrDcmds.cpp

Print this page

  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 
< prev index next >