United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4381996 : Java Bytecode Verification impossible [2]

Details
Type:
Bug
Submit Date:
2000-10-23
Status:
Closed
Updated Date:
2010-11-23
Project Name:
JDK
Resolved Date:
2002-09-02
Component:
tools
OS:
solaris_7,generic,windows_2000
Sub-Component:
javac
CPU:
x86,generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.3.0,1.4.0
Fixed Versions:
1.4.2 (mantis)

Related Reports

Sub Tasks

Description

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.

 
http://java.sun.com/docs/books/jls/second_edition/html/defAssign.doc.html#26242

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

                                    

Comments
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
                                     
2002-07-08
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
                                     
2004-06-10
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


                                     
2004-06-14



Hardware and Software, Engineered to Work Together