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

Class.forName(String) does not comply with the specs for arrays

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 5.0
    • core-libs

      FULL PRODUCT VERSION :
      java version "1.5.0_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
      Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode, sharing)

      java version "1.4.2_06"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)
      Java HotSpot(TM) Client VM (build 1.4.2_06-b03, mixed mode)

      java version "1.3.1_15"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_15-b01)
      Java HotSpot(TM) Client VM (build 1.3.1_15-b01, mixed mode)

      And oldier versions too !

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      This bug follows the bug 6228805 (<a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6228805">bug ID 6228805</a>) that I have already reported.

      As currently stated in the Javadoc of the JDK, it appears that many APIs dealing with class names are not rigorously implemented. Well, it is more likely that the problem comes from the ambiguity of the Javadoc rather than the proven JDK implementation but it is still quite disconcerting.

      If we read the Javadoc for Class.forName(String) at the letter, the className parameter is said to be "the fully qualified name of the desired class". Then, if I refer to the Java Language specifications at section "6.7 Fully Qualified Names and Canonical Names", I guess that I should be able to get my array class with a call such as:
      Class.forName("mypackage.MyClass[]")
      but this does not work (giving the fully qualified name of my array class even so). What is not clearly stated here is that this method requires the internal VM representation of my array class, that is, Class.forName("[Lmypackage.MyClass;"). This is the only way to get my array class.

      The other method Class.forName(String, boolean, ClassLoader) mentions that the class name is in the same format as returned by Class.getName() but it still asserts that it is the fully qualified name. This is not true according to the Java Language Specifications. The Class.getName() returns a String which can be qualified as an hybrid class name. Actually, for simple class name, it is really the fully qualified name but for class of arrays it is not.

      I have noticed that the ClassLoader Javadoc has been clarified in a similar fashion since JDK 5.0. Actually, all methods taking a class name as a String now clearly says that the "binary name" is required. Then, I would like to suggest that all methods in the class Class are clarified in the same way. It may be useful to assign a new term for the class name representation used in class Class, to give it a clear definition in the Javadoc and to create links to this definition whenever such representation is required in any method.

      I think it should be useful that the Javadoc includes direct links to the sections in the Java Language Specifications related to "fully qualified name" (6.7), "binary name" (13.1) and "canonical name" (6.7) rather than a simple link to the document in its whole.

      Moreover, I did not check all APIs in the JDK that may require a class name as a String but I think that it would very beneficial to make the whole Javadoc homogeneous according to the previous comments.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the code I have attached with any version of the JDK.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I was expecting to be able to load a class of array with its fully qualified name as specified by the Class.forName(String) description and the Java Language specs but this does not work.
      ACTUAL -
      D:\Tests\mypackage>d:\jdk1.5.0\bin\java mypackage.Test

      Trying to get a class by calling Class.forName(mypackage.MyClass[])...
      java.lang.ClassNotFoundException: mypackage/MyClass[]
              at java.lang.Class.forName0(Native Method)
              at java.lang.Class.forName(Class.java:164)
              at mypackage.Test.checkClassLoading(Test.java:21)
              at mypackage.Test.main(Test.java:9)
      Class mypackage.MyClass[] could not be retrieved !

      Trying to get a class by calling Class.forName([Lmypackage.MyClass;)...
      Class [Lmypackage.MyClass; has been successfully retrieved.

      D:\Tests\mypackage>d:\jdk1.4.2\bin\java mypackage.Test

      Trying to get a class by calling Class.forName(mypackage.MyClass[])...
      java.lang.ClassNotFoundException: mypackage/MyClass[]
              at java.lang.Class.forName0(Native Method)
              at java.lang.Class.forName(Class.java:141)
              at mypackage.Test.checkClassLoading(Test.java:21)
              at mypackage.Test.main(Test.java:9)
      Class mypackage.MyClass[] could not be retrieved !

      Trying to get a class by calling Class.forName([Lmypackage.MyClass;)...
      Class [Lmypackage.MyClass; has been successfully retrieved.

      D:\Tests\mypackage>d:\jdk1.3.1\bin\java mypackage.Test

      Trying to get a class by calling Class.forName(mypackage.MyClass[])...
      java.lang.ClassNotFoundException: mypackage/MyClass[]
              at java.lang.Class.forName0(Native Method)
              at java.lang.Class.forName(Class.java:115)
              at mypackage.Test.checkClassLoading(Test.java:21)
              at mypackage.Test.main(Test.java:9)
      Class mypackage.MyClass[] could not be retrieved !

      Trying to get a class by calling Class.forName([Lmypackage.MyClass;)...
      Class [Lmypackage.MyClass; has been successfully retrieved.

      D:\Tests\mypackage>d:\jdk1.2.2\bin\java mypackage.Test

      Trying to get a class by calling Class.forName(mypackage.MyClass[])...
      java.lang.ClassNotFoundException: mypackage/MyClass[]
              at java.lang.Class.forName0(Native Method)
              at java.lang.Class.forName(Class.java:117)
              at mypackage.Test.checkClassLoading(Test.java:21)
              at mypackage.Test.main(Test.java:9)
      Class mypackage.MyClass[] could not be retrieved !

      Trying to get a class by calling Class.forName([Lmypackage.MyClass;)...
      Class [Lmypackage.MyClass; has been successfully retrieved.

      D:\Tests\mypackage>d:\jdk1.1.8\bin\java mypackage.Test

      Trying to get a class by calling Class.forName(mypackage.MyClass[])...
      java.lang.IllegalArgumentException: mypackage.MyClass[]
              at mypackage.Test.checkClassLoading(Test.java:21)
              at mypackage.Test.main(Test.java:9)
      Class mypackage.MyClass[] could not be retrieved !

      Trying to get a class by calling Class.forName([Lmypackage.MyClass;)...
      Class [Lmypackage.MyClass; has been successfully retrieved.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      I get a java.lang.ClassNotFoundException with all Java2 JDKs.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package mypackage;

      import java.io.*;

      public class Test
      {
          public static void main(String[] args) throws Exception
          {
              checkClassLoading("mypackage.MyClass[]");
              checkClassLoading("[Lmypackage.MyClass;");
          }

          private static void checkClassLoading(String className)
          {
              Class clazz = null;

              System.out.println();
              System.out.println("Trying to get a class by calling Class.forName(" + className + ")...");
              try
              {
                  clazz = Class.forName(className);
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }

              if (clazz != null)
              {
                  System.out.println("Class " + className + " has been successfully retrieved.");
              }
              else
              {
                  System.out.println("Class " + className + " could not be retrieved !");
              }
          }
      }

      class MyClass implements Serializable
      {
          private String name;

          public MyClass(String name)
          {
              this.name = name;
          }

          public String toString()
          {
              return name;
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Use the VM internal representation of a class of an array instead of its fully qualified name.
      ###@###.### 2005-04-01 09:13:11 GMT

            mchung Mandy Chung (Inactive)
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: