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

ExceptionInInitializerError when String.format() is used in the class loader constructor with locale and language set to English Canada

    XMLWordPrintable

Details

    Description

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10 and server 12
      Java 8

      A DESCRIPTION OF THE PROBLEM :
      The JVM crash with exception at startup
      at sun.util.resources.LocaleData$1.run(LocaleData.java:167)
      at sun.util.resources.LocaleData$1.run(LocaleData.java:163)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.util.resources.LocaleData.getBundle(LocaleData.java:163)
      at sun.util.resources.LocaleData.getNumberFormatData(LocaleData.java:159)
      at sun.util.locale.provider.LocaleResources.getDecimalFormatSymbolsData(LocaleResources.java:168)
      at java.text.DecimalFormatSymbols.initialize(DecimalFormatSymbols.java:616)
      at java.text.DecimalFormatSymbols.<init>(DecimalFormatSymbols.java:113)
      at sun.util.locale.provider.DecimalFormatSymbolsProviderImpl.getInstance(DecimalFormatSymbolsProviderImpl.java:85)
      at java.text.DecimalFormatSymbols.getInstance(DecimalFormatSymbols.java:180)
      at java.util.Formatter.getZero(Formatter.java:2283)
      at java.util.Formatter.<init>(Formatter.java:1892)
      at java.util.Formatter.<init>(Formatter.java:1914)
      at java.lang.String.format(String.java:2940)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      using Windows 10 change the language English US and locale to Canada.
      Create classloader and in its constructor make a call to String.format (does not matter the arguments)
      set the class loader as the JVM classloader using option -Djava.system.class.loader

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The system should start
      ACTUAL -
      crash occurs at startup with exception below as long as String.format is used in the class loader constructor with the locale and language set as above
      Error occurred during initialization of VM
      java.lang.ExceptionInInitializerError
      at sun.util.resources.LocaleData$1.run(LocaleData.java:167)
      at sun.util.resources.LocaleData$1.run(LocaleData.java:163)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.util.resources.LocaleData.getBundle(LocaleData.java:163)
      at sun.util.resources.LocaleData.getNumberFormatData(LocaleData.java:159)
      at sun.util.locale.provider.LocaleResources.getDecimalFormatSymbolsData(LocaleResources.java:168)
      at java.text.DecimalFormatSymbols.initialize(DecimalFormatSymbols.java:616)
      at java.text.DecimalFormatSymbols.<init>(DecimalFormatSymbols.java:113)
      at sun.util.locale.provider.DecimalFormatSymbolsProviderImpl.getInstance(DecimalFormatSymbolsProviderImpl.java:85)
      at java.text.DecimalFormatSymbols.getInstance(DecimalFormatSymbols.java:180)
      at java.util.Formatter.getZero(Formatter.java:2283)
      at java.util.Formatter.<init>(Formatter.java:1892)
      at java.util.Formatter.<init>(Formatter.java:1914)
      at java.lang.String.format(String.java:2940)
      at classloaderarticle.CCLoader.<init>(CCLoader.java:26)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
      at java.lang.SystemClassLoaderAction.run(ClassLoader.java:2211)
      at java.lang.SystemClassLoaderAction.run(ClassLoader.java:2195)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1456)
      at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1436)
      Caused by: java.lang.IllegalStateException: recursive invocation
      at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1450)
      at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1436)
      at java.util.ServiceLoader.loadInstalled(ServiceLoader.java:568)
      at java.util.ResourceBundle.<clinit>(ResourceBundle.java:376)
      at sun.util.resources.LocaleData$1.run(LocaleData.java:167)
      at sun.util.resources.LocaleData$1.run(LocaleData.java:163)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.util.resources.LocaleData.getBundle(LocaleData.java:163)
      at sun.util.resources.LocaleData.getNumberFormatData(LocaleData.java:159)
      at sun.util.locale.provider.LocaleResources.getDecimalFormatSymbolsData(LocaleResources.java:168)
      at java.text.DecimalFormatSymbols.initialize(DecimalFormatSymbols.java:616)
      at java.text.DecimalFormatSymbols.<init>(DecimalFormatSymbols.java:113)
      at sun.util.locale.provider.DecimalFormatSymbolsProviderImpl.getInstance(DecimalFormatSymbolsProviderImpl.java:85)
      at java.text.DecimalFormatSymbols.getInstance(DecimalFormatSymbols.java:180)
      at java.util.Formatter.getZero(Formatter.java:2283)
      at java.util.Formatter.<init>(Formatter.java:1892)
      at java.util.Formatter.<init>(Formatter.java:1914)
      at java.lang.String.format(String.java:2940)
      at classloaderarticle.CCLoader.<init>(CCLoader.java:26)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
      at java.lang.SystemClassLoaderAction.run(ClassLoader.java:2211)
      at java.lang.SystemClassLoaderAction.run(ClassLoader.java:2195)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1456)
      at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1436)

      ---------- BEGIN SOURCE ----------
      import java.io.DataInputStream;
      import java.io.File;
      import java.io.IOException;
      import java.io.InputStream;

      public class CCLoader extends ClassLoader {

      /**
      * This constructor is used to set the parent ClassLoader
      */
      public CCLoader(ClassLoader parent) {
      super(parent);
      System.out.println(String.format("Constructed CCLoader with parent %s",parent));
      }

      private Class getClass(String name) throws ClassNotFoundException {

      String file = name.replace('.', File.separatorChar) + ".class";
      byte[] b = null;
      try {
      // This loads the byte code data from the file
      b = loadClassFileData(file);
      // defineClass is inherited from the ClassLoader class
      // that converts byte array into a Class. defineClass is Final
      // so we cannot override it
      Class<?> c = defineClass(name, b, 0, b.length);
      resolveClass(c);
      return c;
      } catch (IOException e) {
      e.printStackTrace();
      return null;
      }
      }

      @Override
      public Class loadClass(String name) throws ClassNotFoundException {
      System.out.println("Loading Class '" + name + "'");
      if (name.startsWith("classloaderarticle")){
      System.out.println("................Loading Class using CCLoader store");
      return getClass(name);
      }
      System.out.println("..Using parent classLoader");
      return super.loadClass(name);
      }

      private byte[] loadClassFileData(String name) throws IOException {
      InputStream stream = getClass().getClassLoader().getResourceAsStream(name);
      int size = stream.available();
      byte buff[] = new byte[size];
      DataInputStream in = new DataInputStream(stream);
      in.readFully(buff);
      in.close();
      return buff;
      }
      }




      import java.lang.reflect.Method;

      public class CCRun {

          public static void main(String args[]) throws Exception {
              String progClass = "ClassLoaderTest";
              String progArgs[] = {"1212", "1313"};
              

              CCLoader ccl = new CCLoader(CCRun.class.getClassLoader());
              Class<?> clas = ccl.loadClass(progClass);
              Class<?> mainArgType[] = { (new String[0]).getClass() };
              System.out.println("invoking main on the loaded class .....");
              Method main = clas.getMethod("main", mainArgType);
              Object argsArray[] = { progArgs };
              main.invoke(null, argsArray);
              
          }
       
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Just do not call String.format in the constructor of the classloader. you can use string concat using + will work !

      FREQUENCY : always


      Attachments

        1. CCLoader.java
          2 kB
        2. CCRun.java
          0.6 kB
        3. ClassLoaderTest.java
          0.1 kB
        4. Region.png
          Region.png
          20 kB
        5. Region2.png
          Region2.png
          59 kB

        Activity

          People

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: