How to target a lower language level in Java - java

I maintain a Java tutorial application written in Java, that demonstrates features of Java 6, 7, and 8. Each tutorial screen is loaded dynamically by Class.forName as needed. The Java 7 classes need to use Java 7 constructs, and the Java 8 classes need to use Lambdas and Date/Time API.
I would like this to be accessible to users of all three of those language levels, just that if they are on Java 6 we would not load up the Java 7 or 8 classes, and if on 7 we would not load the Java 8 classes.
We would dynamically determine the runtime level and disregard higher levels, loading only the relevant classes by Class.forName(). Obviously users with Java 6 or 7 would not be able to execute code with a magic number of 8. So I would like to target an earlier Java release in the build.
In other words, I would like to set source to 1.8 and target to 1.6
However Maven (and Javac) prevent me from specifying a target lower than the source.
Is there any other way?
I have done this in the past with JavaFX code for Android, where I was able to build JavaFX 8 code using Lambdas, but then deploy it to current Android versions. But in that case, there was a special SDK that handled the lambdas and built to Java 7.
Is there any way to do that with standard Java 8?

The only option you have is -source 1.1 -target 1.0 In every other case, they have to be the same
You need to build a jar for each version and another which combines them.

You will have to make 3 different jars, one for each version where the later version include more of your code examples. (on the bright side, you just have to recompile the the java 6 and 7 code multiple times)
for each jar set the -target code to 6, 7 or 8 respectively. You can optionally also use -source parameter and set it to the same value but I don't think you need to unless you are worried you accidentally put in later language features.

Related

Can I run a java program built using Java 8 (.192) using JRE 17, or does everything (JRE, JVM, JDK) have to be on the correct Java 8 version first?

I have a program for work that I'm told will only use Java version 8 update 192 to run correctly. When I downloaded eclipse, it's suggesting that I use JRE 17.0.2 but I recalled my coworker saying I need Java 8 update 192 otherwise it won't work. Does the JRE version matter? Is it irrelevant?
Perhaps I need to download JRE 8.192? I'm not sure. Any help would be appreciated.
I have a program for work that I'm told will only use Java version 8 update 192 to run correctly.
I would doubt the accuracy of that statement. I would say that someone is making a statement without evidence ... if that is what they actually said.
Maybe a more accurate statement is that the program is only known to run on that particular version ...
Anyway, it will probably run on a later version of Java 8, or Java 11. Java 17 is less certain because of the issue of package sealing / blocking of access to internal packages that occurred in Java 16. (Some of the sealing / blocking started in Java 9 ... but there are easy workarounds ...)
Q: Do you need a JRE?
A: No. A JDK will work just as well. (A JDK distro includes a JRE.) But unless there are strong counter-indications, you need the latest version of Java 8, 11 or 17. Java 8 u192 is years out of date.
The only way to be sure that the application will work on a particular version of Java is to try it. In general, there are no shortcuts.
Java 8 is still available, as the first Long-Term Support (LTS) version. The current release is Update 331. I would suggest starting with the latest update of Java 8.
Be aware that Java 8 is not receiving regular updates for the public except for critical security patches. You may want to consider paying for a support contract from any number of vendors such as Azul Systems or Oracle to get support including possible additional updates releases through the rest of this decade.
Generally Java apps will run on later versions of Java without any modifications needed. The Java team at Oracle and the OpenJDK community place a very high priority on preserving that compatibility.
However, there are exceptions to the compatibility policy. In particular: Java 9 introduced the Java Platform Module System which caused some problems in some apps. And in later versions of Java some libraries that were previously bundled are now removed. Some of those removed libraries were transferred to the Jakarta EE project at the Eclipse Foundation. Some were abandoned for lack of interest such as CORBA.
Some few parts of Java that were for years marked as “deprecated for eventual removal” have now been removed.
If you consider moving beyond Java 8, I suggest your first step be sitting down to read through the Release Notes for every release of Java. They are quite well-written. They should alert you to any issues that may affect your app.
FYI, Java 17 is the latest LTS version. Java 18 is current.
As in the other answers, an application built for Java 8 will probably work fine in Java 17, with some caveats, but if you absolutely need the final product to run under Java 8, go get a real Java 8 runtime and set it up in your IDE. Building a Java application for any specific Java version is best done by having an actual copy of that runtime present, preferably a JDK. By having an exact version of its standard library to compile against, you can avoid accidentally referring to packages, classes, and methods added to, or removed from, later versions. You can get an OpenJDK build of Java 8 from https://adoptium.net/?variant=openjdk8 . Be sure to ask your co-worker why they're mentioning an outdated patch version.
Additionally, keep in mind that Eclipse is itself a large Java application. Running it requires Java, and a growing number of downloads include a Java runtime for that simple reason, even the ones that do not include Java development tools. You don't have to compile your code against that version of Java, though--you probably don't even want to since JDK downloads will include JavaDoc for the standard library, among other useful extras.

