Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 496862

Summary: .class file signature contains invalid exclamation point causing external tools (findbugs) to die
Product: [Eclipse Project] JDT Reporter: Frits Jalvingh <jal>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: CLOSED DUPLICATE QA Contact:
Severity: normal    
Priority: P3 CC: stephan.herrmann
Version: 4.5.1   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
Workspace that shows the problem none

Description Frits Jalvingh CLA 2016-06-27 13:10:02 EDT
Created attachment 262729 [details]
Workspace that shows the problem

The compiler seems to generate an invalid signature:

  #124 = Utf8               !+Lto/etc/other/IIdentifyable<Ljava/lang/Long;>;

which starts with an exclamation point. This caused problems with tools like FindBugs - which die on that. For some reason the class does not cause trouble in other ways- the JVM seems to be fine with it.

I extracted the code that causes this; the problem can be seen by looking at the byte code for the class "SavedRecordList" using javap -v -p

To reproduce: 
- untar the attachment
- start Eclipse and import projects
- wait for compile to finish
- use javap -v -p to decompile the class file.
Comment 1 Stephan Herrmann CLA 2016-06-28 07:11:11 EDT
Hi Frits,

what you are seeing is the "signature" of a wildcard capture.
JVMS 4.7.9.1. doesn't expect a capture in the byte code.

The offending entry in the byte code is:

  private static void lambda$0(java.util.List, to.etc.other.IIdentifyable);
    descriptor: (Ljava/util/List;Lto/etc/other/IIdentifyable;)V
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: invokeinterface #77,  1           // InterfaceMethod to/etc/other/IIdentifyable.ge
tId:()Ljava/lang/Object;
         7: checkcast     #83                 // class java/lang/Long
        10: invokeinterface #119,  2          // InterfaceMethod java/util/List.add:(Ljava/lan
g/Object;)Z
        15: return
      LineNumberTable:
        line 28: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      16     1     a   Lto/etc/other/IIdentifyable;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            0      16     1     a   !+Lto/etc/other/IIdentifyable<Ljava/lang/Long;>;


Read: the lambda expression inside set(List<? extends IIdentifyable<Long>>) has a local variable, who's generic type is a capture.

Now we have a problem: we need to record the type of the local variable in the LocalVariableTypeTable but JVMS doesn't tell us how to encode the capture, bummer!

*** This bug has been marked as a duplicate of bug 494198 ***
Comment 2 Frits Jalvingh CLA 2016-07-06 08:03:18 EDT
Thanks, Stephan, for the detailed explanation in the bugs and on stackoverflow. I did try to find those before I reported the bug, but sadly enough the stackoverflow article would be unfindable using exclamation point/mark ;)

I did circumvent the issue in FindBugs; I'll try to send the fix to that project.