-
Enhancement
-
Resolution: Cannot Reproduce
-
P4
-
None
-
1.3.0
-
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
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