Bug 68133 - [1.5] VerifyError: Code segment has wrong length in class file
Summary: [1.5] VerifyError: Code segment has wrong length in class file
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 3.1 M1   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-06-21 22:41 EDT by Igor Fedorenko CLA
Modified: 2005-01-11 11:03 EST (History)
0 users

See Also:


Attachments
classfile that has this problem (657 bytes, application/octet-stream)
2004-06-28 23:27 EDT, Igor Fedorenko CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Igor Fedorenko CLA 2004-06-21 22:41:21 EDT
I get "java.lang.ClassFormatError: Code segment has wrong length in class file"
when I compile/execute the following class

=================================
package test.cheetah;
import java.util.ArrayList;
public class CodeSegmentTest {
    public static void main(String[] args) {
        ArrayList<Object> l;
        switch (args.length) {
        case 1:
            l = new ArrayList<Object>();
            break;
        default:
            return;
        }
    }
}
=================================

The same code works fine when compiled/executed by javac/java.

Win2k SP4, Eclipse 200406192000, cheetah as of June 21st, 10:30pm EDT ;-), Sun
JDK 1.5.0 beta2. I use Sun JDK 1.4.2_04 to run eclipse itself.
Comment 1 Olivier Thomann CLA 2004-06-28 22:25:13 EDT
Could not reproduce with latest code in the 1.5 branch and the 1.5 b56.
Closing as WORKSFORME.
Please reopen if you get it again with a new cheetah drop.
Comment 2 Igor Fedorenko CLA 2004-06-28 23:26:21 EDT
This is still a problem with latest org.eclipse.jdt.core branch JDK_1_5. I have
verified this on two systems with SUN 1.5 beta2 and b57. 

Note that on both systems I have two eclipse workspaces. I checkout JDK_1_5
org.eclipse.jdt.core into one workspace and start second workspace using
"Run-time workbench" launch configuration. I do all 1.5 development in the
second workspace. The only compiler option that I changed is compiler compliance
level. I can provide you terminal services access to one of the machines if you
want, my ibm email is igorf at ca ibm com.
Comment 3 Igor Fedorenko CLA 2004-06-28 23:27:56 EDT
Created attachment 12874 [details]
classfile that has this problem
Comment 4 Olivier Thomann CLA 2004-06-29 04:15:59 EDT
I will continue to investigate.
Comment 5 Olivier Thomann CLA 2004-06-29 05:01:29 EDT
The bug occurs if I have -perserveAllLocals on the command line. If I don't, it
works fine.
Comment 6 Philipe Mulet CLA 2004-06-29 08:05:03 EDT
PreserveAllLocals isn't the offending, Problem is rather in debug attributes 
for local variables: '-g:vars'.

Offending entries are:

Local variable table:
...
[pc: 28, pc: 38] local: l index: 1 type: .../ArrayList;
[pc: 47, pc: 48] local: l index: 1 type: .../ArrayList;
Local variable type table:
[pc: 28, pc: 38] local: l index: 1 type: .../ArrayList<Ljava/lang/Object;>;
[pc: 47, pc: 48] local: l index: 1 type: .../ArrayList<Ljava/lang/Object;>;

where javac does generate:
Local variable table:
...
[pc: 28, pc: 48] local: l index: 1 type: .../ArrayList;
Local variable type table:
[pc: 28, pc: 48] local: l index: 1 type: .../ArrayList<Ljava/lang/Object;>;
Comment 7 Philipe Mulet CLA 2004-06-29 09:49:50 EDT
Based on our bytecode sequence, I believe our attribute are valid, and seem to 
be rejected by the VM.
The 'return' statement in default case is triggering this behavior, as we 
correctly infer that the second 'return' statement can only be reached through 
a path where the variable is definitely assigned. javac doesn't notice that in 
default case the variable loses its assignment state, and would thus 
incorrectly display it in debugger.

I suspect the one bytecode line number interval is not properly handled at VM 
level.

// Method descriptor  #15 ([Ljava/lang/String;)V
// Stack: 2, Locals: 2
public static void main(String[] args);
   0  aload_0
   1  arraylength
   2  tableswitch default: 38
        case 1: 20
  20  new #17 java/util/ArrayList
  23  dup
  24  invokespecial #18 <Method java/util/ArrayList.<init>()V>
  27  astore_1
  28  getstatic #24 <Field java/lang/System.out Ljava/io/PrintStream;>
  31  aload_1
  32  invokevirtual #30 <Method java/io/PrintStream.println(Ljava/lang/Object;)
  35  goto 47
  38  getstatic #24 <Field java/lang/System.out Ljava/io/PrintStream;>
  41  ldc #32 <String "SUCCESS">
  43  invokevirtual #35 <Method java/io/PrintStream.println(Ljava/lang/String;)
  46  return
  47  return
Comment 8 Philipe Mulet CLA 2004-06-29 09:55:37 EDT
Indeed, if adding a read access to variable 'l' in default case, javac 
correctly reports an error (variable may not have been initialized), thus it 
should not include this interval in the local variable attribute.
Comment 9 Philipe Mulet CLA 2004-06-29 10:02:18 EDT
Interestingly enough, the issue only occurs if using generics. Problem is thus 
located in VM reading of local variable type table (the new attribute for 
encoding generic type info about local variables).
Comment 10 Philipe Mulet CLA 2004-06-29 10:16:12 EDT
Actually, we shouldn't have more than one entry per local variable. It looks 
like it should span over the unitialized ranges?
Comment 11 Philipe Mulet CLA 2004-06-29 10:41:18 EDT
I take back my previous comment. Actually, on following code, javac generates 
2 entries.
Local variable table:
  [pc: 6, pc: 9] local: i index: 1 type: ...ArrayList;
  [pc: 0, pc: 18] local: args index: 0 type: [...String;
  [pc: 10, pc: 18] local: i index: 1 type: ..ArrayList;
Local variable type table:
  [pc: 6, pc: 9] local: i index: 1 type: ...ArrayList<Ljava/lang/Object;>;
  [pc: 10, pc: 18] local: i index: 1 type: ...ArrayList<Ljava/lang/Object;>;


public class X {
	public static void main(String[] args) {
		java.util.ArrayList<Object> i;	
		outer: {
			if (args == null) {
				i = null;
				break outer;
			}
			return;
		}
		System.out.println(i);	
	}
}
Comment 12 Philipe Mulet CLA 2004-06-29 10:44:14 EDT
When replacing last println statement with return, to cause last interval to 
be of size 1, it still works:

Local variable table:
  [pc: 6, pc: 9] local: i index: 1 type: Ljava/util/ArrayList;
  [pc: 0, pc: 11] local: args index: 0 type: [Ljava/lang/String;
  [pc: 10, pc: 11] local: i index: 1 type: Ljava/util/ArrayList;
Local variable type table:
  [pc: 6, pc: 9] local: i index: 1 type: ...ArrayList<Ljava/lang/Object;>;
  [pc: 10, pc: 11] local: i index: 1 type: ...ArrayList<Ljava/lang/Object;>;
Comment 13 Olivier Thomann CLA 2004-06-29 13:52:24 EDT
Fixed and released in HEAD.
Regression tests added.