Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4944478
Votes 3
Synopsis eager class loading causes server VM to throw exception
Category hotspot:compiler2
Reported Against 1.4.2
Release Fixed 1.5(tiger-b30)
State 10-Fix Delivered, bug
Priority: 4-Low
Related Bugs 6624474 , 4954586
Submit Date 28-OCT-2003
Description




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 :
 customer  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) 
======================================================================
Work Around
N/A
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.

  xxxxx@xxxxx   2003-11-13
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang