changeset 14733:5b5637f91747

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
author dfuchs
date Mon, 13 Jun 2016 08:20:34 +0100
parents 5274a502619e
children ac3e32924dfb
files src/java.logging/share/classes/java/util/logging/Formatter.java src/java.logging/share/classes/java/util/logging/SimpleFormatter.java test/java/util/logging/SimpleFormatterFormat.java
diffstat 3 files changed, 31 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.logging/share/classes/java/util/logging/Formatter.java	Sun Jun 12 21:55:20 2016 -0700
+++ b/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/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java	Sun Jun 12 21:55:20 2016 -0700
+++ b/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/test/java/util/logging/SimpleFormatterFormat.java	Sun Jun 12 21:55:20 2016 -0700
+++ b/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 = " +