2016-04-05 7 views
1

デバッグログのフォーマットに使用される抽象JDKクラスFormatterでは、formatMessageメソッドがsynchronizedとして宣言されています。java.util.logging.FormatterのformatMessage()メソッドが同期されているのはなぜですか?

しかし、私はそのような場合の理由を特定できませんでした。

明らかに、スレッドセーフではないオーバーライドバージョンを書くことができますが、なぜデフォルトの実装がスレッドセーフではないのだろうと思います。

+0

https://docs.oracle.com/javase/7/docs/api/java/util/logging/Formatter.html#formatMessage(java.util.logging.LogRecord)私はそれを表示しません同期されていなくても、7も8でもない。 –

+0

OpenJDKでは間違いなく同期化されているが、おそらくJavaDocs(独特のもの) にはない。http://grepcode.com/file/repository.grepcode.com/java/root/jdk/ openjdk/6-b14/java/util/logging/Formatter。java#113 – Uri

+0

おそらく、たくさんのリソースバンドルを読み込んでメモリを奪うのを避けるために?その仕様に関する直接の詳細はありません。 –

答えて

2

[T] formatMessageメソッドはsynchronizedとして宣言されていますが、私はそのような理由を判断できませんでした。

java.util.logging.Formatterの初期バージョンは、java.util.MissingResourceExceptionの構築を避けるために、リソースバンドルのget string呼び出しの結果をキャッシュしようとしました。ルックアップのキャッシュに使用されたHashMapを保護するために同期が使用されました。ここで

は、著作権2004年サン・マイクロシステムズ社のバージョン1.16で、12/19/03ソースコード、コメントの点に注意してください。

public synchronized String formatMessage(LogRecord record) { 
    String format = record.getMessage(); 
    java.util.ResourceBundle catalog = record.getResourceBundle(); 
    if (catalog != null) { 
     // We cache catalog lookups. This is mostly to avoid the 
     // cost of exceptions for keys that are not in the catalog. 
    //  if (catalogCache == null) { 
    //  catalogCache = new HashMap(); 
    //  } 
    //  format = (String)catalogCache.get(record.essage); 
    //  if (format == null) { 
      try { 
       format = catalog.getString(record.getMessage()); 
      } catch (java.util.MissingResourceException ex) { 
       // Drop through. Use record message as format 
       format = record.getMessage(); 
      } 
    //  catalogCache.put(record.message, format); 
    //  } 
    } 
    // Do the formatting. 
    try { 
     Object parameters[] = record.getParameters(); 
     if (parameters == null || parameters.length == 0) { 
     // No parameters. Just return format string. 
     return format; 
     } 
    // Is is 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); 
     } 
     return format; 
    } catch (Exception ex) { 
     // Formatting failed: use localized format string. 
     return format; 
    } 
} 

デフォルトの実装では、スレッドセーフではありませんなぜ私は思ったんだけど。

キャッシュコードがコメントアウトされたときに、同期が削除されているはずです。この問題はJDK-8153666: Possible optimization of Formatter.formatMessageの下に提出されています。

それは間違いなくWhat's New in Javadoc 1.2からのJavaDoc

でのOpenJDKに同期しますが、おそらくないです:

削除 "同期" と署名から "ネイティブ"。 JavadocはAPI仕様を生成します。これらの2つのキーワードは、実装固有のものであるため、仕様のシグネチャには属しません。キーワード「native」は文書化する必要はありません。キーワード "synchronized"は、スレッドセーフな動作を示し、代わりにメソッドの説明に記述する必要があります。スレッドセーフメソッド自体は "synchronized"キーワードを使用しないかもしれませんが、プライベートメソッドを呼び出すかもしれません。

P.S.

  1. record.essage元のコードからの実際の入力ミスです。
  2. record.getMessage()が最初の呼び出しでローカルに格納されていても、複数回呼び出されたことに注目してください。
  3. このコードでは、NPEで失敗するcatalog.getStringにヌル参照を渡すことができます。
関連する問題