|
30 | 30 | #include "jfr/jni/jfrJavaSupport.hpp"
|
31 | 31 | #include "jfr/recorder/jfrRecorder.hpp"
|
32 | 32 | #include "jfr/recorder/service/jfrOptionSet.hpp"
|
| 33 | +#include "logging/log.hpp" |
| 34 | +#include "logging/logConfiguration.hpp" |
| 35 | +#include "logging/logMessage.hpp" |
33 | 36 | #include "memory/resourceArea.hpp"
|
| 37 | +#include "oops/objArrayOop.inline.hpp" |
34 | 38 | #include "oops/oop.inline.hpp"
|
35 | 39 | #include "oops/symbol.hpp"
|
36 | 40 | #include "runtime/handles.inline.hpp"
|
@@ -128,43 +132,86 @@ static bool invalid_state(outputStream* out, TRAPS) {
|
128 | 132 | return is_disabled(out) || !is_module_available(out, THREAD);
|
129 | 133 | }
|
130 | 134 |
|
131 |
| -static void print_pending_exception(outputStream* output, oop throwable) { |
| 135 | +static void handle_pending_exception(outputStream* output, bool startup, oop throwable) { |
132 | 136 | assert(throwable != NULL, "invariant");
|
133 | 137 |
|
134 | 138 | oop msg = java_lang_Throwable::message(throwable);
|
135 |
| - |
136 |
| - if (msg != NULL) { |
137 |
| - char* text = java_lang_String::as_utf8_string(msg); |
138 |
| - output->print_raw_cr(text); |
| 139 | + if (msg == NULL) { |
| 140 | + return; |
| 141 | + } |
| 142 | + char* text = java_lang_String::as_utf8_string(msg); |
| 143 | + if (text != NULL) { |
| 144 | + if (startup) { |
| 145 | + log_error(jfr,startup)("%s", text); |
| 146 | + } else { |
| 147 | + output->print_cr("%s", text); |
| 148 | + } |
139 | 149 | }
|
140 | 150 | }
|
141 | 151 |
|
142 |
| -static void print_message(outputStream* output, const char* message) { |
143 |
| - if (message != NULL) { |
144 |
| - output->print_raw(message); |
| 152 | +static void print_message(outputStream* output, oop content, TRAPS) { |
| 153 | + objArrayOop lines = objArrayOop(content); |
| 154 | + assert(lines != NULL, "invariant"); |
| 155 | + assert(lines->is_array(), "must be array"); |
| 156 | + const int length = lines->length(); |
| 157 | + for (int i = 0; i < length; ++i) { |
| 158 | + const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD); |
| 159 | + if (text == NULL) { |
| 160 | + // An oome has been thrown and is pending. |
| 161 | + break; |
| 162 | + } |
| 163 | + output->print_cr("%s", text); |
145 | 164 | }
|
146 | 165 | }
|
147 | 166 |
|
| 167 | +static void log(oop content, TRAPS) { |
| 168 | + LogMessage(jfr,startup) msg; |
| 169 | + objArrayOop lines = objArrayOop(content); |
| 170 | + assert(lines != NULL, "invariant"); |
| 171 | + assert(lines->is_array(), "must be array"); |
| 172 | + const int length = lines->length(); |
| 173 | + for (int i = 0; i < length; ++i) { |
| 174 | + const char* text = JfrJavaSupport::c_str(lines->obj_at(i), THREAD); |
| 175 | + if (text == NULL) { |
| 176 | + // An oome has been thrown and is pending. |
| 177 | + break; |
| 178 | + } |
| 179 | + msg.info("%s", text); |
| 180 | + } |
| 181 | +} |
| 182 | + |
148 | 183 | static void handle_dcmd_result(outputStream* output,
|
149 | 184 | const oop result,
|
150 | 185 | const DCmdSource source,
|
151 | 186 | TRAPS) {
|
152 | 187 | DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
|
153 | 188 | assert(output != NULL, "invariant");
|
| 189 | + const bool startup = DCmd_Source_Internal == source; |
154 | 190 | if (HAS_PENDING_EXCEPTION) {
|
155 |
| - print_pending_exception(output, PENDING_EXCEPTION); |
| 191 | + handle_pending_exception(output, startup, PENDING_EXCEPTION); |
156 | 192 | // Don't clear excption on startup, JVM should fail initialization.
|
157 |
| - if (DCmd_Source_Internal != source) { |
| 193 | + if (!startup) { |
158 | 194 | CLEAR_PENDING_EXCEPTION;
|
159 | 195 | }
|
160 | 196 | return;
|
161 | 197 | }
|
162 | 198 |
|
163 | 199 | assert(!HAS_PENDING_EXCEPTION, "invariant");
|
164 | 200 |
|
165 |
| - if (result != NULL) { |
166 |
| - const char* result_chars = java_lang_String::as_utf8_string(result); |
167 |
| - print_message(output, result_chars); |
| 201 | + if (startup) { |
| 202 | + if (log_is_enabled(Warning, jfr, startup)) { |
| 203 | + // if warning is set, assume user hasn't configured log level |
| 204 | + // Log to Info and reset to Warning. This way user can disable |
| 205 | + // default output by setting -Xlog:jfr+startup=error/off |
| 206 | + LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(jfr, startup)); |
| 207 | + log(result, THREAD); |
| 208 | + LogConfiguration::configure_stdout(LogLevel::Warning, true, LOG_TAGS(jfr, startup)); |
| 209 | + } else { |
| 210 | + log(result, THREAD); |
| 211 | + } |
| 212 | + } else { |
| 213 | + // Print output for jcmd or MXBean |
| 214 | + print_message(output, result, THREAD); |
168 | 215 | }
|
169 | 216 | }
|
170 | 217 |
|
@@ -261,7 +308,7 @@ void JfrDumpFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
|
261 | 308 |
|
262 | 309 | static const char klass[] = "jdk/jfr/internal/dcmd/DCmdDump";
|
263 | 310 | static const char method[] = "execute";
|
264 |
| - static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;"; |
| 311 | + static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)[Ljava/lang/String;"; |
265 | 312 |
|
266 | 313 | JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
|
267 | 314 | execute_args.set_receiver(h_dcmd_instance);
|
@@ -327,7 +374,7 @@ void JfrCheckFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
|
327 | 374 |
|
328 | 375 | static const char klass[] = "jdk/jfr/internal/dcmd/DCmdCheck";
|
329 | 376 | static const char method[] = "execute";
|
330 |
| - static const char signature[] = "(Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;"; |
| 377 | + static const char signature[] = "(Ljava/lang/String;Ljava/lang/Boolean;)[Ljava/lang/String;"; |
331 | 378 |
|
332 | 379 | JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
|
333 | 380 | execute_args.set_receiver(h_dcmd_instance);
|
@@ -471,7 +518,7 @@ void JfrStartFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
|
471 | 518 | static const char method[] = "execute";
|
472 | 519 | static const char signature[] = "(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/Long;"
|
473 | 520 | "Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/String;"
|
474 |
| - "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/lang/String;"; |
| 521 | + "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/Boolean;)[Ljava/lang/String;"; |
475 | 522 |
|
476 | 523 | JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
|
477 | 524 | execute_args.set_receiver(h_dcmd_instance);
|
@@ -541,7 +588,7 @@ void JfrStopFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
|
541 | 588 |
|
542 | 589 | static const char klass[] = "jdk/jfr/internal/dcmd/DCmdStop";
|
543 | 590 | static const char method[] = "execute";
|
544 |
| - static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"; |
| 591 | + static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"; |
545 | 592 |
|
546 | 593 | JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
|
547 | 594 | execute_args.set_receiver(h_dcmd_instance);
|
@@ -654,7 +701,7 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) {
|
654 | 701 | static const char method[] = "execute";
|
655 | 702 | static const char signature[] = "(ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Integer;"
|
656 | 703 | "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;"
|
657 |
| - "Ljava/lang/Long;Ljava/lang/Boolean;)Ljava/lang/String;"; |
| 704 | + "Ljava/lang/Long;Ljava/lang/Boolean;)[Ljava/lang/String;"; |
658 | 705 |
|
659 | 706 | JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
|
660 | 707 | execute_args.set_receiver(h_dcmd_instance);
|
|
0 commit comments