8153666: Optimize Formatter.formatMessage
Summary: This patch brings a small optimization that removes needless synchronization in Formatter.formatMessage. It also fixes the code that decides whether to call MessageFormat, and brings a small clarification to the API documentation on the conditions when that will happen.
Reviewed-by: rriggs, martin
--- a/jdk/src/java.logging/share/classes/java/util/logging/Formatter.java Sun Jun 12 21:55:20 2016 -0700
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Formatter.java Mon Jun 13 08:20:34 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -101,23 +101,23 @@
* formatting.
* <ul>
* <li>If there are no parameters, no formatter is used.
- * <li>Otherwise, if the string contains "{0" then
- * java.text.MessageFormat is used to format the string.
+ * <li>Otherwise, if the string contains "{{@literal<digit>}"
+ * where {@literal <digit>} is in [0-9],
+ * java.text.MessageFormat is used to format the string.
* <li>Otherwise no formatting is performed.
* </ul>
*
* @param record the log record containing the raw message
* @return a localized and formatted message
*/
- public synchronized String formatMessage(LogRecord record) {
+ public String formatMessage(LogRecord record) {
String format = record.getMessage();
java.util.ResourceBundle catalog = record.getResourceBundle();
if (catalog != null) {
try {
- format = catalog.getString(record.getMessage());
+ format = catalog.getString(format);
} catch (java.util.MissingResourceException ex) {
// Drop through. Use record message as format
- format = record.getMessage();
}
}
// Do the formatting.
@@ -130,11 +130,16 @@
// Is it a java.text style format?
// Ideally we could match with
// Pattern.compile("\\{\\d").matcher(format).find())
- // However the cost is 14% higher, so we cheaply check for
- // 1 of the first 4 parameters
- if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
- format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
- return java.text.MessageFormat.format(format, parameters);
+ // However the cost is 14% higher, so we cheaply use indexOf
+ // and charAt to look for that pattern.
+ int index = -1;
+ int fence = format.length() - 1;
+ while ((index = format.indexOf('{', index+1)) > -1) {
+ if (index >= fence) break;
+ char digit = format.charAt(index+1);
+ if (digit >= '0' & digit <= '9') {
+ return java.text.MessageFormat.format(format, parameters);
+ }
}
return format;
--- a/jdk/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java Sun Jun 12 21:55:20 2016 -0700
+++ b/jdk/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java Mon Jun 13 08:20:34 2016 +0100
@@ -153,7 +153,7 @@
* @return a formatted log record
*/
@Override
- public synchronized String format(LogRecord record) {
+ public String format(LogRecord record) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(
record.getInstant(), ZoneId.systemDefault());
String source;
--- a/jdk/test/java/util/logging/SimpleFormatterFormat.java Sun Jun 12 21:55:20 2016 -0700
+++ b/jdk/test/java/util/logging/SimpleFormatterFormat.java Mon Jun 13 08:20:34 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6381464
+ * @bug 6381464 8153666
* @summary Test the custom simple formatter output
*
* @run main/othervm SimpleFormatterFormat
@@ -60,13 +60,19 @@
"test.foo",
"test.foo",
"test.bar",
+ "test.bar",
+ "test.bar",
"test.bar"
};
private static String[] messages = new String[] {
"severe hello world",
"warning lost connection",
"info welcome",
- "warning exception thrown",
+ "warning beware of traps",
+ "warning { {ok7} }",
+ // keep exception logging as last test case to avoid having
+ // to skip the exception stack trace in the output
+ "warning exception thrown"
};
private static void writeLogRecords(PrintStream logps) throws Exception {
try {
@@ -79,8 +85,11 @@
Logger bar = Logger.getLogger("test.bar");
bar.finest("Dummy message");
bar.info(messages[2]);
- bar.log(Level.WARNING, messages[3], new IllegalArgumentException());
+ bar.log(Level.WARNING, "{0}", new Object[] { messages[3] });
+ bar.log(Level.WARNING, "warning '{' '{'{7}} }", new Object[] {"ok", "ok1", "ok2", "ok3", "ok4", "ok5", "ok6", "ok7", "ok8", "ok9", "ok10"});
+ // Keep this one last - as it also prints the exception stack trace...
+ bar.log(Level.WARNING, messages[messages.length-1], new IllegalArgumentException());
} finally {
logps.flush();
logps.close();
@@ -108,7 +117,7 @@
Matcher m = p.matcher(line);
if (!m.matches()) {
- throw new RuntimeException("Unexpected output format");
+ throw new RuntimeException("Unexpected output format: " + line);
}
if (m.groupCount() != 3) {
throw new RuntimeException("Unexpected group count = " +