Java development kit 1.7 and earlier version compatibility - java

I am currently working on java 1.7 standard version, and I am really fun of the new features:
Nio(new input out put)
non redundant code with collections
...
I want to know if there is a way to switch the class I want to execute depending on the version of (JRE)java runtime environment it will be deployed.

You first need to create some sort of launcher app in order to check the JRE version of the environment, then you can lauch the JAR compiled for those version of the JRE. Your code cannot be compiled to newer versions of the JRE and be executed in an older one. That's why you need to complie the launcher app targeting a very old JRE.
As a side note, you can obtain the JRE version in which your program is running using:
System.getProperty("java.version")

The Java class file(s) are almost always binary compatible with new versions of the language (and the few exceptions, like using enum before the keyword was added, are fairly rare). If you restrict your usage of features to the "lowest common denominator" it is possible to compile back to an arbitrary version. That being said, Java 7 is now quite long in the tooth and I've found Java 8 to be remarkably stable. Finally, if you do choose to use new language features (like lambdas) you cannot use the earlier version of the language.

You can create two compiled build for both version to use language feature differently and have them running on jre 7, but you should just upgrade code compatibility and runtime to 1.8 (Even better)

Related

Java versions confusion

I want to install Java on a few different servers for running a third party service on tomcat.
I am not a Java developer and I got a bit confused when I began searching for the installer.
I checked the different Java versions and their long term support dates.
It seems that Java 11 JDK is - LTS so i decided to use it.
But when I was trying to find a runtime version (JRE?) since this is the version I am supposed to install on the server(?) I only found Java JRE 8.X.X, and this got me confused.
There is no higher major version of the JRE?
How does it work if you use the JDK 11 or even 14-15 as a developer and then use Java 8 JRE on your deployed servers?
Maybe the JDK holds inside of it the Java 8 JRE version?
Or do you actually need to install the JDK version on the servers instead?
The JRE is a subset of JDK. It contains everything needet to run Java applications but no support for development. So, if you need a JRE, a JDK is also good, although it conatins much stuff that you will not need.
Normally, for executing a Java application, you need a JRE with the same version or higher than the JDK used for development. But the developer can advise the compiler to generate code for a lower version. If he does so, he cannot use the features of the higher versions. For example the compiler of JDK 1.8 can produce code for JRE 1.6. You should consult the manual, to see which old versions are supported by the compiler of a specific version.
After some research,
It seems there is no separate JRE section anymore.
Also JDK 11 for production is not free and I guess this is an ongoing trend for the near future.
On a side note there is the open JDK 11 version but it does warn you about outdated security updates.
So basically in my case sticking to updated Java JRE 8 version is good enough for the near future.

Create Jar Compatible With Java 7 With IntelliJ Using JDK8

