|
Quick Lists
|
|
Bug ID:
|
4368664
|
|
Votes
|
5
|
|
Synopsis
|
VerifyError when using array of arrays
|
|
Category
|
java:compiler
|
|
Reported Against
|
1.3
, 1.2.2
|
|
Release Fixed
|
1.4.2(mantis)
|
|
State
|
10-Fix Delivered,
bug
|
|
Priority:
|
4-Low
|
|
Related Bugs
|
4007663
,
4850079
|
|
Submit Date
|
06-SEP-2000
|
|
Description
|
/*
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)
======================================================================
|
|
Work Around
|
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.
xxxxx@xxxxx 2001-7-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
xxxxx@xxxxx 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.
xxxxx@xxxxx 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.
xxxxx@xxxxx 2002-09-26
|
|
Comments
|
Submitted On 29-SEP-2000
yougotit80
I want to know about sum of the arrays
Submitted On 24-SEP-2002
eblake
I disagree with the evaluation of this bug. The JVMS does not state that the component type of the null reference
is null, nor does it state that an arbitrary type is not assignable to a variable of type null (the only way you can get
a variable of null type is by accessing an array element of null).
Submitted On 27-SEP-2002
eblake
Make that - "I still claim that this is a verifier bug, not a JVMS bug"
Submitted On 27-SEP-2002
eblake
I still claim that this is not a verifier bug. Note that the
following are special cased:
((Object[]) null)[0] = "";
((int[]) null)[0] = 0;
In the first, the verifier sees aconst_null; iconst_0; ldc
""; aastore. But "" (Ljava/lang/String;) is most certainly
not assignment compatible to null, which you are claiming is
the element type of null.
And with the second, aconst_null; iconst_0; iastore; you are
special casing the fact that int is not assignable to the
element type of null. I think this should be fixed in
1.4.2, and not wait until 1.5 - the JVMS as it stands does
not seem to require the VerifyError that you claim it does.
Submitted On 25-SEP-2003
iabervon
In 1.4.2 (build 1.4.2-b28) I still get the VerifyError for
the following:
int positions[]; // (method argument)
Object prev[] = null;
Object posn = contents;
for (int i = 0; i < positions.length - 1; i++) {
if (posn == null) {
posn = new Object[sizes[i]];
prev[positions[i - 1]] = posn;
}
prev = (Object [])posn;
if (positions[i] == -1)
return;
posn = prev[positions[i]];
}
Changing the initializer of prev to new Object[0] works.
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |