Let's say I'm using Java 11 javac
, but I'm using the --source
and --target
options set to 1.8
so that my source code will be considered Java 8 and the output .class
files will be compatible with Java 8. My goal is to produce .class
files that can run on a Java 8 JVM.
And let's say I have the following Java 8 code I'm compiling:
import java.nio.ByteBuffer;
…
ByteBuffer byteBuffer = …; //init somehow
byteBuffer.flip(); //what ends up in the `.class` file?
The question is: what should Java 11 javac
put in the .class
file to link the byteBuffer.flip()
method call? Before you answer, consider this:
- Neither Java 8
ByteBuffer
nor Java 11ByteBuffer
declare theflip()
method at theByteBuffer
level. ByteBuffer
is a direct subclass ofBuffer
. There is both a Java 8Buffer.flip()
and a Java 11Buffer.flip()
declared in theBuffer
API for both versions.- In the Java 8 source code, there is no
ByteBuffer.flip()
method. - But in the Java 11 source code,
ByteBuffer
overrides theBuffer.flip()
method like the following. The purpose apparently was to use covariance so that in Java 11ByteBuffer.flip()
would conveniently return aByteBuffer
instead of aBuffer
.@Override public ByteBuffer flip() { super.flip(); return this; }
So to restate the question: Should Java 11 javac
, with the --source
and --target
options set to 1.8
, generate a .class
file that links to Buffer.flip()
or to ByteBuffer.flip()
? If it is the former, then how does it know not to include ByteBuffer.flip()
instead, as the (Java 8) code clearly references ByteBuffer.flip()
and the (Java 11) compiler sees that there is a ByteBuffer.flip()
method in the runtime? But if it is the latter, then how can I ever know that my 100% correct Java 8 compatible source code, when compiled using Java 11, will run on a Java 8 JRE even if I use the --source
and --target
options to indicate Java 8? (Note that OpenJDK 11.0.5 seems to choose the latter option. But which is correct?)
(Note that I'm using the word "link" loosely; I'm not currently well-versed in what bytecode is generated. All I know is that the class file has come reference somehow to Buffer.flip()
or ByteBuffer.flip()
; and if this method can't be found at runtime, the JVM will throw an exception such as: java.lang.NoSuchMethodError: java.nio.ByteBuffer.flip()Ljava/nio/ByteBuffer;
.)
As a bonus question, I wonder whether using the --release
option set for Java 8 would change the answer. But note that I can't use the --release
option (equivalent to the Maven <release>
compiler plugin option) because I want my Maven project to be buildable with both Java 8 and Java 11.