JDK-6614974 : javac successfully compiles code that throws java.lang.VerifyError when run
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6,6u26
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux,windows_xp
  • CPU: x86
  • Submitted: 2007-10-10
  • Updated: 2011-09-20
  • Resolved: 2011-05-18
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 Availabitlity Release.

To download the current JDK release, click here.
JDK 7
7 b25Fixed
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b06)
Java HotSpot(TM) Client VM (build 1.6.0_02-b06, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
The following code compiles successfully with javac:

public class BugReport<T> {

	private T n;

	public void error() {
		BugReport<Integer> val = new BugReport<Integer>();
		val.n = 0;
		Integer.toString(val.n++);
	}

	public static void main(String[] args) {
		BugReport.class.getMethods();
	}
}

However, when run with `java BugReport', it always throws the following error:

Exception in thread "main" java.lang.VerifyError: (class: BugReport, method: error signature: ()V) Incompatible object argument for function call

This is likely due to the generics/autoboxing combination that fails in this case at the line Integer.toString(val.n++).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the code from the description and run it.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No error.
ACTUAL -
This error:

Exception in thread "main" java.lang.VerifyError: (class: BugReport, method: error signature: ()V) Incompatible object argument for function call

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.VerifyError: (class: BugReport, method: error signature: ()V) Incompatible object argument for function call

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class BugReport<T> {

	private T n;

	public void error() {
		BugReport<Integer> val = new BugReport<Integer>();
		val.n = 0;
		Integer.toString(val.n++);
	}

	public static void main(String[] args) {
		BugReport.class.getMethods();
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
val.n++ can be moved out of the method call and the call itself can be changed to Integer.toString(val.n).

Comments
SUGGESTED FIX http://sa.sfbay.sun.com/projects/langtools_data/7/6614974/
2008-02-11

EVALUATION Autoboxing is implemented by javac by means of LetExpr nodes of AST of the kind let int v = i.intValue in ...; //where i is a variable whose type is Integer However, when the compiler generates those LetExpr nodes, a synthetic cast should be added if the type of the right handed expression is a type variable as described in the example: let int v = n.intValue() in v++ ...; Here, since n is of type T, a type variable whose bound is Object. Since no synthetic cast is added by the compiler, the LetExpr flows into the compiler pipeline, thus causing bad code to be generated since T is erased to Object and Object does not define a method intValue(). The solution to the problem is to force an explicit type conversion to the actual type of T (which is known at compile-time) so that the LetExpr node is generated as follows: let int v = ((Integer)n).intValue() in v++ ...;
2008-02-11

EVALUATION Cast from Object to Integer is missing before pc=46. public void error(); Code: 0: new #2; //class BugReport 3: dup 4: invokespecial #3; //Method "<init>":()V 7: astore_1 8: aload_1 9: iconst_0 10: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 13: putfield #5; //Field n:Ljava/lang/Object; 16: aload_1 17: astore_2 18: aload_2 19: getfield #5; //Field n:Ljava/lang/Object; 22: astore_3 23: aload_2 24: aload_2 25: getfield #5; //Field n:Ljava/lang/Object; 28: checkcast #6; //class java/lang/Integer 31: invokevirtual #7; //Method java/lang/Integer.intValue:()I 34: iconst_1 35: iadd 36: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 39: dup_x1 40: putfield #5; //Field n:Ljava/lang/Object; 43: astore 4 45: aload_3 *** aload_3 loads raw type val.n; *** need checkcast #6 // class java/lang/Integer 46: invokevirtual #7; //Method java/lang/Integer.intValue:()I 49: invokestatic #8; //Method java/lang/Integer.toString:(I)Ljava/lang/String; 52: pop 53: return
2008-01-04