java.util.Calendar.java (cache): New private static field.
authorBryce McKinlay <mckinlay@redhat.com>
Sat, 10 Jul 2004 02:38:55 +0000 (02:38 +0000)
committerBryce McKinlay <bryce@gcc.gnu.org>
Sat, 10 Jul 2004 02:38:55 +0000 (03:38 +0100)
2004-07-09  Bryce McKinlay  <mckinlay@redhat.com>

* java.util.Calendar.java (cache): New private static field. Cached
mappings of locales->calendar classes.
(ctorArgTypes): New private static field. Singleton argument for
calendar class constructor lookup.
(getInstance): Cache Locale->Calendar class mappings using HashMap.
Optimize by bypassing reflection instantiation for the
GregorianCalendar case.

From-SVN: r84438

libjava/ChangeLog
libjava/java/util/Calendar.java

index c69302e425ac27f6e9c282454eb58376e630e77d..5e2492069c9168f61d55165fcd5dfb08c035c2de 100644 (file)
@@ -1,3 +1,13 @@
+2004-07-09  Bryce McKinlay  <mckinlay@redhat.com>
+
+       * java.util.Calendar.java (cache): New private static field. Cached
+       mappings of locales->calendar classes.
+       (ctorArgTypes): New private static field. Singleton argument for
+       calendar class constructor lookup.
+       (getInstance): Cache Locale->Calendar class mappings using HashMap.
+       Optimize by bypassing reflection instantiation for the 
+       GregorianCalendar case.
+
 2004-07-09  Bryce McKinlay  <mckinlay@redhat.com>
 
        * java/util/Calendar.java: Use getSystemClassLoader as argument for
index e1ecf3e519aee6d2dc16c9999e094be23393e51e..b7ffb3381064711c0f7784931478d6fb42c8fc2c 100644 (file)
@@ -437,6 +437,16 @@ public abstract class Calendar implements Serializable, Cloneable
     return getInstance(TimeZone.getDefault(), locale);
   }
 
+  /** 
+   * Cache of locale->calendar-class mappings. This avoids having to do a ResourceBundle
+   * lookup for every getInstance call.  
+   */
+  private static HashMap cache = new HashMap();
+
+  /** Preset argument types for calendar-class constructor lookup.  */
+  private static Class[] ctorArgTypes
+    = new Class[] {TimeZone.class, Locale.class};
+
   /**
    * Creates a calendar representing the actual time, using the given
    * time zone and locale.
@@ -445,29 +455,58 @@ public abstract class Calendar implements Serializable, Cloneable
    */
   public static synchronized Calendar getInstance(TimeZone zone, Locale locale)
   {
-    String calendarClassName = null;
-    ResourceBundle rb = getBundle(locale);
-    calendarClassName = rb.getString("calendarClass");
-    if (calendarClassName != null)
+    Class calendarClass = (Class) cache.get(locale);
+    Throwable exception = null;
+
+    try
       {
-       try
+       if (calendarClass == null)
          {
-           Class calendarClass = Class.forName(calendarClassName);
-           if (Calendar.class.isAssignableFrom(calendarClass))
+           ResourceBundle rb = getBundle(locale);
+           String calendarClassName = rb.getString("calendarClass");
+
+           if (calendarClassName != null)
              {
-               return (Calendar) calendarClass.getConstructor(
-                 new Class[] { TimeZone.class, Locale.class}
-               ).newInstance(new Object[] {zone, locale} );
+               calendarClass = Class.forName(calendarClassName);
+               if (Calendar.class.isAssignableFrom(calendarClass))
+                 cache.put(locale, calendarClass);
              }
          }
-       catch (ClassNotFoundException ex) {}
-       catch (IllegalAccessException ex) {}
-       catch (NoSuchMethodException ex) {}
-       catch (InstantiationException ex) {}
-       catch (InvocationTargetException ex) {}
-       // XXX should we ignore these errors or throw an exception ?
+
+        // GregorianCalendar is by far the most common case. Optimize by 
+       // avoiding reflection.
+       if (calendarClass == GregorianCalendar.class)
+         return new GregorianCalendar(zone, locale);
+
+       if (Calendar.class.isAssignableFrom(calendarClass))
+         {
+           Constructor ctor = calendarClass.getConstructor(ctorArgTypes);
+           return (Calendar) ctor.newInstance(new Object[] {zone, locale});
+         }
+      }
+    catch (ClassNotFoundException ex)
+      {
+       exception = ex;
+      }
+    catch (IllegalAccessException ex)
+      {
+       exception = ex;
+      }
+    catch (NoSuchMethodException ex)
+      {
+       exception = ex;
+      }
+    catch (InstantiationException ex)
+      {
+       exception = ex;
+      }
+    catch (InvocationTargetException ex)
+      {
+       exception = ex;
       }
-    return new GregorianCalendar(zone, locale);
+    
+    throw new RuntimeException("Error instantiating calendar for locale " +
+                              locale, exception);
   }
 
   /**