JDK-6764974 : Plugin2: casts a ClassNotFoundException instead of a NoClassDefFoundError
  • Type: Bug
  • Component: deploy
  • Sub-Component: plugin
  • Affected Version: 6u10
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2008-10-29
  • Updated: 2011-02-16
  • Resolved: 2009-01-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6u12 b01Fixed
Description
FULL PRODUCT VERSION :
Java 1.6.0_10

ADDITIONAL OS VERSION INFORMATION :
Windows XP SP3
But would fail with any other windows/linux/solaris version that uses the Applet2ClassLoader found in plugin2

A DESCRIPTION OF THE PROBLEM :
Previous to Java 1.6.0_10 loading a class which extended or otherwise refered to a non-existing class would cause a NoClassDefFoundError to be thrown.

With plugin2 this now causes a ClassNotFoundException to be thrown instead, stating that the given class cannot be loaded because it does not exist (even though it does).

A quick example can be found here
http://ziggy.signaturgruppen.dk/MissingClassDemo/

The example consists of two classes (one of which has been deleted in this example to cause the error to happen).

public ClassOne extends Applet
public ClassTwo extends ClassOne

These two classes have been compiled (to ClassOne.class and ClassTwo.class) and ClassTwo.class has been placed on the website, without ClassOne.

When starting this applet (calling ClassTwo directly as in the example) the new JRE 1.6.0_10 using plugin2 will throw a ClassNotFoundException (caused by either a FileNotFoundException on the loaded class when running locally or an IOException when running on a webserver) even though ClassTwo does in fact exist.

java.lang.ClassNotFoundException: dk.signaturgruppen.demo.ClassTwo.class
	at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	... [snip] ...
Caused by: java.io.IOException: open HTTP connection failed:http://10.10.117.110:9080/MissingClassDemo/dk/signaturgruppen/demo/ClassTwo/class.class
	at sun.plugin2.applet.Applet2ClassLoader.getBytes(Unknown Source)
	... [snip] ...

Previous to plugin2 (fx. using Java 1.6.0_07 or disabling plugin2 in the control panel) the same code would throw a NoClassDefFoundError (caused by a ClassNotFoundException on the class the loaded class extends or refers)

java.lang.NoClassDefFoundError: dk/signaturgruppen/test/ClassOne
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(Unknown Source)
	at java.security.SecureClassLoader.defineClass(Unknown Source)
	... [snip] ...
Caused by: java.lang.ClassNotFoundException: dk.signaturgruppen.test.ClassOne
	at sun.applet.AppletClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	... [snip] ...

This change of behaviour has caused some of our frameworks to behave differently. We would expect the correct behaviour to be the one used by the old plugin, whereas the new plugin2 causes the user to think that the class is missing (even though it is a class that it refers that is missing).


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Visit the link with plugin2 enabled, and then with plugin2 disabled (using the controlpanel to turn plugin2 on/off works fine).

Otherwise, simple create a very small applet with two classes, where one extends the other, and then delete the super class. The result should be the same (ClassNotFoundException for plugin2 and NoClassDefFound for plugin1).

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
We would expect the code to throw a NoClassDefFoundError
ACTUAL -
The code throws a ClassNotFoundException on the class that does in fact exist, hiding the fact that it is one of the classes that it refers that does not exist.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Just the backtraces mentioned above

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
File: ClassOne.java
public class ClassOne extends Applet {
	public void init() {
		System.out.println("Applet is running");
	}
}

File: ClassTwo.java
public class ClassTwo extends ClassOne {
	public void init() {
		super.init();
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Turning of plugin2 in the control panel.

Release Regression From : 6u7
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
EVALUATION Since we use reflection to call defineClass() method in Plugin2ClassLoader's superclass, the NoClassDefFoundError is buried deeply in the exceptions chain. We can propagate such error in order to be consistent with old plugin. Please note in the old plugin, since it throws NoClassDefFoundError instead of ClassNofFoundException, it effectively skips the codebase lookup. In this sample testcase, the missing ClassOne.class is not looked up in the codebase url.
30-10-2008

EVALUATION This is probably related to the new class signing checks that were necessarily added in the context of the new Java Plug-In. Assigning for further investigation.
29-10-2008