I am required to compile my source code with Java 6 for university. I currently have Java 8 JDK installed on my PC (Linux). How do I compile in Java 6?
p.s. I understand I wont be able to use any Java 7 or 8 features.
p.p.s. I realize java 6 source code will compile fine using the Java 8 JDK however I find that I am accidentally using post Java 6 features in my programs when compiling at home. When I try to compile the source code on the lab computers at uni I run into a bunch of errors. e.g. not being able to cast an object to a primitive.
The way to fix that problem is to compile using the later SDK and use the cross compilation options when compiling.
Cross-Compilation Options
By default, classes are compiled against the bootstrap and extension classes of the platform that javac shipped with. But javac also supports cross-compiling, where classes are compiled against a bootstrap and extension classes of a different Java platform implementation. It is important to use the -bootclasspath and -extdirs options when cross-compiling.
-target version
Generates class files that target a specified release of the virtual machine. Class files will run on the specified target and on later releases, but not on earlier releases of the JVM. Valid targets are 1.1, 1.2, 1.3, 1.4, 1.5 (also 5), 1.6 (also 6), 1.7 (also 7), and 1.8 (also 8).
The default for the -target option depends on the value of the -source option:
If the -source option is not specified, then the value of the -target option is 1.8
If the -source option is 1.2, then the value of the -target option is 1.4
If the -source option is 1.3, then the value of the -target option is 1.4
If the -source option is 1.5, then the value of the -target option is 1.8
If the -source option is 1.6, then the value of the -target is option 1.8
If the -source option is 1.7, then the value of the -target is option 1.8
For all other values of the -source option, the value of the -target option is the value of the -source option.
-bootclasspath bootclasspath
Cross-compiles against the specified set of boot classes. As with the user class path, boot class path entries are separated by colons (:) and can be directories, JAR archives, or ZIP archives.
To use the options completely correctly (i.e. using also the -bootclasspath option) requires the rt.jar of a JRE (not JDK) of the target version.
You can use the below for compilation
% javac -target 1.6 <whatever you want to compile>
I had a similar issue where a part of the project wanted to use Java 6 and rest of the project needed Java 8. You can change java version in just one terminal window for this purpose.
To change the java version in just one terminal window without changing the profile, use:
export JAVA_HOME=$(/usr/libexec/java_home -v 1.6)
Related
I am posting this question as I have limited resources to test or confirm by my own.
Problem statement : I have an old custom Jar working with java 1.6. We don't have source code as well.
To fix one of the issue we updated 2 .class file of this jar using 7-zip.The code change was just to update the existing loggers with more meaningful messages.
These 2 .class file compiled with java 1.7.
Now the questions is whether this jar will work correctly with java 1.6 or will generate java version issue as 2 of the .class files are compiled with java 1.7.
Note - I know it's easy to test this rather then asking here but my test environment is only supporting java 1.8 and it's working perfectly but whether it will run with java 1.6 or not I can't test.
If you compile using: javac Foo.java where that javac is from a JDK1.7 installation, and you then attempt to run the class file that results on a JDK1.6, it will not work.
However, all you need to do is this:
javac -source 1.6 -target 1.6 Foo.java, and then it will, unless you used features from 1.7. If you use language features (I can't think of any, so I doubt it), it won't compile, and thus you know. If you use API, it will compile and you won't know. There is no easy solution to this other than compiling with JDK1.6 (or compiling with javac7 against a bootcp of JDK1.6, but you need to download and install a JDK1.6 to get that; might as well just use javac6 then).
Binary Compatibility
The class file version for Java SE 7 is 51, as per the JVM Specification, because of the invokedynamic byte code introduced by JSR 292. Version 51 class files produced by the Java SE 7 compiler cannot be used in Java SE 6.
Java SE 7 is binary-compatible with Java SE 6 except for the incompatibilities . Except for the noted incompatibilities, class files built with the Java SE 6 compiler will run correctly in Java SE 7.
Friends Words ...
The compiler is not backwards compatible because bytecode generated with Java7 JDK won't run in Java 1.6 jvm (unless compiled with the -target 1.6 flag). But the JVM is backwards compatible, as it can run older bytecodes.
So they chose to consider the compatibility from the point of view of javac (as it is the part specific to the JDK), meaning that the bytecode generated can be run in future releases of the jvm (that is more related to the JRE, but also bundled in the JDK).
In brief, we can say:
JDK's are (usually) forward compatible.
JRE's are (usually) backward compatible.
Java Says
Cross-Compilation Options
By default, classes are compiled against the bootstrap and extension classes of the platform that javac shipped with. But javac also supports cross-compiling, where classes are compiled against a bootstrap and extension classes of a different Java platform implementation. It is important to use -bootclasspath and -extdirs when cross-compiling; see Cross-Compilation Example below.
-target version
Generate class files that target a specified version of the VM. Class files will run on the specified target and on later versions, but not on earlier versions of the VM. Valid targets are 1.1, 1.2, 1.3, 1.4, 1.5 (also 5), 1.6 (also 6), and 1.7 (also 7).
The default for -target depends on the value of -source:
If -source is not specified, the value of -target is 1.7
If -source is 1.2, the value of -target is 1.4
If -source is 1.3, the value of -target is 1.4
If -source is 1.5, the value of -target is 1.7
If -source is 1.6, the value of -target is 1.7
For all other values of -source, the value of -target is the value of -source.
-bootclasspath bootclasspath
Cross-compile against the specified set of boot classes. As with the user class path, boot class path entries are separated by colons (:) and can be directories, JAR archives, or ZIP archives.
For More about Cross-Compilation look at
http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#crosscomp-options
Better than me at
http://www.oracle.com/technetwork/java/javase/compatibility-417013.html
The code base for Java 7 and versions of Java 6 is very similar and even shares many of the same bugs. e.g. the was a well known bug in Java 7 when it was released to do with loop optimisation and people suggested waiting for it to be fixed before migrating. The interesting thing was the bug was also in Java 6, the only difference was that the optimisation was on by default in Java 7 and off by default in Java 6.
Most of the performance improvements in Java 7 were back ported into Java 6.
Java 9's javac has a new flag --release:
> javac --help
...
--release <release>
Compile for a specific VM version. Supported targets: 6, 7, 8, 9
How is it different from -source and -target flags? Is it just a shortcut for -source X -target X?
Not exactly.
JEP 247: Compile for Older Platform Versions defines this new command-line option, --release:
We defined a new command-line option, --release, which automatically configures the compiler to produce class files that will link against an implementation of the given platform version. For the platforms predefined in javac, --release N is equivalent to -source N -target N -bootclasspath <bootclasspath-from-N>. (emphasis mine)
So no, it is not equivalent to -source N -target N. The reason for this addition is stated in the "Motivation" section:
javac provides two command line options, -source and -target, which can be used to select the version of the Java language accepted by the compiler and the version of the class files it produces, respectively. By default, however, javac compiles against the most-recent version of the platform APIs. The compiled program can therefore accidentally use APIs only available in the current version of the platform. Such programs cannot run on older versions of the platform, regardless of the values passed to the -source and -target. options. This is a long-term usability pain point, since users expect that by using these options they'll get class files that can run on the specified platform version.
In short, specifying the source and target options are not sufficient for cross-compilation. Because javac, by default, compiles against the most recent of the platform APIs, they can't be guaranteed to run on older versions. You also need to specify the -bootclasspath option corresponding to the older version to cross-compile correctly. This would include the correct API version to compile against and allow for execution on older version. Since it was very often forgotten, it was decided to add one command line option which did all the necessary things to correctly cross-compile.
Further reading in the mailing list and Oracle Docs. The original bug was filed here. Note that since the integration of this option, JDK builds have come bundled with descriptions of the platform APIs of older releases, mentioned under section "Risks and Assumptions". That means you don't need the older version installed on your machine for cross-compilation to work.
--release X is more than just a shortcut to -source X -target X because -source and -target are not sufficient to safely compile to an older release. You also need to set a -bootclasspath flag which must correspond to the older release (and this flag is often forgotten). So, in Java 9 they made a single --release flag which is a replacement for three flags: -source, -target and -bootclasspath.
So, this is an example of compiling to Java 1.7:
javac --release 7 <source files>
Note that you don't even need to have JDK 7 installed on your computer. JDK 9 already contains the needed information to prevent you from accidental linking to symbols that did not exist in JDK 7.
Another important difference is that you can only use public APIs when compiling with --release:
> javac --add-exports java.base/sun.invoke=ALL-UNNAMED --release 11 Main.java
error: exporting a package from system module java.base is not allowed with --release
1 error
If you want to use internal APIs, you have to remove the option --release:
> javac --add-exports java.base/sun.invoke=ALL-UNNAMED Main.java
or
> javac --add-exports java.base/sun.invoke=ALL-UNNAMED -source 11 -target 11 Main.java
Can a applet compiled with JDK 1.6(but not using any new features of 1.6) work on systems having JRE 1.5?
As others have mentions, you need -target 1.5 to generate 1.5 code. In order to use -target 1.5 you also need to set -source 1.5. Using any part of the 1.6 library that is not used in 1.5 will also cause a fail at run time, so use -bootclasspath to point to a 1.5 rt.jar. For completeness the "external directories" (libraries available to almost all code) should be set (probably to something empty) with, IIRC, -Dext.dirs.
No, the compiled code will require JRE 1.6 or later. JDK 1.6 will generate Java .class files with version 50.0 while 1.5 uses version 49.0.
Use javac -target 1.5 to generate .class files that JRE 1.5 can use. See http://docs.oracle.com/javase/6/docs/technotes/tools/windows/javac.html#options
If the code was compiled using compiler flag -target 1.6 (which is default for 1.6 JDK) - then it will not run on 1.5 JRE.
However, if the flag -target 1.5 was used - then it will work properly on 1.5 JRE.
I have installed many versions of the JDK: 1.4.2, 1.5 and 1.6.
How do I specify which version of the JDK is used when compiling using Ant?
Two solutions:
Specify the full path in your command:
for example /opt/java/jdk16/bin/javac ... on Linux
Use the -source and -target arguments of the javac command. This allows you specify the source code level and targeted JRE version
Also note:
Some Linux distributions can include tools to specify which JDK version to use by default.
Using -source and -target checkes that your language constructs are compliant with the targeted runtime, but does NOT check that core classes are compatible. This means that compiling with -source 1.4 on a JDK 1.6 will be just fine, even if you use String.isEmpty() which appeared in Java 6. This might lead to errors at runtime
javac -source 1.4 -target 1.4 YourFile.java
-source release
Specifies the version of source code accepted. The following
values for release are allowed:
1.3 the compiler does not support assertions, generics, or other
language features introduced after JDK 1.3.
1.4 the compiler accepts code containing assertions, which were
introduced in JDK 1.4.
1.5 the compiler accepts code containing generics and other
language features introduced in JDK 5. The compiler defaults to the
version 5 behavior if the -source flag is not used.
5 Synonym for 1.5
Here is the relevant documentation.
http://download.oracle.com/javase/1,5.0/docs/tooldocs/windows/javac.html
Use the Ant <javac> task<source> and/or <target> attributes. Valid values can be from 1.1 to 1.7, with 5, 6, and 7 valid aliases for 1.5, 1.6 and 1.7. Also, the <executable> attribute can be used to set which java javac compiler is used. For example:
<javac source="1.4" target="1.4" executable="c:\java1.6\bin\javac.exe"/>
I need to install JDK 5 for testing Amazon mechanical turk APIs (which is not fully compatible with JDK 6). On Apple's website, I can only find the latest JDK. Is there a way to get older versions of JDKs for Mac?
This hint might help :
10.6: Re-enable Java 1.4.2 and Java 1.5 apps in Snow Leopard
Yes, this is the problem with macs.
If you do backups, then you can just copy old folders containing jdk 5 from backup disk back to your machine. Worked for me.
use
-target 1.5
You can compile against the 1.5 jdk with settings in javac.
In your case :
javac -source 1.5 -target 1.5
You can even set this in your IDE. Or you can do this with maven and the maven.compile.target and maven.compile.properties
-source release
Specifies the version of source code accepted. The following values for release are allowed:
[...]
1.5
The compiler accepts code containing generics and other language features introduced in JDK 5.
[...]
-target version
Generate class files that target a specified version of the VM. Class files will run on the specified target and on later versions, but not on earlier versions of the VM. Valid targets are 1.1 1.2 1.3 1.4 1.5 (also 5) and 1.6 (also 6).
The default for -target depends on the value of -source:
If -source is not specified, the value of -target is 1.6
If -source is 1.2, the value of -target is 1.4
If -source is 1.3, the value of -target is 1.4
For all other values of -source, the value of -target is the value of -source.
Resources :
Javac 6 documentation
Maven - Setting the -source and -target of the Java Compiler