JDK-4944478 : eager class loading causes server VM to throw exception
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2003-10-28
  • Updated: 2003-11-25
  • Resolved: 2003-11-25
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.
Other
5.0 b30Fixed
Related Reports
Relates :  
Relates :  
Description

Name: rmT116609			Date: 10/27/2003


FULL PRODUCT VERSION :
java version "1.4.2_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_02-b03)
Java HotSpot(TM) Client VM (build 1.4.2_02-b03, mixed mode)

FULL OS VERSION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
The problem occurs only in the server VM!
We have a class that contains one anonymous inner class and (at least) one named inner class. The anonymous inner class definition (here a Runnable) is disabled with a "if (false)" construct. After several thousand invocations running correctly (!) a ClassLoader exception is thrown claiming it does not find the anonymous inner class definition. We found that the compiler optimized away the entire "if (false)" construct so we were surprised how the VM could know about the absent inner class, but to our surprise we found a reference to it in a weird constructor of the named inner class which has a reference to the anonymous one as second argument, not written by us!
Apparently (from the stacktrace), this second constructor is tried to be used only after hotspot optimized the code.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See the appended short example that reproduces the problem reliably.
Simply compile and then start with "java -server" option.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No exceptions in execution of the demo
ACTUAL -
After a number of dot-lines indicating correct behaviour for thousands of calls the same stacktrace always appears.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.ClassNotFoundException: InnerClassServerVMBug$1
	at java.net.URLClassLoader$1.run(URLClassLoader.java:199)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
	at com.orbotech.flash.jochenr.InnerClassServerVMBug$Data.<init>(InnerClassServerVMBug.java:40)
	at com.orbotech.flash.jochenr.InnerClassServerVMBug.internalCalculate(InnerClassServerVMBug.java:29)
	at com.orbotech.flash.jochenr.InnerClassServerVMBug.calculate(InnerClassServerVMBug.java:25)
	at com.orbotech.flash.jochenr.InnerClassServerVMBug.main(InnerClassServerVMBug.java:58)
Exception in thread "main" Process terminated with exit code 1

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class InnerClassServerVMBug {
    private int _value;
    public InnerClassServerVMBug() {
        _value = 0;
    }
    public void calculate() {
        if (false) {
            new Runnable() {
                public void run() {
                    internalCalculate();
                }
            }.run();
        } else
            internalCalculate();
    }
    private void internalCalculate() {
        setValue(new Data(0).getData());
    }
    private void setValue(int result) {
        _value = result;
    }
    public int getValue() {
        return _value;
    }

    private class Data {
        int _data;

        private Data(int data) {
            _data = data;
        }

        public int getData() {
            return _data;
        }
    }
    public static void main(String[] args) throws Exception {
        final InnerClassServerVMBug p = new InnerClassServerVMBug();
        long sum = 0;
        int idx = 0;

        while (sum < 10000000L) {
            p.calculate();
            sum += p.getValue();
            System.out.print(".");
            if (++idx >= 100) {
                System.out.println();
                idx = 0;
            }
            System.out.flush();
        }
        System.out.println("sum = " + sum);
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Commenting out the anonymous inner class code instead of using "if (false){}" block
(Incident Review ID: 217483) 
======================================================================

Comments
SUGGESTED FIX file:///net/prt-archiver.sfbay/data/archived_workspaces/main/c2_baseline/2003/20031117154426.rasbold.c2_baseline1/workspace/webrevs/webrev-2003.11.17/index.html
05-11-2007

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger-beta FIXED IN: tiger-beta INTEGRATED IN: tiger-b30 tiger-beta
14-06-2004

EVALUATION Javac fails to generate a .class file for the anonymous inner class. The wrapper for the Data constructor has an unused parameter (for purposes of having a unique signature) which is an object from the anonymous inner class. The server compiler, when attempting to compile the <init> method from the Data class, attempts to eagerly load the anonymous class. This, of course, fails, and the VM reports it as a ClassNotFoundException. The compiler broker needs to more resiliant when a class eager loaded fails. Still need to investigate if the lack of a .class file is a javac bug. ###@###.### 2003-11-13
13-11-2003