United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6614974 javac successfully compiles code that throws java.lang.VerifyError when run
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

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



Hardware and Software, Engineered to Work Together