Can newer JRE versions run Java programs compiled with older JDK versions? - java

Would I encounter any problems running Java programs and associated libraries compiled in Java version 1.6 and 1.7 (I'm compiling using 1.7 whereas some libraries are compiled using 1.6) and running the entire program in a 1.7 JRE?

As answered already you are mostly safe and most products and 3rd party libraries will simply work. However there do exist very rare cases where binary incompatibilities (ones where the class file compiled using older JDK will fail to run in the newer JVM) were introduced between JDK versions.
Official list of Oracle Java incompatibilities between versions:
in Java SE 9 since Java SE 8
in Java SE 8 since Java SE 7
in Java SE 7 since Java SE 6
in Java SE 6 since Java SE 5.0
in Java SE 5.0 since Java SE 1.4.2
Compatibility tool
Packaged with JDK 9, there is a tool called jdeprscan which will verify the compatibility, list no longer used APIs within your code and suggest alternatives(!). You can specify the target JDK version (works for JDK 9, 8, 7 and 6) and it will list incompatibilities specific to your target version.
Additional comment in case of libraries:
A reasonable rule of thumb is to use latest stable release version of library for the JRE version your software targets. Obviously you will find many exceptions from this rule, but in general stability of publicly available libraries usually increases with time.
Naturally API compatibility and versioning have to be considered when changing versions of dependencies.
Again most popular dependencies will have web pages where such information should be available.
If however you are using something a bit more obscure, you can discern which JRE were the classes within your dependency compiled for.
Here is a great answer on how to find out class version. You might need to unzip the JAR file first.

You would not encounter any problems - that's the magic of Java -it's backwards compatible.You can run almost all code from Java 1 on Java 8. There's no reason why Java 6 code won't run on a Java 8 Runtime.
What is interesting, is that for applications written in, let's say, Java 1.4, you even have speed increases when running them on later runtimes. This is because Java is constantly evolving, not just the language known as "Java", but also the JVM (Java virtual machine). I still have source code from more than 10 years ago that still work, as expected in the latest JVM.
If you want to target, let's say, a Java 5 VM, then you can do that with the Java 8 SDK tools. You can ultimately specify which target VM you wish to support, as long as you bear in mind that a version 5 VM might not support all the features a version 8 VM will.
I've just tested code I wrote in Java 5 against the new Java 8 runtime and everything works as expected, so, even though we have a more powerful language and runtime now, we can continue to use our investments of the past. Just that alone makes Java a great development choice for companies.

Related

Do libraries written in a new version of Java work with older versions of Java? [duplicate]

Backward binary compatibility (or downward compatibility) - an ability of clients built with an old version of library API to run on a new one (wiki).
Upward binary compatibility (or forward compatibility) - an ability of clients built with a new version of library API to run on old one (wiki).
The general Sun's document about JDK Incompatibilities in J2SE 5.0 since 1.4.2 (and Java SE 6 compatibility with J2SE 5.0 too) describes the compatibility of JDK as following:
JDK 5.0 is upwards binary-compatible with Java 2 SDK, v1.4.2 except for the incompatibilities listed below. This means that, except for the noted incompatibilities, class files built with version 1.4.2 compilers will run correctly in JDK 5.0.
I suppose that documentation writers have mixed up terms "upward" and "backward" compatibility in this sentence. They describe a "backward" compatibility, but call this feature as "upward" compatibility.
Is this a typo, mistake or intended term here?
Is JDK "upward" or "backward" compatible?
Note that for something to be backwards compatible there must be a counterpart that is forwards compatible (either intentionally or unintentionally). For example: are the DVD readers backwards compatible with CD's or are the CD's forward compatible with DVD readers?
In this case, it depends if you look at the compiler (or the bytecode it generates) or the virtual machine.
The compiler is not backwards compatible because bytecode generated with Java5 JDK won't run in Java 1.4 jvm (unless compiled with the -target 1.4 flag). But the JVM is backwards compatible, as it can run older bytecodes.
So I guess 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.
(And it also serves as a lesson that should be learnt long ago: the people writing the compilers are usually right, and we the people using them wrong xD)
By the way, doesn't it make more sense to pair backward/forward and downward/upward rather than mixing them up?
Extending answers to include the most recent Java …
Java SE 7 and JDK 7 Compatibility
Quotes from Oracle's undated page:
Compatibility is a complex issue. This document discusses three types
of potential incompatibilities relating to a release of the Java
platform:
Source: Source compatibility concerns translating Java source code into class files including whether or not code still compiles at
all.
Binary: Binary compatibility is defined in The Java Language Specification as preserving the ability to link without error.
Behavioral: Behavioral compatibility includes the semantics of the code that is executed at runtime.
… and
Incompatibilities between Java SE 7 and Java SE 6 Java SE 7 is strongly compatible with previous versions of the Java platform.
Almost all existing programs should run on Java SE 7 without
modification. However, there are some minor potential source and
binary incompatibilities in the JRE and JDK that involve rare
circumstances and "corner cases" that are documented here for
completeness.
Java SE 7 Incompatibilities in the Language, the JVM, or the Java SE API
… and
Incompatibilities between JDK 7 and JDK 6
JDK 7 Incompatibilities in javac, in HotSpot, or Java SE API
(No preamble there – just a list of incompatibilities.)
Backward only. Forward compat ("gracefully accept input intended for later versions of itself") would require the 1.5 JVM to be able to run 1.6 compiled code, which it can't.
Backward requires "if it can work with input generated by an older device" which is true as a 1.6 JVM can run 1.5 compiled code.
Each release of the JDK/JRE coincides with a version of Java bytecode. Each compiler produces code of a specific bytecode version. Each JVM understands a version and all earlier versions of a specific bytecode version.
When the JVM loads a class it checks the bytecode version and if it is > than the JVMs latest understood version you'll get an Error. (ClassVersionError or something).
Java (VM) is Backward compatible. Code built by java 1.4.2 will run on 1.5 & 6 VM's. The JDK compiler is not backward compatible. So code cannot be compiled by java 1.5 to run on 1.4.2 for example.
JDK is Backward compatible, i.e. Byte Code that complies to 1.4.2 spec will run on Java 5 JVM
JDK is downwards compatible as per the definition from wiki.
It should be backward compatible.
jdk is upward compatible - new version can run on old one

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.

Scala + OpenJFX + OpenJDK

I am about to start a new GUI project utilizing Scala and JavaFX/OpenJFX.
Last time I was involved Java 8 was state-of-the-art, JavaFX was integrated with both JDK and JRE and Scala used JDK 8 for building, Jigsaw was not there and Oracle provided (free) (bug) fixes almost forever.
Now, a few years later, things have changed rather dramatically: Java 11+ is what we are supposed to use, JavaFX has been unbundled and its development is continued as OpenJFX (more or less) independently to Java, Jigsaw is there and Oracle forces the users to upgrade their environment every 6 months.
That changes would not be too bad if it wasn't for the fact that Scala still seems to operate on JDK 8, OpenJDK builds do not include JavaFX, and AFAIR, OpenJFX is not available to Java version prior to Java 11.
All that leads me to the question: What tool stack would one use to implement a Scala application using JavaFX/OpenJFX as GUI toolkit?
Is it safe to use Scala with JDK (not JRE!) 11+?
Oracle forces the users to upgrade their environment every 6 months.
As noted in the comments, this is not true. You can still use JDK 8 even. If you want Oracle LTS, use Java 11. There are other companies that give LTS to other OpenJDK versions (RedHat JDK, Azure JDK...). Mark Reinhold (Chief Java Architect) explained this many times in his talks (1, 2 or any of his talks that he has repeated 3 times a year for the last 2 years).
What tool stack would one use to implement a Scala application using JavaFX/OpenJFX as GUI toolkit?
I'm not a Scala developer, but use whatever latest OpenJDK build Scala allows you to, and depending on if and what support you need, whichever OpenJDK version is supported. I'm willing to bet OpenJDK 11 will answer all your needs.
JavaFX has been removed from the Oracle JDK, but was never bundled in OpenJDK JDK1. You can easily bundle OpenJFX2 as a dependency when using OpenJDK, either as external JARs or through a dependency manager (Gradle, Maven...). The JavaFX/OpenJFX website is https://openjfx.io and contains instructions on how to do it.
JavaFX/OpenJFX versions are released in parallel (more or less) to the JDKs and supports 1 versions back of OpenJDK (OpenJFX N supports JDK N-1 and JDK N, and maybe JDK N-2...). So, if you use OpenJDK 11, you can use OpenJFX 11 or 12. OpenJFX 13+ could work, but it is not guaranteed.
Is it safe to use Scala with JDK (not JRE!) 11+?
If your Scala version supports it, OpenJDK 11+ and OpenJFX 11+ are safe. Note that the JRE has been removed from the JDK, so it's irrelevant.
1 OpenJDK JDK is the right way to refer to it, like Oracle JDK, but most people just use OpenJDK.
2 OpenJFX is to JavaFX what OpenJDK JDK is to Oracle JDK, but OpenJFX and JavaFX are used interchangeably since there's no real difference.

Compiling web app against Java 5, but String.isEmpty() is still being allowed?

I am compiling my web app in Netbeans against Java EE 5. I know that the String.isEmpty() function is only supported in Java 6. Having said that, I can still compile my project using the .isEmpty() in my code.
How come Netbeans is allowing my web app to compile if I am compiling against Java EE 5?
The compiler level is not equal to the JDK level you use for compiling. The compiler level only checks for the syntax and of course creates a different output. But the compiler itself will use the jdk on your classpath so if you compiled with java 5 option but with the java 6 jars on your classpath the code will compile without an error.
You should check your classpath.
As many have pointed out, Java EE versions are not strictly tied with Java SE (JDK) versions. Mostly, they require a minimal Java SE version but are compatible with later versions.
Java EE 5 specification (downloadable PDF here) says:
This specification requires that containers provide a Java Compatible™ runtime
environment, as defined by the Java 2 Platform, Standard Edition, v5.0 specification
(J2SE)
Since JSE versions are backwards compatible, you can take a container compatible with Java 5 and run it on top of Java SE 6 or Java SE 7.
You can check the compatibility level that Netbeans is using by checking the project "Properties > Source > Source/Binary Format"
If you still have doubts about "Java vs Java EE" you can look for several questions here on SO about the difference between Java SE and Java EE.

Has the Java language maintained source-code backward compatibility throughout its history?

Has Java always maintained source-code backward compatibility during its development?
More precisely: given two Java versions X and Y with X < Y, is any program for Java X also a valid program for Java Y, with the same semantics?
E.g. X = Java 2 (or 1.2 with the old numbering) and Y = Java 5.
Or is there only compatibility at the JVM level: e.g. a class compiled for the JVM 1.2 can be run by the JVM 5?
If it is possible to run Java 2 code on a Java 5 (or 6, or 7), what are the exact steps that I have to follow? Compile directly with a Java 5 compiler? Compile with a Java 2 compiler and run on JVM 5?
Sun, and now Oracle, have always been extremely careful with backward compatibility with regards to Java.
Binary compatibility: You should be able to run Java code compiled with older versions on newer versions without modification. There might, however, be small incompatibilities.
Source compatibility: Code originally written for an older JDK version should almost always compile without modification with a newer Java compiler, but there are a number of small incompatibilities. One of them is the enum keyword added in Java 5; on older versions of Java, enum was a valid identifier, but not on Java 5. Also, importing classes from the default package has been removed (I think since Java 1.4). So you can't do:
import SomeClassName;
anymore on Java 1.4 or newer.
In the documentation of every JDK release there is a document about backward compatibility with previous releases, which lists the details.
Java SE 7 and JDK 7 Compatibility
Java SE 6 Compatibility
Incompatibilities in J2SE 5.0 (since 1.4.2)
Java 2 Platform, Standard Edition Version 1.4.0 Compatibility with Previous Releases
Starting witg Java 1.5 enum became a reserved word. Thus any Java 1.4 source code containing enum became broken starting with 1.5
As far as I know JVMs are backwards compatible. A class compiled with JDK 1 will work in the latest JRE 7.
The libraires are definitely not 100% compatible. Some methods have been deprecated (and subsequently removed). Some classes changed behavior in (usually) subtle ways which will cause programs to behave differently.
You can always run with a newer version of the JDK then the one used for compilation. The other way around is not possible (unless you compile using the -target parameter).
You might want to read this document (in particular the Cross-Compilation Options section), which explains the target parameter and the default behavior
You can look at the backward compatibility analysis of the Java (Jre) library classes here: http://abi-laboratory.pro/java/tracker/timeline/jre/
The report is generated by the japi-compliance-checker tool.
Java is generally compatible with previous releases but anyway it may be a lot f issues with migration.
See my article about migration from JDK 6 to 8 for details

Categories