Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/share/logging/logConfiguration.cpp
64440 views
1
/*
2
* Copyright (c) 2015, 2022, 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
#include "precompiled.hpp"
25
#include "jvm.h"
26
#include "logging/log.hpp"
27
#include "logging/logAsyncWriter.hpp"
28
#include "logging/logConfiguration.hpp"
29
#include "logging/logDecorations.hpp"
30
#include "logging/logDecorators.hpp"
31
#include "logging/logDiagnosticCommand.hpp"
32
#include "logging/logFileOutput.hpp"
33
#include "logging/logOutput.hpp"
34
#include "logging/logSelectionList.hpp"
35
#include "logging/logStream.hpp"
36
#include "logging/logTagSet.hpp"
37
#include "memory/allocation.inline.hpp"
38
#include "memory/resourceArea.hpp"
39
#include "runtime/os.hpp"
40
#include "runtime/semaphore.hpp"
41
#include "utilities/globalDefinitions.hpp"
42
43
LogOutput** LogConfiguration::_outputs = NULL;
44
size_t LogConfiguration::_n_outputs = 0;
45
46
LogConfiguration::UpdateListenerFunction* LogConfiguration::_listener_callbacks = NULL;
47
size_t LogConfiguration::_n_listener_callbacks = 0;
48
49
// LogFileOutput is the default type of output, its type prefix should be used if no type was specified
50
static const char* implicit_output_prefix = LogFileOutput::Prefix;
51
52
// Stack object to take the lock for configuring the logging.
53
// Should only be held during the critical parts of the configuration
54
// (when calling configure_output or reading/modifying the outputs array).
55
// Thread must never block when holding this lock.
56
class ConfigurationLock : public StackObj {
57
private:
58
// Semaphore used as lock
59
static Semaphore _semaphore;
60
debug_only(static intx _locking_thread_id;)
61
public:
62
ConfigurationLock() {
63
_semaphore.wait();
64
debug_only(_locking_thread_id = os::current_thread_id());
65
}
66
~ConfigurationLock() {
67
debug_only(_locking_thread_id = -1);
68
_semaphore.signal();
69
}
70
debug_only(static bool current_thread_has_lock();)
71
};
72
73
Semaphore ConfigurationLock::_semaphore(1);
74
#ifdef ASSERT
75
intx ConfigurationLock::_locking_thread_id = -1;
76
bool ConfigurationLock::current_thread_has_lock() {
77
return _locking_thread_id == os::current_thread_id();
78
}
79
#endif
80
81
void LogConfiguration::post_initialize() {
82
// Reset the reconfigured status of all outputs
83
for (size_t i = 0; i < _n_outputs; i++) {
84
_outputs[i]->_reconfigured = false;
85
}
86
87
LogDiagnosticCommand::registerCommand();
88
Log(logging) log;
89
if (log.is_info()) {
90
log.info("Log configuration fully initialized.");
91
log_develop_info(logging)("Develop logging is available.");
92
93
LogStream info_stream(log.info());
94
describe_available(&info_stream);
95
96
LogStream debug_stream(log.debug());
97
LogTagSet::list_all_tagsets(&debug_stream);
98
99
ConfigurationLock cl;
100
describe_current_configuration(&info_stream);
101
}
102
}
103
104
void LogConfiguration::initialize(jlong vm_start_time) {
105
LogFileOutput::set_file_name_parameters(vm_start_time);
106
assert(_outputs == NULL, "Should not initialize _outputs before this function, initialize called twice?");
107
_outputs = NEW_C_HEAP_ARRAY(LogOutput*, 2, mtLogging);
108
_outputs[0] = &StdoutLog;
109
_outputs[1] = &StderrLog;
110
_n_outputs = 2;
111
}
112
113
void LogConfiguration::finalize() {
114
disable_outputs();
115
FREE_C_HEAP_ARRAY(LogOutput*, _outputs);
116
}
117
118
// Normalizes the given LogOutput name to type=name form.
119
// For example, foo, "foo", file="foo", will all be normalized to file=foo (no quotes, prefixed).
120
static bool normalize_output_name(const char* full_name, char* buffer, size_t len, outputStream* errstream) {
121
const char* start_quote = strchr(full_name, '"');
122
const char* equals = strchr(full_name, '=');
123
const bool quoted = start_quote != NULL;
124
const bool is_stdout_or_stderr = (strcmp(full_name, "stdout") == 0 || strcmp(full_name, "stderr") == 0);
125
126
// ignore equals sign within quotes
127
if (quoted && equals > start_quote) {
128
equals = NULL;
129
}
130
131
const char* prefix = "";
132
size_t prefix_len = 0;
133
const char* name = full_name;
134
if (equals != NULL) {
135
// split on equals sign
136
name = equals + 1;
137
prefix = full_name;
138
prefix_len = equals - full_name + 1;
139
} else if (!is_stdout_or_stderr) {
140
prefix = implicit_output_prefix;
141
prefix_len = strlen(prefix);
142
}
143
size_t name_len = strlen(name);
144
145
if (quoted) {
146
const char* end_quote = strchr(start_quote + 1, '"');
147
if (end_quote == NULL) {
148
errstream->print_cr("Output name has opening quote but is missing a terminating quote.");
149
return false;
150
}
151
if (start_quote != name || end_quote[1] != '\0') {
152
errstream->print_cr("Output name can not be partially quoted."
153
" Either surround the whole name with quotation marks,"
154
" or do not use quotation marks at all.");
155
return false;
156
}
157
// strip start and end quote
158
name++;
159
name_len -= 2;
160
}
161
162
int ret = jio_snprintf(buffer, len, "%.*s%.*s", prefix_len, prefix, name_len, name);
163
assert(ret > 0, "buffer issue");
164
return true;
165
}
166
167
size_t LogConfiguration::find_output(const char* name) {
168
for (size_t i = 0; i < _n_outputs; i++) {
169
if (strcmp(_outputs[i]->name(), name) == 0) {
170
return i;
171
}
172
}
173
return SIZE_MAX;
174
}
175
176
LogOutput* LogConfiguration::new_output(const char* name,
177
const char* options,
178
outputStream* errstream) {
179
LogOutput* output;
180
if (strncmp(name, LogFileOutput::Prefix, strlen(LogFileOutput::Prefix)) == 0) {
181
output = new LogFileOutput(name);
182
} else {
183
errstream->print_cr("Unsupported log output type: %s", name);
184
return NULL;
185
}
186
187
bool success = output->initialize(options, errstream);
188
if (!success) {
189
errstream->print_cr("Initialization of output '%s' using options '%s' failed.", name, options);
190
delete output;
191
return NULL;
192
}
193
return output;
194
}
195
196
size_t LogConfiguration::add_output(LogOutput* output) {
197
size_t idx = _n_outputs++;
198
_outputs = REALLOC_C_HEAP_ARRAY(LogOutput*, _outputs, _n_outputs, mtLogging);
199
_outputs[idx] = output;
200
return idx;
201
}
202
203
void LogConfiguration::delete_output(size_t idx) {
204
assert(idx > 1 && idx < _n_outputs,
205
"idx must be in range 1 < idx < _n_outputs, but idx = " SIZE_FORMAT
206
" and _n_outputs = " SIZE_FORMAT, idx, _n_outputs);
207
LogOutput* output = _outputs[idx];
208
// Swap places with the last output and shrink the array
209
_outputs[idx] = _outputs[--_n_outputs];
210
_outputs = REALLOC_C_HEAP_ARRAY(LogOutput*, _outputs, _n_outputs, mtLogging);
211
delete output;
212
}
213
214
// MT-SAFETY
215
//
216
// The ConfigurationLock guarantees that only one thread is performing reconfiguration. This function still needs
217
// to be MT-safe because logsites in other threads may be executing in parallel. Reconfiguration means unified
218
// logging allows users to dynamically change tags and decorators of a log output via DCMD(logDiagnosticCommand.hpp).
219
//
220
// A RCU-style synchronization 'wait_until_no_readers()' is used inside of 'ts->set_output_level(output, level)'
221
// if a setting has changed. It guarantees that all logs, either synchronous writes or enqueuing to the async buffer
222
// see the new tags and decorators. It's worth noting that the synchronization occurs even if the level does not change.
223
//
224
// LogDecorator is a set of decorators represented in a uint. ts->update_decorators(decorators) is a union of the
225
// current decorators and new_decorators. It's safe to do output->set_decorators(decorators) because new_decorators
226
// is a subset of relevant tagsets decorators. After updating output's decorators, it is still safe to shrink all
227
// decorators of tagsets.
228
//
229
void LogConfiguration::configure_output(size_t idx, const LogSelectionList& selections, const LogDecorators& decorators) {
230
assert(ConfigurationLock::current_thread_has_lock(), "Must hold configuration lock to call this function.");
231
assert(idx < _n_outputs, "Invalid index, idx = " SIZE_FORMAT " and _n_outputs = " SIZE_FORMAT, idx, _n_outputs);
232
LogOutput* output = _outputs[idx];
233
234
output->_reconfigured = true;
235
236
size_t on_level[LogLevel::Count] = {0};
237
238
bool enabled = false;
239
for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
240
LogLevelType level = selections.level_for(*ts);
241
242
// Ignore tagsets that do not, and will not log on the output
243
if (!ts->has_output(output) && (level == LogLevel::NotMentioned || level == LogLevel::Off)) {
244
on_level[LogLevel::Off]++;
245
continue;
246
}
247
248
// Update decorators before adding/updating output level,
249
// so that the tagset will have the necessary decorators when requiring them.
250
if (level != LogLevel::Off) {
251
ts->update_decorators(decorators);
252
}
253
254
// Set the new level, if it changed
255
if (level != LogLevel::NotMentioned) {
256
ts->set_output_level(output, level);
257
} else {
258
// Look up the previously set level for this output on this tagset
259
level = ts->level_for(output);
260
}
261
262
if (level != LogLevel::Off) {
263
// Keep track of whether or not the output is ever used by some tagset
264
enabled = true;
265
}
266
267
// Track of the number of tag sets on each level
268
on_level[level]++;
269
}
270
271
// For async logging we have to ensure that all enqueued messages, which may refer to previous decorators,
272
// or a soon-to-be-deleted output, are written out first. The flush() call ensures this.
273
AsyncLogWriter::flush();
274
275
// It is now safe to set the new decorators for the actual output
276
output->set_decorators(decorators);
277
278
// Update the decorators on all tagsets to get rid of unused decorators
279
for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
280
ts->update_decorators();
281
}
282
283
if (!enabled && idx > 1) {
284
// Output is unused and should be removed, unless it is stdout/stderr (idx < 2)
285
delete_output(idx);
286
return;
287
}
288
289
output->update_config_string(on_level);
290
assert(strlen(output->config_string()) > 0, "should always have a config description");
291
}
292
293
void LogConfiguration::disable_outputs() {
294
size_t idx = _n_outputs;
295
296
// Remove all outputs from all tagsets.
297
for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
298
ts->disable_outputs();
299
}
300
301
// Handle 'jcmd VM.log disable' and JVM termination.
302
// ts->disable_outputs() above has disabled all output_lists with RCU synchronization.
303
// Therefore, no new logging message can enter the async buffer for the time being.
304
// flush out all pending messages before LogOutput instances die.
305
AsyncLogWriter::flush();
306
307
while (idx > 0) {
308
LogOutput* out = _outputs[--idx];
309
// Delete the output unless stdout or stderr (idx 0 or 1)
310
if (idx > 1) {
311
delete_output(idx);
312
} else {
313
out->set_config_string("all=off");
314
}
315
}
316
}
317
318
void LogConfiguration::disable_logging() {
319
ConfigurationLock cl;
320
disable_outputs();
321
// Update the decorators on all tagsets to get rid of unused decorators
322
for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
323
ts->update_decorators();
324
}
325
notify_update_listeners();
326
}
327
328
void LogConfiguration::configure_stdout(LogLevelType level, int exact_match, ...) {
329
size_t i;
330
va_list ap;
331
LogTagType tags[LogTag::MaxTags];
332
va_start(ap, exact_match);
333
for (i = 0; i < LogTag::MaxTags; i++) {
334
LogTagType tag = static_cast<LogTagType>(va_arg(ap, int));
335
tags[i] = tag;
336
if (tag == LogTag::__NO_TAG) {
337
assert(i > 0, "Must specify at least one tag!");
338
break;
339
}
340
}
341
assert(i < LogTag::MaxTags || static_cast<LogTagType>(va_arg(ap, int)) == LogTag::__NO_TAG,
342
"Too many tags specified! Can only have up to " SIZE_FORMAT " tags in a tag set.", LogTag::MaxTags);
343
va_end(ap);
344
345
LogSelection selection(tags, !exact_match, level);
346
assert(selection.tag_sets_selected() > 0,
347
"configure_stdout() called with invalid/non-existing log selection");
348
LogSelectionList list(selection);
349
350
// Apply configuration to stdout (output #0), with the same decorators as before.
351
ConfigurationLock cl;
352
configure_output(0, list, _outputs[0]->decorators());
353
notify_update_listeners();
354
}
355
356
bool LogConfiguration::parse_command_line_arguments(const char* opts) {
357
char* copy = os::strdup_check_oom(opts, mtLogging);
358
359
// Split the option string to its colon separated components.
360
char* str = copy;
361
char* substrings[4] = {0};
362
for (int i = 0 ; i < 4; i++) {
363
substrings[i] = str;
364
365
// Find the next colon or quote
366
char* next = strpbrk(str, ":\"");
367
#ifdef _WINDOWS
368
// Skip over Windows paths such as "C:\..." and "C:/...".
369
// Handles both "C:\..." and "file=C:\...".
370
if (next != NULL && next[0] == ':' && (next[1] == '\\' || next[1] == '/')) {
371
if (next == str + 1 || (strncmp(str, "file=", 5) == 0)) {
372
next = strpbrk(next + 1, ":\"");
373
}
374
}
375
#endif
376
while (next != NULL && *next == '"') {
377
char* end_quote = strchr(next + 1, '"');
378
if (end_quote == NULL) {
379
log_error(logging)("Missing terminating quote in -Xlog option '%s'", str);
380
os::free(copy);
381
return false;
382
}
383
// Keep searching after the quoted substring
384
next = strpbrk(end_quote + 1, ":\"");
385
}
386
387
if (next != NULL) {
388
*next = '\0';
389
str = next + 1;
390
} else {
391
str = NULL;
392
break;
393
}
394
}
395
396
if (str != NULL) {
397
log_warning(logging)("Ignoring excess -Xlog options: \"%s\"", str);
398
}
399
400
// Parse and apply the separated configuration options
401
char* what = substrings[0];
402
char* output = substrings[1];
403
char* decorators = substrings[2];
404
char* output_options = substrings[3];
405
char errbuf[512];
406
stringStream ss(errbuf, sizeof(errbuf));
407
bool success = parse_log_arguments(output, what, decorators, output_options, &ss);
408
409
if (ss.size() > 0) {
410
// If it failed, log the error. If it didn't fail, but something was written
411
// to the stream, log it as a warning.
412
LogLevelType level = success ? LogLevel::Warning : LogLevel::Error;
413
414
Log(logging) log;
415
char* start = errbuf;
416
char* end = strchr(start, '\n');
417
assert(end != NULL, "line must end with newline '%s'", start);
418
do {
419
assert(start < errbuf + sizeof(errbuf) &&
420
end < errbuf + sizeof(errbuf),
421
"buffer overflow");
422
*end = '\0';
423
log.write(level, "%s", start);
424
start = end + 1;
425
end = strchr(start, '\n');
426
assert(end != NULL || *start == '\0', "line must end with newline '%s'", start);
427
} while (end != NULL);
428
}
429
430
os::free(copy);
431
return success;
432
}
433
434
bool LogConfiguration::parse_log_arguments(const char* outputstr,
435
const char* selectionstr,
436
const char* decoratorstr,
437
const char* output_options,
438
outputStream* errstream) {
439
assert(errstream != NULL, "errstream can not be NULL");
440
if (outputstr == NULL || strlen(outputstr) == 0) {
441
outputstr = "stdout";
442
}
443
444
LogSelectionList selections;
445
if (!selections.parse(selectionstr, errstream)) {
446
return false;
447
}
448
449
LogDecorators decorators;
450
if (!decorators.parse(decoratorstr, errstream)) {
451
return false;
452
}
453
454
ConfigurationLock cl;
455
size_t idx;
456
bool added = false;
457
if (outputstr[0] == '#') { // Output specified using index
458
int ret = sscanf(outputstr + 1, SIZE_FORMAT, &idx);
459
if (ret != 1 || idx >= _n_outputs) {
460
errstream->print_cr("Invalid output index '%s'", outputstr);
461
return false;
462
}
463
} else { // Output specified using name
464
// Normalize the name, stripping quotes and ensures it includes type prefix
465
size_t len = strlen(outputstr) + strlen(implicit_output_prefix) + 1;
466
char* normalized = NEW_C_HEAP_ARRAY(char, len, mtLogging);
467
if (!normalize_output_name(outputstr, normalized, len, errstream)) {
468
return false;
469
}
470
471
idx = find_output(normalized);
472
if (idx == SIZE_MAX) {
473
// Attempt to create and add the output
474
LogOutput* output = new_output(normalized, output_options, errstream);
475
if (output != NULL) {
476
idx = add_output(output);
477
added = true;
478
}
479
}
480
481
FREE_C_HEAP_ARRAY(char, normalized);
482
if (idx == SIZE_MAX) {
483
return false;
484
}
485
}
486
if (!added && output_options != NULL && strlen(output_options) > 0) {
487
errstream->print_cr("Output options for existing outputs are ignored.");
488
}
489
configure_output(idx, selections, decorators);
490
notify_update_listeners();
491
selections.verify_selections(errstream);
492
return true;
493
}
494
495
void LogConfiguration::describe_available(outputStream* out) {
496
out->print("Available log levels:");
497
for (size_t i = 0; i < LogLevel::Count; i++) {
498
out->print("%s %s", (i == 0 ? "" : ","), LogLevel::name(static_cast<LogLevelType>(i)));
499
}
500
out->cr();
501
502
out->print("Available log decorators:");
503
for (size_t i = 0; i < LogDecorators::Count; i++) {
504
LogDecorators::Decorator d = static_cast<LogDecorators::Decorator>(i);
505
out->print("%s %s (%s)", (i == 0 ? "" : ","), LogDecorators::name(d), LogDecorators::abbreviation(d));
506
}
507
out->cr();
508
509
out->print("Available log tags:");
510
LogTag::list_tags(out);
511
512
LogTagSet::describe_tagsets(out);
513
}
514
515
void LogConfiguration::describe_current_configuration(outputStream* out) {
516
out->print_cr("Log output configuration:");
517
for (size_t i = 0; i < _n_outputs; i++) {
518
out->print(" #" SIZE_FORMAT ": ", i);
519
_outputs[i]->describe(out);
520
if (_outputs[i]->is_reconfigured()) {
521
out->print(" (reconfigured)");
522
}
523
out->cr();
524
}
525
}
526
527
void LogConfiguration::describe(outputStream* out) {
528
describe_available(out);
529
ConfigurationLock cl;
530
describe_current_configuration(out);
531
}
532
533
void LogConfiguration::print_command_line_help(outputStream* out) {
534
out->print_cr("-Xlog Usage: -Xlog[:[selections][:[output][:[decorators][:output-options]]]]");
535
out->print_cr("\t where 'selections' are combinations of tags and levels of the form tag1[+tag2...][*][=level][,...]");
536
out->print_cr("\t NOTE: Unless wildcard (*) is specified, only log messages tagged with exactly the tags specified will be matched.");
537
out->cr();
538
539
out->print_cr("Available log levels:");
540
for (size_t i = 0; i < LogLevel::Count; i++) {
541
out->print("%s %s", (i == 0 ? "" : ","), LogLevel::name(static_cast<LogLevelType>(i)));
542
}
543
out->cr();
544
out->cr();
545
546
out->print_cr("Available log decorators: ");
547
for (size_t i = 0; i < LogDecorators::Count; i++) {
548
LogDecorators::Decorator d = static_cast<LogDecorators::Decorator>(i);
549
out->print("%s %s (%s)", (i == 0 ? "" : ","), LogDecorators::name(d), LogDecorators::abbreviation(d));
550
}
551
out->cr();
552
out->print_cr(" Decorators can also be specified as 'none' for no decoration.");
553
out->cr();
554
555
out->print_cr("Available log tags:");
556
LogTag::list_tags(out);
557
out->print_cr(" Specifying 'all' instead of a tag combination matches all tag combinations.");
558
out->cr();
559
560
LogTagSet::describe_tagsets(out);
561
562
out->print_cr("\nAvailable log outputs:");
563
out->print_cr(" stdout/stderr");
564
out->print_cr(" file=<filename>");
565
out->print_cr(" If the filename contains %%p and/or %%t, they will expand to the JVM's PID and startup timestamp, respectively.");
566
out->print_cr(" Additional output-options for file outputs:");
567
out->print_cr(" filesize=.. - Target byte size for log rotation (supports K/M/G suffix)."
568
" If set to 0, log rotation will not trigger automatically,"
569
" but can be performed manually (see the VM.log DCMD).");
570
out->print_cr(" filecount=.. - Number of files to keep in rotation (not counting the active file)."
571
" If set to 0, log rotation is disabled."
572
" This will cause existing log files to be overwritten.");
573
out->cr();
574
out->print_cr("\nAsynchronous logging (off by default):");
575
out->print_cr(" -Xlog:async");
576
out->print_cr(" All log messages are written to an intermediate buffer first and will then be flushed"
577
" to the corresponding log outputs by a standalone thread. Write operations at logsites are"
578
" guaranteed non-blocking.");
579
out->cr();
580
581
out->print_cr("Some examples:");
582
out->print_cr(" -Xlog");
583
out->print_cr("\t Log all messages up to 'info' level to stdout with 'uptime', 'levels' and 'tags' decorations.");
584
out->print_cr("\t (Equivalent to -Xlog:all=info:stdout:uptime,levels,tags).");
585
out->cr();
586
587
out->print_cr(" -Xlog:gc");
588
out->print_cr("\t Log messages tagged with 'gc' tag up to 'info' level to stdout, with default decorations.");
589
out->cr();
590
591
out->print_cr(" -Xlog:gc,safepoint");
592
out->print_cr("\t Log messages tagged either with 'gc' or 'safepoint' tags, both up to 'info' level, to stdout, with default decorations.");
593
out->print_cr("\t (Messages tagged with both 'gc' and 'safepoint' will not be logged.)");
594
out->cr();
595
596
out->print_cr(" -Xlog:gc+ref=debug");
597
out->print_cr("\t Log messages tagged with both 'gc' and 'ref' tags, up to 'debug' level, to stdout, with default decorations.");
598
out->print_cr("\t (Messages tagged only with one of the two tags will not be logged.)");
599
out->cr();
600
601
out->print_cr(" -Xlog:gc=debug:file=gc.txt:none");
602
out->print_cr("\t Log messages tagged with 'gc' tag up to 'debug' level to file 'gc.txt' with no decorations.");
603
out->cr();
604
605
out->print_cr(" -Xlog:gc=trace:file=gctrace.txt:uptimemillis,pid:filecount=5,filesize=1m");
606
out->print_cr("\t Log messages tagged with 'gc' tag up to 'trace' level to a rotating fileset of 5 files of size 1MB,");
607
out->print_cr("\t using the base name 'gctrace.txt', with 'uptimemillis' and 'pid' decorations.");
608
out->cr();
609
610
out->print_cr(" -Xlog:gc::uptime,tid");
611
out->print_cr("\t Log messages tagged with 'gc' tag up to 'info' level to output 'stdout', using 'uptime' and 'tid' decorations.");
612
out->cr();
613
614
out->print_cr(" -Xlog:gc*=info,safepoint*=off");
615
out->print_cr("\t Log messages tagged with at least 'gc' up to 'info' level, but turn off logging of messages tagged with 'safepoint'.");
616
out->print_cr("\t (Messages tagged with both 'gc' and 'safepoint' will not be logged.)");
617
out->cr();
618
619
out->print_cr(" -Xlog:disable -Xlog:safepoint=trace:safepointtrace.txt");
620
out->print_cr("\t Turn off all logging, including warnings and errors,");
621
out->print_cr("\t and then enable messages tagged with 'safepoint' up to 'trace' level to file 'safepointtrace.txt'.");
622
623
out->print_cr(" -Xlog:async -Xlog:gc=debug:file=gc.log -Xlog:safepoint=trace");
624
out->print_cr("\t Write logs asynchronously. Enable messages tagged with 'safepoint' up to 'trace' level to stdout ");
625
out->print_cr("\t and messages tagged with 'gc' up to 'debug' level to file 'gc.log'.");
626
}
627
628
void LogConfiguration::rotate_all_outputs() {
629
// Start from index 2 since neither stdout nor stderr can be rotated.
630
for (size_t idx = 2; idx < _n_outputs; idx++) {
631
_outputs[idx]->force_rotate();
632
}
633
}
634
635
void LogConfiguration::register_update_listener(UpdateListenerFunction cb) {
636
assert(cb != NULL, "Should not register NULL as listener");
637
ConfigurationLock cl;
638
size_t idx = _n_listener_callbacks++;
639
_listener_callbacks = REALLOC_C_HEAP_ARRAY(UpdateListenerFunction,
640
_listener_callbacks,
641
_n_listener_callbacks,
642
mtLogging);
643
_listener_callbacks[idx] = cb;
644
}
645
646
void LogConfiguration::notify_update_listeners() {
647
assert(ConfigurationLock::current_thread_has_lock(), "notify_update_listeners must be called in ConfigurationLock scope (lock held)");
648
for (size_t i = 0; i < _n_listener_callbacks; i++) {
649
_listener_callbacks[i]();
650
}
651
}
652
653
bool LogConfiguration::_async_mode = false;
654
655