JDK-8005632 : Inner classes within lambdas cause build failures
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8-repo-lambda
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2013-01-02
  • Updated: 2013-11-12
  • Resolved: 2013-02-01
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.
JDK 8
8 b82Fixed
Related Reports
Relates :  
Description
With the original version of java.util.stream.ReferencePipeline, builds failed in the creation of 'make images'. 
The failure is with the compiler error:

Creating rt.jar
warning: package com.oracle.nio does not exist
Using boot class path = [/home/robert/work/lambda/lambda/build/linux-x86_64-normal-server-release/images/lib/rt.jar, /home/robert/work/lambda/lambda/build/linux-x86_64-normal-server-release/langtools/dist/bootstrap/lib/javac.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/resources.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/sunrsasign.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/jsse.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/jce.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/charsets.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/netx.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/plugin.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/rhino.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/jfr.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/classes, /home/robert/work/lambda/lambda/build/linux-x86_64-normal-server-release/jdk/classes, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/ext/dnsns.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/ext/sunjce_provider.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/ext/pulse-java.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/ext/localedata.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/ext/zipfs.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/ext/sunpkcs11.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/ext/sunec.jar, /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/ext/gnome-java-bridge.jar]
error: bad class file: /home/robert/work/lambda/lambda/build/linux-x86_64-normal-server-release/images/lib/rt.jar(java/util/stream/ReferencePipeline$1.class)
    bad enclosing method attribute for class java.util.stream.ReferencePipeline$1
    Please remove or make sure it appears in the correct subdirectory of the classpath.
1 error
1 warning

The error is generated in ClassReader.readEnclosingMethodAttr (since nt is null):

        NameAndType nt = (NameAndType)readPool(nextChar());
...
        MethodSymbol m = findMethod(nt, c.members_field, self.flags());
        if (nt != null && m == null)
            throw badClassFile("bad.enclosing.method", self);

On re-reading classfiles, the compiler does not enter synthetic members.  See this method from ClassReader:

    private void enterMember(ClassSymbol c, Symbol sym) {
        if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC)
            c.members_field.enter(sym);
    }

Lambda methods are SYNTHETIC.  Changing LambdaToMethod to remove the SYNTHETIC attribute, the build succeeds.


As a workaround to this issue, ReferencePipeline was changed. To reproduce, revert the filter() method of ReferencePipeline to:

    @Override
    public Stream<U> filter(Predicate<? super U> predicate) {
        Objects.requireNonNull(predicate);
        return pipeline(Ops.<U,U>chainedRef(StreamOpFlag.NOT_SIZED,
                                            (flags, sink) -> new Sink.ChainedReference<U>(sink) {
                                                @Override
                                                        public void accept(U u) {
                                                            if (predicate.test(u))
                                                                downstream.accept(u);
                                                        }
                                            }));
    }

and perform a 'make images' in the new build system.  The same failure will also occur in the old build system.

This is the lambda method bytecode in ReferencePipeline:

  private java.util.stream.Sink lambda$72(java.util.function.Predicate, int, java.util.stream.Sink);
    flags: ACC_PRIVATE, ACC_SYNTHETIC
    Code:
      stack=5, locals=4, args_size=4
         0: new           #61                 // class java/util/stream/ReferencePipeline$1
         3: dup          
         4: aload_0      
         5: aload_3      
         6: aload_1      
         7: invokespecial #62                 // Method java/util/stream/ReferencePipeline$1."<init>":(Ljava/util/stream/ReferencePipeline;Ljava/util/stream/Sink;Ljava/util/function/Predicate;)V
        10: areturn       
Comments
Unable to verify this bug as no test is included in the changeset. Filed JDK-8027116 to add a test for the bugfix. Will verify this bug once JDK-8027116 is completed.
22-10-2013

This was not fixed. There is a work-around in the JDK repo, so this isn't yet. But when that is removed, the error occurs. I'll take the bug.
01-02-2013