-
Bug
-
Resolution: Not an Issue
-
P3
-
None
-
8u11
-
x86_64
-
linux_ubuntu
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.
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.