6

I'm reading section 4.10.2.2 of the specification for JVM version 8 (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html) how to verify bytecode. In this case what happens in control flow, when the stack now contains a slot with an int[] when coming from one source and a String[] when coming from another source.

I read the following, which was not present in the JVM versions 7 docs:

If corresponding values are both array reference types, then their dimensions are examined. If the array types have the same dimensions, then the merged value is a reference to an instance of an array type which is first common supertype of both array types. (If either or both of the array types has a primitive element type, then Object is used as the element type instead.)

...

Even int[] and String[] can be merged; the result is Object[], because Object is used instead of int when computing the first common supertype.

This does not make any sense to me, because that would mean that an int[] could be cast to an Object[]. But in Java arrays of primitive types cannot be cast to Object[].

Could anyone explain the rationale behind this?

Emil
  • 16,784
  • 2
  • 41
  • 52

1 Answers1

3

I am not sure why that language is in the specification, but it does not describe the way the JVM actually behaves (which makes sense, since as you pointed out, the described behavior is nonsense).

You can find the inference bytecode verifier source here, and it hasn't changed since 2013.

As an extra check, I created a test file that merges an int[] and a String[] and then stores a String in the result. As expected, I got a verification error (Java version 1.8.0_111).

Antimony
  • 37,781
  • 10
  • 100
  • 107
  • 1
    Perhaps copy&paste’d from the previous item, then screwed up while trying to adapt. I suppose, it should actually be “*Even int[][] and String[] can be merged; the result is Object[], because Object is used instead of int[] when computing the first common supertype*”… – Holger Sep 05 '17 at 17:32
  • @Holger That almost makes sense, but there's an error in the text above it as well. It says "If either or both of the array types has a primitive element type, then Object is used as the element type instead.". It should say that if one is primitive or both are different primitive types, then they are considered Object arrays *with one fewer dimension*. – Antimony Sep 05 '17 at 22:13
  • In the end, the three-sentence variant of the previous spec, saying that reference types are merged to the common super type was better than this. It’s not clear why this contradicting expansion was made, especially as this part is about the “Type inference verifier”, which applies to class files version 50 (Java 6) and below only. The rules for these legacy class files should not change in newer versions. – Holger Sep 06 '17 at 07:05