Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8005632

Inner classes within lambdas cause build failures

    XMLWordPrintable

Details

    • b82
    • generic
    • generic
    • Not verified

    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

      Attachments

        Issue Links

          Activity

            People

              rfield Robert Field (Inactive)
              rfield Robert Field (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: