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

Javac requires interface on classpath when using impl

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Not an Issue
    • Affects Version/s: 8u11
    • Fix Version/s: None
    • Component/s: tools
    • Labels:
    • Subcomponent:
    • CPU:
      x86_64
    • OS:
      linux_ubuntu

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_11"
      Java(TM) SE Runtime Environment (build 1.8.0_11-b12)
      Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Linux *** 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      With Java 8, when using a class, the interfaces it implements must be on the compile classpath as well. With Java 7, it was enough that the interface was on the classpath while compiling the used class.
      Given a jar api.jar containing an interface, and a jar api-impl.jar containing an implementation of the interface. While compiling source code that is dependent on the concrete implementation, you obviously need api-impl.jar on the classpath. With Java 8, additionally, you need to have api.jar on the classpath, even when you do not reference the API.

      REGRESSION. Last worked in version 7u65

      ADDITIONAL REGRESSION INFORMATION:
      java version "1.7.0_65"
      Java(TM) SE Runtime Environment (build 1.7.0_65-b17)
      Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create 3 folders, each with one java class:
      * api contains an interface class
      * api-impl contains an implementation of that interface
      * impl-consumer contains a class that uses the implementation explicitly (so without referencing the interface)

      Compile the API first, and make it into a jar.
      Then compile the api-impl, with the api.jar on the classpath, and make it into a jar too.
      Then compile the impl-consumer, with the api-impl.jar on the classpath.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      It would compile just fine, as there is not a single reference in the consumer code to the api.
      ACTUAL -
      Compilation fails with one error.


      astellin@cnl1478:/tmp/javac8$ chmod +x javacBug.sh
      astellin@cnl1478:/tmp/javac8$ ./javacBug.sh
      exit code: 0 when JAVA_HOME=/usr/lib/jvm/java-7-oracle
      astellin@cnl1478:/tmp/javac8$ export JAVA_HOME=/usr/lib/jvm/java-8-oracle/
      astellin@cnl1478:/tmp/javac8$ rm -r api/ api-impl/ impl-consumer/ api.jar api-impl.jar
      astellin@cnl1478:/tmp/javac8$ ./javacBug.sh
      Consumer.java:1: error: cannot access Interface
      public class Consumer { public void useImpl(Implementation i) { i.doNothing(); } }
                                                                       ^
        class file for Interface not found
      1 error
      exit code: 1 when JAVA_HOME=/usr/lib/jvm/java-8-oracle/

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Consumer.java:1: error: cannot access Interface
      public class Consumer { public void useImpl(Implementation i) { i.doNothing(); } }
                                                                       ^
        class file for Interface not found
      1 error

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      #!/bin/sh
      # In my example this file is on /tmp/javac8/javacBug.sh
      mkdir api api-impl impl-consumer
      echo "public interface Interface { void doNothing(); }" > api/Interface.java
      echo "public class Implementation implements Interface { public void doNothing() { } }" > api-impl/Implementation.java
      echo "public class Consumer { public void useImpl(Implementation i) { i.doNothing(); } }" > impl-consumer/Consumer.java
      cd api
      $JAVA_HOME/bin/javac Interface.java
      $JAVA_HOME/bin/jar cf ../api.jar Interface.class
      cd ../api-impl/
      $JAVA_HOME/bin/javac -classpath ../api.jar Implementation.java
      $JAVA_HOME/bin/jar cf ../api-impl.jar Implementation.class
      cd ../impl-consumer/
      $JAVA_HOME/bin/javac -classpath ../api-impl.jar Consumer.java
      echo "exit code: $? when JAVA_HOME=$JAVA_HOME"
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      If one has access to the jar containing the interface, one could include that in the compile classpath. But it's not a given that that jar is available always.

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: