United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6614974 : javac successfully compiles code that throws java.lang.VerifyError when run

Details
Type:
Bug
Submit Date:
2007-10-10
Status:
Closed
Updated Date:
2011-09-20
Project Name:
JDK
Resolved Date:
2011-05-18
Component:
tools
OS:
linux,windows_xp
Sub-Component:
javac
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
6,6u26
Fixed Versions:

Related Reports
Duplicate:
Relates:

Sub Tasks

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
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
SUGGESTED FIX

http://sa.sfbay.sun.com/projects/langtools_data/7/6614974/
                                     
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



Hardware and Software, Engineered to Work Together