Bug 16279 - compiler creates code that causes verifier error
Summary: compiler creates code that causes verifier error
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P3 critical (vote)
Target Milestone: 2.0 F2   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 19916 (view as bug list)
Depends on:
Blocks:
 
Reported: 2002-05-17 12:56 EDT by Marc Schier CLA
Modified: 2002-06-12 05:42 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marc Schier CLA 2002-05-17 12:56:37 EDT
I am using the Jakarta Avalon open source project.  I checked out jakarta-
avalon-excalibur from the apache cvs tree, mounted all source folders in the 
project and imported the necessary libraries.  

I have a class that needs to use the 
org/apache/excalibur/fortress/util/ContextManager class.  When I try to run my 
class or the unit test class 
org.apache.excalibur.fortress.test.ContainerProfile.java (any class that needs 
the ContextManager) I get the following Exception trace:

java.lang.VerifyError: (class: 
org/apache/excalibur/fortress/util/ContextManager, method: 
initializeLoggerManager signature: ()V) Register 2 contains wrong type
	at 
org.apache.excalibur.fortress.test.ContainerProfile.testCompare_ECM_ContainerMan
ager_UseageTime(ContainerProfile.java:106)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at junit.framework.TestCase.runTest(TestCase.java:166)
	at junit.framework.TestCase.runBare(TestCase.java:140)
	at junit.framework.TestResult$1.protect(TestResult.java:106)
	at junit.framework.TestResult.runProtected(TestResult.java:124)
	at junit.framework.TestResult.run(TestResult.java:109)
	at junit.framework.TestCase.run(TestCase.java:131)
	at junit.framework.TestSuite.runTest(TestSuite.java:173)
	at junit.framework.TestSuite.run(TestSuite.java:168)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:319)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run
(RemoteTestRunner.java:215)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main
(RemoteTestRunner.java:150)

When running the excalibur build file using ant and the jdk1.4 compiler and 
then import the generated jar everything seems to work ok,  so I attribute the 
error to the eclipse compiler.  I also tried to change the order of the class 
path, which didn't help.

I am running latest stable build M5 on Win2k and jdk1.4.  The compiler 
compatibility settings are set to jdk1.4.
Comment 1 Philipe Mulet CLA 2002-05-18 05:09:14 EDT
Could you provide the offending unit source for debug purpose ?
Comment 2 Olivier Thomann CLA 2002-05-21 16:06:14 EDT
Here is a simpler test case:
public class Test16279 {

	Logger logger;

	public static 
void main(String[] args) {
	}

	public void foo() {
		try 
{
			System.out.println();
		} catch (Exception ce) {
			String s = null;
			try 
{
				return;
			} catch (Exception ex) {
			}

			s.hashCode();
		} finally 
{
			if (this.logger == null) {
				LoggerManager loggerManager = 
null;
			}
		}
	}
}

The J9 doesn't complain even if you add -verify. Any JDK fails 
with:
Exception in thread "main" java.lang.VerifyError: (class: Test16279, method: foo 
signature: ()V) Register 2 contains wrong type.

It seems to be related to the subroutine code 
generation. For the above code, our bytecodes are:
Method void foo()
   0 getstatic #26 <Field 
java.io.PrintStream out>
   3 invokevirtual #31 <Method void println()>
   6 goto 31
   9 
astore_1
  10 aconst_null
  11 astore_2
  12 jsr 37
  15 return
  16 astore_3
  17 aload_2   <==== 
This seems to be the problem
  18 invokevirtual #37 <Method int hashCode()>
  21 pop
  22 goto 
31
  25 astore_1
  26 jsr 37
  29 aload_1
  30 athrow
  31 jsr 37
  34 goto 50
  37 astore 4
  39 
aload_0
  40 getfield #39 <Field Logger logger>
  43 ifnonnull 48
  46 aconst_null
  47 
astore_2 <==== This seems to be the problem
  48 ret 4
  50 return
Exception table:
   from   to  
target type
     0     9     9   <Class java.lang.Exception>
    12    16    16   <Class java.lang.Exception>
     0    22    25   
any

The first attempt we can do in order to fix the problem is to avoid reusing the same slot 
between the first catch block and the finally block.
Javac produces the following 
bytecodes:
Method void foo()
   0 getstatic #2 <Field java.io.PrintStream out>
   3 
invokevirtual #3 <Method void println()>
   6 jsr 42
   9 goto 56
  12 astore_1
  13 aconst_null
  
14 astore_2
  15 jsr 42
  18 return
  19 astore_3
  20 goto 23
  23 aload_2
  24 invokevirtual #5 
<Method int hashCode()>
  27 pop
  28 jsr 42
  31 goto 56
  34 astore 4
  36 jsr 42
  39 aload 4
  41 
athrow
  42 astore 5
  44 aload_0
  45 getfield #6 <Field Logger logger>
  48 ifnonnull 54
  51 
aconst_null
  52 astore 6
  54 ret 5
  56 return
Exception table:
   from   to  target type
     0     6    12   
<Class java.lang.Exception>
     0     9    34   any
    12    18    34   any
    19    31    34   any
    34    39    34   any

We can see 
that they never reuse any register for the locals. I will investigate this solution.
Comment 3 Olivier Thomann CLA 2002-05-21 16:28:36 EDT
Jikes 1.15 compiles in a similar way we do compare to javac, but it doesn't reuse the same slots for 
the locals:
Method void foo()
   0 getstatic #21 <Field java.io.PrintStream out>
   3 
invokevirtual #26 <Method void println()>
   6 jsr 41
   9 goto 53
  12 astore 4
  14 aconst_null
  
15 astore 5
  17 jsr 41
  20 return
  21 astore 6
  23 aload 5
  25 invokevirtual #34 <Method int 
hashCode()>
  28 pop
  29 jsr 41
  32 goto 53
  35 astore_1
  36 jsr 41
  39 aload_1
  40 athrow
  
41 astore_2
  42 aload_0
  43 getfield #38 <Field Logger logger>
  46 ifnonnull 51
  49 
aconst_null
  50 astore_3
  51 ret 2
  53 return
Exception table:
   from   to  target type
    17    21    
21   <Class java.lang.RuntimeException>
     0     6    12   <Class java.lang.RuntimeException>
     0    29    35   
any

I am not sure this is not a bug in the bytecode verifier. If you remove the latest if in the 
source code, then you can run the code fine. Anyway we have to fix this problem, because any JDK will 
fail running the code compiled by Eclipse.
Comment 4 Philipe Mulet CLA 2002-05-22 07:40:27 EDT
The finally block needs to be shifted behind try and catch blocks for local 
variable allocation. We did shift against the try block, and missed the catch 
blocks shifting.

Fixed
Comment 5 Olivier Thomann CLA 2002-05-22 11:43:29 EDT
Verified. The source can now compile fine.
Comment 6 Olivier Thomann CLA 2002-06-03 14:19:28 EDT
Verified in F2.
Comment 7 Olivier Thomann CLA 2002-06-03 14:19:41 EDT
Verified.
Comment 8 Philipe Mulet CLA 2002-06-12 05:42:02 EDT
*** Bug 19916 has been marked as a duplicate of this bug. ***