Two Java versions might be conflicted in team collaboration?

Here's the thing:
Me and my teammates are now working on a Java project, but I'm almost new to Java development. The thing is that I recently updated my local Java version to 15.0.2, however, they created the project with JDK 1.8 (Java 8 perhaps?).
We are worried that this might cause some conflicts since our Java versions are not corresponding, and I'm also not familiar with the relationship between Java version and JDK version (Just like Java 8 and JDK 1.8).
Could somebody give me some explanations of this? Thanks a lot!
We are worried that this might cause some conflicts since our Java versions are not corresponding ...
Yes, you could run into problems:
There are significant differences in the Java language and Java standard class libraries between Java 8 and Java 15. Code written for Java 15 using Java 15 may not compile on Java 8.
Java 8 and Java 15 tool chains produce compiled code with different classfile version numbers. Code compiled for Java 15 will not run on a Java 8 platform.
It is possible to work around these problems, but it is much simpler if all project members use the same Java version.
If you are new to Java, my recommendation is to install and use Java 8. Note that it is possible to have different versions of Java installed simultaneously, and use different versions for different projects.
... and I'm also not familiar with the relationship between Java version and JDK version (Just like Java 8 and JDK 1.8).
It is pretty straightforward. Java 8 is JDK 1.8, Java 9 is JDK 1.9, and so on. This started with Java 5 / JDK 1.5
The weird numbering is a result of a Sun Management / Marketing decision when naming Java 5:
"The number "5.0" is used to better reflect the level of maturity, stability, scalability and security of the J2SE."
Source: https://docs.oracle.com/javase/1.5.0/docs/relnotes/version-5.0.html
(You could also say that the people who made this decision didn't understand the principles of semantic version numbering.)

Where is HttpRequest.BodyProcessor in Java10

I'm currently leaning HTTP/2 Client in Java9~10 through this.
Java 9 does have HttpRequest.BodyProcessor interface while Java 10 does not have HttpRequest.BodyProcessor, but instead it does have HttpRequest.BodyPublisher. Both interfaces are similar.
Why are Java change Interface's name? I think backward compatibility ignored.
The HttpClient has been a part of an incubator module with Java 9 and 10. So what one saw there was more of a prototyped work which though ideally shouldn't change much, yet doesn't guarantee the same.
From the incubator JEP#Incubator Modules:
An incubating feature is an API of non-trivial size that is under
development for eventual inclusion in the Java SE Platform, or the
JDK, but is not yet sufficiently proven.
If you wish to use the standard module you can make use of it in Java 11, where it is named as java.net.http. [notice that its marked as since Java 11 and not 9 or 10]
The jdk.incubator.httpclient module not found in Java11 could help you migrate the usage of HttpClient in Java 11 if you were already using that in Java9/10.
Slightly Off-topic: If you could compare the source code in the two JDK, you would find that there have been updates to the methods in the BodyPublisher as compared to its previous state, both in Java 10 as well as Java 11.

Can I cross compile Java code that optionally uses classes from Java 8 but is compiled to Java 6?

I know that cross compiled Java code cannot use new language features, IE no features like lambdas from Java 8 or try-with-resources from Java 7.
But is it possible to refer to new classes that are added in new Java versions?
Say I have a library that supports Java 6+ and I have some method that accepts a date as an argument.
For Java 6 I offer an API using java.util.Date, but for users of Java 8 I wanted to offer the option of using java.time.Instant.
I would expect the Java 6 users to be able to use the library but encounter a ClassNotFoundException if they try using the Instant method.
Is there an accepted way of doing something like this, and how would it be achieved with common build tools like Gradle or Maven?
The example given is contrived, please don't give answers on alternative approaches to dealing with time.
It is not possible to do cleanly. APIs that mention Java 8 types cannot be loaded on a Java 6 JRE.
If your API uses Java 8 classes, then a Java 6 client cannot compile against it. In theory, you could replace the Java 8 classes with (say) java.lang.Object and require the client code to cast to either java.util.Date or java.time.Instant depending on the execution platform. But I don't see how that would be acceptable, let alone useful to programmers trying to use your libraries.
And you'd need to change your APIs anyway.
If you really need to support Java 6 and you also want to start using Java 8 features in your APIs, I would advise supporting two separate APIs:
one for Java 6 that uses only Java 6, and
another that uses Java 8 types as well.
You may be able to share some of the code behind the two versions of your APIs, but it depends on how "deep" the Java 8 dependencies go.
However, a better idea would be to bite the bullet and stop supporting Java 6 compatibility. Java 6 reached its end-of-life in February 2013. IMO, you are justified in putting a freeze on your Java 6 API, and then treating your Java 8 API as a new release that requires your client to switch to Java 8.
I think if you compile with javac (or Gradle or Maven) from Java 8 with target version Java 6 but without setting the classpaths from Java 6 it should work. But you might need to split on class level, not on method level.
Backporting
As the other Answers explain, basically the answer is “No”. A workaround is to use code that back-ports functionality to an earlier version of Java.
Regarding the java.time classes specifically:
ThreeTen-BackportMuch of the java.time functionality is back-ported to Java 6 & 7 in the ThreeTen-Backport project.
ThreeTenABPThe above back-port is further adapted to Android in the ThreeTenABP project.

Can program developed with Java 8 be run on Java 7?

I am a little confused.
Oracle says Java 8 is highly compatible with Java 7 (backward). But, what possibilities exist that Java 8 program can be run on Java 7 successfully (SE/EE)?
If point one was true, Java 8 applications will be deployed and executed on a Java 7 server support? for example, Tomcat 8 or WildFly?
In general, no.
The backwards compatibility means that you can run Java 7 program on Java 8 runtime, not the other way around.
There are several reasons for that:
Bytecode is versioned and JVM checks if it supports the version it finds in .class files.
Some language constructs cannot be expressed in previous versions of bytecode.
There are new classes and methods in newer JRE's which won't work with older ones.
If you really, really want (tip: you don't), you can force the compiler to treat the source as one version of Java and emit bytecode for another, using something like this:
javac -source 1.8 -target 1.7 MyClass.java
(the same for Maven), and compile against JDK7, but in practice it will more often not work than work. I recommend you don't.
EDIT: JDK 8 apparently doesn't support this exact combination, so this won't work. Some other combinations of versions do work.
There are also programs to convert newer Java programs to work on older JVM's. For converting Java 8 to 5-7, you can try https://github.com/orfjackal/retrolambda To get lower than 5, you can pick one of these: http://en.wikipedia.org/wiki/Java_backporting_tools
None of these hacks will give you new Java 8 classes and methods, including functional programming support for collections, streams, time API, unsigned API, and so on. So I'd say it's not worth it.
Or, since you want to run your Java 8 JEE applications on an application server, just run your entire server on Java 8, it may work.
Backward compatibility means
You can Run Lower configuration on Higher Configuration not Vice-Versa .
Well, there is the -target compiler option, which lets you target the class file format of previous java versions. However, this doesn't fix or detect things such as using classes or methods introduced in JDK APIs after the target version.
No backward compatibility means that Java7 programs will run under Java8 but the reverse is not always true
You may also check Oracle Limit Backward Compatibility
In general, new versions have to give backwards compatibility, so people dont have to throw their work and can upgrade easily. The other way round (newer version running in older version) is not necesarily true because if you use some new implemented feature, that feature obviously does not exist in the previous version and won't work.
Regards
I generated stubs from WSDL, compiled in java 8 and was able to deploy them on server having java 1.6 jvm on it.

Categories