JDK-4368664 : VerifyError when using array of arrays
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 1.2.2,1.3.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_98,windows_nt
  • CPU: x86
  • Submitted: 2000-09-06
  • Updated: 2002-11-07
  • Resolved: 2002-11-07
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
1.4.2 mantisFixed
Related Reports
Relates :  
Description

Name: tb29552			Date: 09/06/2000


/*
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

The "javac" compiler accept the following code, but "java" throws a VerifyError:

*/
public class ArrayTest {
    public static void main(final String[] args) {
    }

    private static void neverCalled() {
        float[][] channels = null;
        channels[0] = resize(channels[0]);
    }

    private static float[] resize(final float[] array) {
        return null;
    }
}
/*

When I try to run this code (with "java Test"), I get the following message:

Exception in thread "main" java.lang.VerifyError: (class: Test, method:
neverCalled signature: ()V) Incompatible types for storing into array of arrays
or objects

A work around is to replace "float[][] channels=null" by "float[][]
channels=float[0][]". The problem is that in my complete class, "channels" was
lazily created only when needed.

Thanks,

*/

(Review ID: 106837) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis FIXED IN: mantis INTEGRATED IN: mantis mantis-b07
2004-06-14

PUBLIC COMMENTS We expect to modify the verifier spec and implementation by JDK 1.5 so that this will not be an issue.
2004-06-10

EVALUATION Looks like a verifier issue. Both javac and oldjavac produce the same code for this example, which appears to be correct. Note that the code does attempt to subscript an array variable that contains null, which should result in an exception at runtime. The generated code is as follows: super public class ArrayTest { public Method "<init>":"()V" stack 1 locals 1 { aload_0; invokespecial Method java/lang/Object."<init>":"()V"; return; } public static Method main:"([Ljava/lang/String;)V" stack 0 locals 1 { return; } private static Method neverCalled:"()V" stack 4 locals 1 { aconst_null; astore_0; aload_0; iconst_0; aload_0; iconst_0; aaload; invokestatic Method resize:"([F)[F"; aastore; return; } private static Method resize:"([F)[F" stack 1 locals 1 { aconst_null; areturn; } } // end Class ArrayTest william.maddox@Eng 2000-10-24 ======================================================= This is not a verifier bug. The byte code in method neverCalled() as shown above has a type error in aastore. The compiled byte code has lost the declaration information in the source code. Therefore local variable 0 does not has [[F type. Instead, both local variable 0 and its value pushed on operand stack have null type. Their component types are null as well. After method 'resize' is invoked, the verifier pushes type [F (return type of 'resize') on the operand stack. Note that each method is verified separately. So method 'neverCalled' does not know that 'resize' returns null. It only knows that 'resize' returns [F from its signature. According to JVM Spec 2nd edition P. 176 (aastore), the top of current operand stack type (the return type of 'resize') must be assignment compatible with the type of the components of the array type on the third of operand stack (it is null here). Because type [F is not assignable to null, the verifier detects a type error. Another workaround is to assign resize(channels[0]) to another variable instead of channels[0], or directly assign null to channels[0] without calling resize. This bug will be closed as not a bug. ###@###.### 2001-7-10 I'm reopening this report, because our toolchain still doesn't function. Yes, the verifier is behaving as specified, but nevertheless a correct Java program fails to run. This is an unfortunate mismatch between the compikler (javac) and the verifier. I'm keeping this bug open until the program runs fine on the product. Note that it would be possible to "fix" the compiler by emitting casts into the code whenever null is used as a value of a multidimensional array type. ###@###.### 2002-09-26
2002-09-26

WORK AROUND Name: tb29552 Date: 09/06/2000 Do not use "float[][] x=null". Use "float[][] x=new float[0][]" instead. ====================================================================== An alternative workaround: Do not use "channels[0] = resize(channels[0]);". Use "float[] temp = resize(channels[0]);" or "channels[0] = null;" instead. ###@###.### 2001-7-10
2001-07-10