JDK-4381996 : Java Bytecode Verification impossible [2]
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 1.3.0,1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,solaris_7,windows_2000
  • CPU: generic,x86
  • Submitted: 2000-10-23
  • Updated: 2010-11-23
  • Resolved: 2002-09-02
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.
1.4.2 mantisFixed

Name: skT45625			Date: 10/23/2000

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

The following legal Java program is rejected by any Java Bytecode
verifier I have tried. The program shows that Java Bytecode Verification
is not possible as described in the Java Virtual Machine Specification.

Remark: The example program shows a different problem than in my
previous bug report. There are no "break" statements and labels involved
in this program.

public class Test {
  int test(boolean b) {
    int i;
    try {
      if (b) return 1;
      i = 2;
    } finally {
      if (b) i = 3;
    return i;

tomis> java -version
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0)
Java HotSpot(TM) Client VM (build 1.3.0, mixed mode)
tomis> javac Test.java
tomis> java Test
Exception in thread "main" java.lang.VerifyError: (class: Test, method: test
signature: (Z)I) Register 2 contains wrong type

What is the problem? The variable i is modified by the subroutine S
corresponding to the finally block. The variable i, however, is
"unusable" at the end of S, since S is called before the "return 1" and
after the try block. When S is called before the "return 1" variable i
is "unusable" and it remains "unusable", since there is a path from the
beginning to the end of S which does not have an "istore i"
instruction. Hence, at the of the try block, the variable "i" is
unusable in the eyes of the bytecode verifier and therefore also at the
end of the method at the "return i" instruction.

Solution? Restrict the "rules of definite assignment" in the JLS for
16.2.14 "try statement" such that the above program is no longer legal.


  V is definitely assigned after the try statement iff the following
  is true:
     V is definitely assigned after the finally block.
(Review ID: 111235) 

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis mantis-b02 FIXED IN: mantis mantis-b02 INTEGRATED IN: mantis mantis-b02 VERIFIED IN: mantis

PUBLIC COMMENTS javac no longer generates the jsr instruction, instead inlining the finally clause. Consequently, code with deeply nested try-finally blocks may generate more byte code than before. In the extreme case, synthetic Java source code that deeply nests try-finally blocks may generate more bytecode in a single method than can be expressed in the bytecode file format, even though such code used to compile without problems. This particular problem may be seen in some JSP implementations. In general, you should avoid the try-finally language construct in synthetic Java source code. If you do run into this problem but you cannot modify the generator of your synthetic code, you can use the following flag to cause javac to once again generate jsr instructions for try-finally blocks -XDjsrlimit=0

EVALUATION I believe this is true. gilad.bracha@eng 2000-12-04 I believe these two bugs are caused by the interaction of jsr generated by javac and the verifier. In a sense, they are compiler bugs and not spec bugs because we could fix these problems by not using jsr. We are considering a new verifier scheme for 1.5 that would require the compiler to stop generating jsr. See also 4494152. ###@###.### 2002-01-17 The Mantis (1.4.2) javac compiler avoids using jsr instructions most of the time. This test case will not fail in Mantis, though with some effort one could construct a test case that does. ###@###.### 2002-07-08 Yes, compilers may choose not to generate jsrs (or generate them only in simple cases). I would encourage compilers to stop the use of jsrs altogether. Future versions of the class file format may deprecate jsrs. So I am reclassifying this as a compiler bug. ###@###.### 2002-07-08