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

ResourceBundle.getBundle() can return NONEXISTENT_BUNDLE

XMLWordPrintable

      FULL PRODUCT VERSION :


      A DESCRIPTION OF THE PROBLEM :
      There seems to be a concurrency problem inside java.util.ResourceBundle.getBundle() caching logic where it's possible that the algorithm returns NONEXISTENT_BUNDLE, which is not supposed to be returned.

      ResrouceBundle.putBundleInCache() could return NONEXISTENT_BUNDLE if another thread has put it in the cache. It should check the result of cacheList.putIfAbsent() to not be NONEXISTENT_BUNDLE


      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.util.MissingResourceException: Can't find resource for bundle java.util.ResourceBundle$1, key NumberElements
      at java.util.ResourceBundle.getObject(ResourceBundle.java:395) ~[na:1.7.0_67]
      at java.util.ResourceBundle.getObject(ResourceBundle.java:392) ~[na:1.7.0_67]
      at java.util.ResourceBundle.getStringArray(ResourceBundle.java:372) ~[na:1.7.0_67]
      at java.text.DecimalFormatSymbols.initialize(DecimalFormatSymbols.java:541) ~[na:1.7.0_67]
      at java.text.DecimalFormatSymbols.<init>(DecimalFormatSymbols.java:94) ~[na:1.7.0_67]
      at java.text.DecimalFormatSymbols.getInstance(DecimalFormatSymbols.java:157) ~[na:1.7.0_67]
      at java.util.Formatter.getZero(Formatter.java:2251) ~[na:1.7.0_67]
      at java.util.Formatter.<init>(Formatter.java:1877) ~[na:1.7.0_67]
      at java.util.Formatter.<init>(Formatter.java:1898) ~[na:1.7.0_67]
      at java.lang.String.format(String.java:2790) ~[na:1.7.0_67]

      REPRODUCIBILITY :
      This bug can be reproduced rarely.

      ---------- BEGIN SOURCE ----------
      import java.net.URL;
      import java.net.URLClassLoader;
      import java.util.Arrays;
      import java.util.Collections;
      import java.util.Enumeration;
      import java.util.Locale;
      import java.util.MissingResourceException;
      import java.util.Random;
      import java.util.ResourceBundle;
      import java.util.concurrent.atomic.AtomicInteger;

      public class ResourceBundleTest {

        static Random rnd = new Random();
        static AtomicInteger ctr = new AtomicInteger();
        static AtomicInteger tryCounter = new AtomicInteger();

        public static void main(String[] args) throws Exception {
          final CL1 cl = new CL1(new URL[0]);
          for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {

              @Override
              public void run() {
                while (true) {
                  if (rnd.nextFloat() > 0.8) {
                    ctr.incrementAndGet();
                  }
                  int c = tryCounter.incrementAndGet();
                  if (c % 1000 == 0) {
                    System.out.println(c);
                  }
                  try {
                    ResourceBundle bundle = ResourceBundle.getBundle("" + ctr.get(), Locale.getDefault(), cl);
                    if (bundle.getClass().getName().contains("$1")) {
                      System.err.println("ERROR: " + bundle + " " + c);
                      System.exit(1);
                    }
                  }
                  catch (MissingResourceException e) {
                  }
                }
              }

            }).start();
          }
        }

        static class CL1 extends URLClassLoader {

          private Random r = new Random();

          public CL1(URL[] urls) {
            super(urls);
          }

          @Override
          public Class<?> loadClass(String name) throws ClassNotFoundException {
            if (r.nextBoolean()) {
              return Bundle.class;
            }
            else {
              throw new ClassNotFoundException();
            }
          }

        }

        public static class Bundle extends ResourceBundle {

          @Override
          protected Object handleGetObject(String key) {
            return new Object();
          }

          @Override
          public Enumeration<String> getKeys() {
            return Collections.enumeration(Arrays.asList("foo"));
          }

        }

      }

      ---------- END SOURCE ----------

            naoto Naoto Sato
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: