Skip to content

Commit 64b37c6

Browse files
author
duke
committedAug 27, 2021
Automatic merge of jdk:master into master
2 parents 22f9246 + b16a04e commit 64b37c6

File tree

6 files changed

+168
-14
lines changed

6 files changed

+168
-14
lines changed
 

‎src/hotspot/share/logging/logConfiguration.cpp

+14-6
Original file line numberDiff line numberDiff line change
@@ -564,12 +564,20 @@ void LogConfiguration::print_command_line_help(outputStream* out) {
564564
out->print_cr(" file=<filename>");
565565
out->print_cr(" If the filename contains %%p and/or %%t, they will expand to the JVM's PID and startup timestamp, respectively.");
566566
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.");
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->print_cr(" foldmultilines=.. - If set to true, a log event that consists of multiple lines"
574+
" will be folded into a single line by replacing newline characters"
575+
" with the sequence '\\' and 'n' in the output."
576+
" Existing single backslash characters will also be replaced"
577+
" with a sequence of two backslashes so that the conversion can be reversed."
578+
" This option is safe to use with UTF-8 character encodings,"
579+
" but other encodings may not work.");
580+
573581
out->cr();
574582
out->print_cr("\nAsynchronous logging (off by default):");
575583
out->print_cr(" -Xlog:async");

‎src/hotspot/share/logging/logFileOutput.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,17 @@ bool LogFileOutput::parse_options(const char* options, outputStream* errstream)
195195
char* value_str = equals_pos + 1;
196196
*equals_pos = '\0';
197197

198-
if (strcmp(FileCountOptionKey, key) == 0) {
198+
if (strcmp(FoldMultilinesOptionKey, key) == 0) {
199+
if (strcmp(value_str, "true") == 0) {
200+
_fold_multilines = true;
201+
} else if (strcmp(value_str, "false") == 0) {
202+
_fold_multilines = false;
203+
} else {
204+
errstream->print_cr("Invalid option '%s' for %s.", value_str, FoldMultilinesOptionKey);
205+
success = false;
206+
break;
207+
}
208+
} else if (strcmp(FileCountOptionKey, key) == 0) {
199209
size_t value = parse_value(value_str);
200210
if (value > MaxRotationFileCount) {
201211
errstream->print_cr("Invalid option: %s must be in range [0, %u]",

‎src/hotspot/share/logging/logFileStreamOutput.cpp

+29-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,8 @@
3030
#include "memory/allocation.inline.hpp"
3131
#include "utilities/defaultStream.hpp"
3232

33+
const char* const LogFileStreamOutput::FoldMultilinesOptionKey = "foldmultilines";
34+
3335
static bool initialized;
3436
static union {
3537
char stdoutmem[sizeof(LogStdoutOutput)];
@@ -117,6 +119,30 @@ bool LogFileStreamOutput::flush() {
117119
total += result; \
118120
}
119121

122+
int LogFileStreamOutput::write_internal(const char* msg) {
123+
int written = 0;
124+
if (!_fold_multilines) {
125+
WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s\n", msg), written);
126+
} else {
127+
char *dupstr = os::strdup_check_oom(msg, mtLogging);
128+
char *cur = dupstr;
129+
char *next;
130+
do {
131+
next = strpbrk(cur, "\n\\");
132+
if (next == NULL) {
133+
WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s\n", cur), written);
134+
} else {
135+
const char *found = (*next == '\n') ? "\\n" : "\\\\";
136+
*next = '\0';
137+
WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s%s", cur, found), written);
138+
cur = next + 1;
139+
}
140+
} while (next != NULL);
141+
os::free(dupstr);
142+
}
143+
return written;
144+
}
145+
120146
int LogFileStreamOutput::write(const LogDecorations& decorations, const char* msg) {
121147
const bool use_decorations = !_decorators.is_empty();
122148

@@ -126,7 +152,7 @@ int LogFileStreamOutput::write(const LogDecorations& decorations, const char* ms
126152
WRITE_LOG_WITH_RESULT_CHECK(write_decorations(decorations), written);
127153
WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, " "), written);
128154
}
129-
WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s\n", msg), written);
155+
written += write_internal(msg);
130156

131157
return flush() ? written : -1;
132158
}
@@ -141,7 +167,7 @@ int LogFileStreamOutput::write(LogMessageBuffer::Iterator msg_iterator) {
141167
WRITE_LOG_WITH_RESULT_CHECK(write_decorations(msg_iterator.decorations()), written);
142168
WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, " "), written);
143169
}
144-
WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s\n", msg_iterator.message()), written);
170+
written += write_internal(msg_iterator.message());
145171
}
146172

147173
return flush() ? written : -1;

‎src/hotspot/share/logging/logFileStreamOutput.hpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
2626

2727
#include "logging/logDecorators.hpp"
2828
#include "logging/logOutput.hpp"
29+
#include "runtime/os.hpp"
2930
#include "utilities/globalDefinitions.hpp"
3031

3132
class LogDecorations;
@@ -42,11 +43,15 @@ static LogFileStreamInitializer log_stream_initializer;
4243
class LogFileStreamOutput : public LogOutput {
4344
private:
4445
bool _write_error_is_shown;
46+
47+
int write_internal(const char* msg);
4548
protected:
49+
static const char* const FoldMultilinesOptionKey;
4650
FILE* _stream;
4751
size_t _decorator_padding[LogDecorators::Count];
52+
bool _fold_multilines;
4853

49-
LogFileStreamOutput(FILE *stream) : _write_error_is_shown(false), _stream(stream) {
54+
LogFileStreamOutput(FILE *stream) : _write_error_is_shown(false), _stream(stream), _fold_multilines(false) {
5055
for (size_t i = 0; i < LogDecorators::Count; i++) {
5156
_decorator_padding[i] = 0;
5257
}

‎src/java.base/share/man/java.1

+12-2
Original file line numberDiff line numberDiff line change
@@ -4418,8 +4418,18 @@ selected.
44184418
\f[I]output\-options\f[R] is
44194419
.RS
44204420
.PP
4421-
\f[CB]filecount=\f[R]\f[I]file\-count\f[R] \f[CB]filesize=\f[R]\f[I]file size
4422-
with optional K, M or G suffix\f[R]
4421+
\f[CB]filecount=\f[R]\f[I]file\-count\f[R] \f[CB]filesize=\f[R]\f[I]<file size
4422+
with optional K, M or G suffix>\f[R] \f[CB]foldmultilines=\f[R]\f[I]<true|false>\f[R]
4423+
.RE
4424+
.PP
4425+
When \f[I]foldmultilines\f[R] is true, a log event that consists of
4426+
multiple lines will be folded into a single line by replacing newline characters
4427+
with the sequence '\\' and 'n' in the output.
4428+
Existing single backslash characters will also be replaced with a sequence of
4429+
two backslashes so that the conversion can be reversed.
4430+
This option is safe to use with UTF-8 character encodings, but other encodings may not work.
4431+
For example, it may incorrectly convert multi-byte sequences in Shift JIS and BIG5.
4432+
This option is available only for file outputs.
44234433
.RE
44244434
.RE
44254435
.SS Default Configuration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2021 NTT DATA.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
/*
26+
* @test
27+
* @bug 8271186
28+
* @library /test/lib
29+
* @run driver FoldMultilinesTest
30+
*/
31+
32+
import java.nio.file.Files;
33+
import java.nio.file.Path;
34+
import jdk.test.lib.process.OutputAnalyzer;
35+
import jdk.test.lib.process.ProcessTools;
36+
37+
public class FoldMultilinesTest {
38+
39+
private static Path EXCEPTION_LOG_FILE = Path.of("exceptions.log");
40+
private static String XLOG_BASE = "-Xlog:exceptions=info:file=" + EXCEPTION_LOG_FILE.toString();
41+
42+
private static void analyzeFoldMultilinesOn(ProcessBuilder pb) throws Exception {
43+
OutputAnalyzer output = new OutputAnalyzer(pb.start());
44+
output.shouldHaveExitValue(0);
45+
46+
String logs = Files.readString(EXCEPTION_LOG_FILE);
47+
if (!logs.contains("line 1\\nline 2\\\\nstring")) {
48+
throw new RuntimeException("foldmultilines=true did not work.");
49+
}
50+
}
51+
52+
private static void analyzeFoldMultilinesOff(ProcessBuilder pb) throws Exception {
53+
OutputAnalyzer output = new OutputAnalyzer(pb.start());
54+
output.shouldHaveExitValue(0);
55+
56+
String logs = Files.readString(EXCEPTION_LOG_FILE);
57+
if (!logs.contains("line 1" + System.lineSeparator() + "line 2\\nstring")) {
58+
throw new RuntimeException("foldmultilines=false did not work.");
59+
}
60+
}
61+
62+
private static void analyzeFoldMultilinesInvalid(ProcessBuilder pb) throws Exception {
63+
OutputAnalyzer output = new OutputAnalyzer(pb.start());
64+
output.shouldContain("Invalid option 'invalid' for foldmultilines.");
65+
output.shouldNotHaveExitValue(0);
66+
}
67+
68+
public static void main(String[] args) throws Exception {
69+
String Xlog;
70+
ProcessBuilder pb;
71+
72+
Xlog = XLOG_BASE + "::foldmultilines=true";
73+
pb = ProcessTools.createJavaProcessBuilder(Xlog, InternalClass.class.getName());
74+
analyzeFoldMultilinesOn(pb);
75+
76+
Xlog = XLOG_BASE + "::foldmultilines=false";
77+
pb = ProcessTools.createJavaProcessBuilder(Xlog, InternalClass.class.getName());
78+
analyzeFoldMultilinesOff(pb);
79+
80+
Xlog = XLOG_BASE + "::foldmultilines=invalid";
81+
pb = ProcessTools.createJavaProcessBuilder(Xlog, InternalClass.class.getName());
82+
analyzeFoldMultilinesInvalid(pb);
83+
}
84+
85+
public static class InternalClass {
86+
public static void main(String[] args) {
87+
try {
88+
throw new RuntimeException("line 1\nline 2\\nstring");
89+
} catch (Exception e) {
90+
// Do nothing to return exit code 0
91+
}
92+
}
93+
}
94+
95+
}

0 commit comments

Comments
 (0)
Please sign in to comment.