I am using JDK8 on my normal desktop and I have a separate linux box that I am trying to run the Java program on.
The problem I'm running into is that the linux box is running jdk7, so the computer has JRE7 basically that it is running off of. My question is, is it possible to create a jar file in JDK8 that will be compatible with java 7?
I'm using IntelliJ to compile. I tried to compile in 1.7, but it gave an error when I did end up trying to do it. I compile it here:
In 1.8 it works fine to compile, but when I try to compile in 1.7 it doesn't work.
I know the short answer is to update the linux to JRE 8. But I am curious, is there a way to make it backwards compatible? Or is the other answer to simply install JDK7 on the desktop in order for it to run on the linux box using JRE7?
Java programs built with JDK 8 will only run on machines running JRE 8 (or higher).
I found this when trying to compile classes on my local Linux machine (using JDK 8) and deploying to a remote server running JRE 7. The classes just wouldn't work (like you're finding).
If you want to use JRE 8 on linux, I recommend using the oracle-java8-installer package from webupd8team. Installation instructions found here (assuming Debian based distro).
If you want to compile to JDK 7, it's not good enough to only have JDK 8 installed and pick to compile 1.7. You need JDK 7 installed to and restage your project to use JDK 7.
The thing you have to remember is that the difference between JRE/JDK versions is not just the extra features developers can use (e.g Lambda functions) but it's also that the JRE itself is improved (efficiency, garbage collection, etc.).
As a extreme example: If you wrote code that only used JDK 1 features but compiled it using JDK 8, it wouldn't run on a machine running JRE 1 because the Java classes had been compiled with JRE 8 in mind.
Do note though, that if you're Java Code uses only features from JDK 7 or 6 etc., you might think it good practice to compile using the minimum JDK required to allow for compatibility with more machines. Well...you'd have that compatibility but at a cost of using inefficient, out of date, possibly vulnerable compiled classes (At little extreme, but you get my point).
Are you using any new Java 8 features? Because if you are, this means you cannot build the project against the JRE7.
If you are not using any Java 8 features, you can build to Java 7 most easily by downloading the JDK7 and switching the project to use that instead of the JDK8.
You should also set project language level to 1.7 (and module language level(s) as well, if they're different). It's done in Project Structure settings dialog. After that the project should compile.
Note that you shouldn't use any of the APIs that appeared in 1.8, but such usages will most likely be highlighted in the editor.

Eclipse/Java - JDK Compliance

This may seem a daft question so I will be as brief as possible.
Where I work, we deal with lots of Java apps that are compiled on old versions of Java, in fact we recently upgraded one of them to Java 1.6
We've been given new laptops recently with no admin rights and Java 7 installed by default.
I am presently unable to get hold of and install a copy of JDK 1.5 (which I need)
In Eclipse, if I set my JDK Compliance level to 1.5 but the Installed JRE is 1.7
Which of these 2 statements is true... ?
1. I am building my code at Java 1.5 ?
2. I am building my code at Java 7 ?
I've seen and spoken to various people on this subject and I am still non-the-wiser.
It means the byte code that is generated from your source code will be compliant to the 1.5 JRE.
The syntax highlighter will not allow you to do things that were new to 1.6, 1.7 such as switching on strings.
Developing with a JDK higher than the target platform is in principle possible, using the "compliance settings" and/or target version switches with javac.
Its however not practically feasible for doing real development, as nothing will prevent/warn you from using the API's present in your installed JDK but not in the target platform.
If, for example you develop for java 1.4 using an installed 1.5, while the compiler will not let you use autoboxing (which was introduced in 1.5), but it will happily let you use (for example) Integer.valueOf(int). Which is not present in 1.4.

Does the JDK version being used to compile the code matter?

In a conversation with someone else, they claimed that the version of JDK being used to compile the code does not matter vs. the JVM version being used to run the compiled code.
That seems strange to me - are there never instances where the JDK version matters? Is functionality always only dependent on the JVM the code is running on, and not on how the code is being compiled?
https://stackoverflow.com/a/19554706/2687324 talks about backwards compatibility. Is Java code also forwards compatible?
No, you can't necessarily run code compiled with a new JDK on an old JRE. Compiled classes contain a version number for the class file format; if this is newer than the runtime expects, it will refuse to load the class.
Most Java compilers support an option to target an older JRE, generating an older class file format than the compiler was built for. However, you can still run into trouble if you don't also compile against an older version of the Java runtime library. Your code might use new API that isn't in the older version of Java. The compiler, with its current version of the API, won't catch this even when you specify an older target.
For the standard javac compiler in OpenJDK, these options are -target and -bootclasspath. You might also want to set the -source option to catch usage of newer language features that require support the older class files don't provide.

JRE version must be equal to or above JDK version?

I've read that the bytecodes that the JDK generate are generic. What I say is that they only do things like memory mapping, calling, etc... So if that's true, it would mean that I can, for example, if write a program with characteristics of JDK 1.7, I don't need to worry about if it can run in a user with JRE 1.6? (It's an example, it could happen with more exagerated cases).
So, my question is: Can I write a program with new things from 1.7 and run it in 1.6?
Can I write a program with new things from 1.7 and run it in 1.6?
No. Java is not backward compatible.
Note that it is possible to create code compatible with a Java 1.6 JRE in a 1.7 JDK by using the cross-compilation options, but that code can only use the classes, attributes, methods and language features available in version 1.6.
Can I write a program with new things from 1.7 and run it in 1.6?
The short answer is yes, but it is not officially supported. You'll have to resort to some hacks, but you can get it to work if you really want to. I wouldn't recommend doing this in a major project though.
In general bytecode is not backwards compatible because each classfile contains a version field. The JVM will refuse to run classes with a higher version than it was built for (lower versions are of course ok). By default, the javac that comes with Java 7 will create classes with version 51.0, which means they can only be executed by the JVM that comes with Java 7 or higher.
However, this doesn't mean it's impossible if you really want to create Java 6 compatible code. You can tell the compiler to generate classfiles with an earlier version. All this means is that you won't be able to use library and bytecode level features introduced in the new version.
Luckily, version 51.0 did not actually introduce any new bytecode features used by javac. All of the new features in Java 7 are implemented at compile time - the bytecode isn't any different except for the version! This means that any Java 7 class can be made to work as long as it doesn't rely on standard library updates (for example Try With Resources requires library support).
Unfortunately, javac refuses to compile Java 7 to version 50.0. But you can always change the bytecode version field yourself, either manually or with a tool. Since there were no new bytecode features, it will work just fine.
P.S. Memory mapping is down by the VM. There's no bytecode instructions for it. But you have the right idea.

Categories