Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4812194

Suggest ResourceBundle.loadBundle check for .class before calling Class.forName

    XMLWordPrintable

Details

    • Enhancement
    • Resolution: Duplicate
    • P4
    • None
    • 1.4.1_01
    • core-libs
    • None

    Description

      During startup of an application that uses *.properties resource bundles heavily (e.g. NetBeans / Sun ONE Studio IDE), there is some overhead caused by ResourceBundle's search algorithm. Specifically, loadBundle (used to physically try loading a bundle from a given loader using a given base name + locale) first tries Class.forName to load .class resources, then if that fails (typically with ClassNotFoundException), then tries looking for a .properties file.

      The problem is that an exception is being used for control flow - a perfectly normal situation results in potentially many exceptions being created and then discarded, for which the JVM is poorly optimized. ClassLoader currently does not provide any API for loading a class and returning null on failure.

      Suggest a tiny optimization that would be helpful: loadBundle should first check for the existence of the .class file:

      String classFile = bundleName.replace('.', '/') + ".class";
      // similarly for loader == null of course:
      if (loader.getResource(classFile) != null) {
          // try Class.forName as before
      }
      // continue trying .properties

      This would avoid the CNFE in the primary control flow.

      One caveat: I am not sure if the ClassLoader specification requires that a loader supply a foo/Bar.class resource for every foo.Bar class it is capable of loading. Certainly all loaders I have come across do so, but it is not clear if this is necessarily true for exotic network or dynamic loaders.

      Sample test class:

      ---%<---
      import java.net.URL;
      import java.util.*;
      public class RBTest {
          public static void main(String[] x) throws Exception {
              try {
                  ResourceBundle.getBundle("foo.bar", Locale.getDefault(), new L());
              } catch (MissingResourceException e) {
                  // ignore
              }
          }
          private static final class L extends ClassLoader {
              public Class loadClass(String n) throws ClassNotFoundException {
                  System.out.println("loadClass: " + n);
                  return super.loadClass(n);
              }
              public URL getResource(String n) {
                  System.out.println("getResource: " + n);
                  return super.getResource(n);
              }
          }
      }
      ---%<---

      Actual output:

      ---%<---
      java version "1.4.1_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
      Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

      loadClass: foo.bar
      getResource: foo/bar.properties
      loadClass: foo.bar_en
      getResource: foo/bar_en.properties
      loadClass: foo.bar_en_US
      getResource: foo/bar_en_US.properties
      ---%<---

      Would prefer to see e.g.:

      ---%<---
      getResource: foo/bar.class
      loadClass: foo.bar
      getResource: foo/bar.properties
      getResource: foo/bar_en.class
      loadClass: foo.bar_en
      getResource: foo/bar_en.properties
      getResource: foo/bar_en_US.class
      loadClass: foo.bar_en_US
      getResource: foo/bar_en_US.properties
      ---%<---

      ###@###.### 2003-02-03

      Attachments

        Issue Links

          Activity

            People

              okutsu Masayoshi Okutsu
              jglick Jesse Glick (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: