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

javap throws NPE with improper clone method in subclass

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Cannot Reproduce
    • Icon: P4 P4
    • None
    • 1.3.0
    • tools
    • sparc
    • generic

      The Transparent Persistence team is
      working on a post-processing tool that reads in .class files and
      enhances the byte code for persistence.

      We've found a bug with the 'javap'
      disassembler tool that is shipped with:

          92 tmp> java -version
          java version "1.2.2"
          Solaris VM (build Solaris_JDK_1.2.2_05a, native threads, sunwjit)
          
      and

          15 tmp> java -version
          java version "1.3.0"
          Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
          Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

      Please find further details on the bug below.

      Description:
      ------------

      If a class file contains a _protected_ method clone() (added
      by postprocessor) and there's a superclass providing a _public_ clone(),
      then javap crashes with a null-pointer exception.

      The generated class file clearly violates Java's rule that the access
      modifier of a class member must not be restricted by subclasses. However,
      javap shouldn't crash with an exception indicating an internal error but
      should report the actual problem with the byte-code instead.


      Files in the attachment .zip file:
      ------

        Test.java // the test's source
                                    
        before/enhancer/clone: // the unmodified .class files generated by javac
            PT.class // subclass
            PTC.class // subclass, doesn't contain a method clone()
            T.class // superclass
            TC.class // superclass, contains a public method clone()
            Test.class // main program
                                    
        after/enhancer/clone: // the modified, postprocessed .class files
            PT.class // contains a generated, protected method clone()
            PTC.class // contains a generated, protected method clone()

        crosscheck/enhancer/clone: // the unmodified .class file generated by javac
            TC.class // superclass, contains a protected method clone()
          
        PTC_NPE.log // exception stack trace by running javap on PTC

        PTC_OK.log // crosscheck: normal output running javap on PTC

        PT.log // normal output produced by javap
          
        Test.log // test's normal execution trace


      How to reproduce the bug:
      -------------------------

      1. Set the CLASSPATH to contain the modified classes before the
         unmodified ones:

             export CLASSPATH=after:before

      2. Run the test on the modified test classes:

             java enhancer.clone.Test (redirect to Test.log)

         The output file Test.log shows that the modifed files are accepted by
         the JVM and execute normally.

      3. Run javap on the modified class PTC:

             javap -private -c enhancer.clone.PTC (redirect to PTC_NPE.log)

         The error output file PTC.log shows the null-pointer exception.
         The problem is caused by the protected method clone() in class PTC
         overriding the public method clone() in the superclass TC. This is an
         infeasible restriction of the access modifier by the subclass.
         Generating the method PTC.clone() with a public access modifier makes
         the problem with javap disappear.

      4. Do the crosscheck: Make the superclass TC having a protected instead of
         public method clone() and run 'javap' on the subclass PTC again -- which
         now succeeds without any null-pointer exception, since the method's
         access modifier isn't restricted by the subclass anymore.

         The directory 'crosscheck' already contains the compiled superclass TC,
         which resulted from changing the source file Test.java for method
         TC.clone() being protected and compiling into directory 'crosscheck'.
         Set CLASSPATH to use the superclass from 'crosscheck' and run 'javap'

             export CLASSPATH=after:crosscheck:before
             javap -private -c enhancer.clone.PTC (redirect to PTC_OK.log)

      5. Run javap on the modified class PT:

             javap -private -c enhancer.clone.PT (redirect to PT.log)

         This executes fine. Because the super class T of the class PT doesn't
         provide a method clone() at all, the protected method clone() in the
         subclass PT overrides the protected clone() from the java.lang.Object,
         which doesn't restrict the access modifier.

         However, this class shows another flaw of javap: The generated method
         clone() contains an instruction:
             invokespecial <Method java.lang.Object enhancer.clone.T.clone()>

         This method invocation isn't clearly resolved by javap, which prints:
             invokespecial #75 <Method null>

         This is due to the fact that the direct superclass enhancer.clone.T
         doesn't define a method clone() at all. However, as the JVM, javap
         should be able to resolve by the same rule that the code for that
         non-virtual method invocation is taken from the class java.lang.Object.


      If you have questions:
      ----------------------

      contact:

          Martin Zaun Tech@Spree Software Technology GmbH
          mailto:###@###.### Buelowstr. 66
          Tel.:++49/30/23 55 20-33 D-10783 Berlin
          Fax.:++49/30/21 75 20-12 http://www.tech.spree.de

      or:
          Craig Russell 650 786-7819
          Architect mailto:###@###.###
          Sun Microsystems, Inc. http://www.sun.com

            Unassigned Unassigned
            clrussel Craig Russell (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: