When Does The JDK Compile Version Matter? - java

I have two Java artifacts being built. One needs to be built in 1.6, because PowerMock isn't compatible w/ 1.7 and we are using it in a lot of unit tests. Refactoring PowerMock out right now isn't an option as it will take too much time.
However, I want to use this artifact in a Java application built in 1.7 and run the whole thing in 1.7. I think that it should be Ok since it is just building some class files, which I doubt changed much if any probably as far back as 1.2 or earlier. Anyway, I obviously have a fuzzy understanding of this and I am interested to get a Java experts deep dive explanation as to when this would matter, when it wouldn't, and why.
Thanks!

Java is usually backwards compatible between versions so anything compiled on an old version should run fine on a newer JVM. In fact a lot of common libraries are compiled in as old a version as possible (usually Java 5 now a days) unless they need a newer feature to allow more people who are still stuck on old JVMs.
Having said that, there are a few gotchas you need to worry about. One problem I had on some Java 6 to 7 conversion was TreeMap with an initial value of null http://hariharanselvarajan-java.blogspot.com/2013/02/treemap-in-java-6-and-java-7.html
EDIT
Here is a link to Oracle discussing what isn't compatible between 6 and 7 although I would imagine this only affects things that are recompiled: http://www.oracle.com/technetwork/java/javase/compatibility-417013.html

The compiled code should be backwards compatible, so if you run it all on java7 it shouldn't matter than some was compiled using java6.
When you try the other way you get an invalid major/minor version number error.
I would assume that you can mix & match java 6 and 7 code too, just as you can (with caution) mix and match pre & post generics java.

Related

Is it possible to use ConcurrentHashmap compute with java 7 source level?

We have an old project using gwt 2.6 and therefore we need to compile with -source 1.7 option.
The JRE and JDK used are 1.8, but compile with 1.7 source code option.
We want to use the new compute function from ConcurrentHashMap which is only available from java 8. When using eclipse and maven everything compiled well. On the other hand IntelliJ is complaining. My question is, will it work or will we have issues with it?
Will this project run?
Searching in google for ConcurrentHashmap compute, java 8 and source code level 1.7 did not give any info.
If at all, this would require a lot of careful "manual" work.
When you look at this question for example, you can find that there are various different ideas how people want to enable "stream based" functional programming with Java 7. Maybe, after doing a lot of research, you might be able to find similar things regarding such "enhanced collection" features.
But then, all of that might be quite fragile. The fact that some examples might work fine wouldn't mean that you would be able to run a large production code base on a Java 7 VM.
Thus more of a non-answer here: be careful how to invest your time and energy. Instead of trying to backport libraries to Java 7, rather look into moving your whole project onto Java8 at least. Especially keeping in mind that the release cadence for Java has changed significantly, and going with outdated Java versions for many years is simply even less desirable compared to a few years ago.
Well, the simple answer is that it will not work. The target runtime will not have the updated API (i.e., the compute*** methods won't be on the version of Map that Java 7 has).
So if you deploy that code, the runtime will understand the class version, but will raise NoSuchMethodError and similar errors.
In addition to this, there are many reasons for upgrading your runtime.

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.

Old projects compatible with Java 7

My old projects use Java 6 (1.6), and I don't know when I update (Java 7), they can run fine ?
There is an official list of known incompatibilities between java 6 and java 7 from Oracle (including descriptions of both binary and source-level incompatibilities in public APIs).
Also you can look at the independent analysis of API changes in the Java API Tracker project: http://abi-laboratory.pro/java/tracker/timeline/jre/
The report is generated by the japi-compliance-checker tool.
They should do, yes. Java has a reasonably strong history of backward compatibility. However, if these are in any way important projects you should still perform a thorough test pass before deploying anywhere production-like.
There shouldn't be any compatibility differences as the JVM is basically the same. However it is early days so there may be subtle differences which cause a problem which people are not yet aware of.
e.g. Eclipse looks at the Supplier in the java.exe on Windows and sets the command line arguments differently for different suppliers. It has a problem with Java 6 update 22 because Oracle wanted to change it from "Sun" to "Oracle". I believe this has been changed so it is "Oracle" in Java 7 (but still "Sun" for Java 6)
My point being, that if you write generic Java code, you shouldn't have a problem. However, if you are doing something a bit unusual, you are likely to need to re-test your application.
As was already stated backward compatibility is a very important aspect in new Java releases, so in general there should be no problems in switching to a newer Java version. In this case, however, Java 7 seems to have a few bugs in the new hotspot compiler optimizations. The Apache Software Foundation has issued a warning that their products Lucene and Solr are affected by these bugs.
http://lucene.apache.org/#28+July+2011+-+WARNING%3A+Index+corruption+and+crashes+in+Apache+Lucene+Core+%2F+Apache+Solr+with+Java+7
The affected loop optimizations can be switched off by starting java with -XX:-UseLoopPredicate.
AFAIS here, there's no Java 6 features which get deprecated in Java 7 so yes, your project should run fine.

Convert our app from java version 6 to 5,

Is there any solution through which I can convert java'a higher application, created in netbeans IDE 6.5.1, into lower version of java version 5.
If you have the source code, which I assume you do, this might be easy or difficult depending on the code.
Java 6 made few language changes over Java 5. The only one that springs to mind is you can put #Override on implementations of an interface.
The bigger issue is whether you use any of the API differences, of which there are several. I think JDBC has some major differences, which you may or may not use.
These issues may be big or small. It's really hard to say without knowing anything about your app. Generally speaking though they should be small.
Otherwise you should mostly just be able to recompile it with a Java 5 compiler.
If you don't have the source code it's still doable but you just need to disassemble it first and fixing any issues may be tedious.
You can simply try to recompile it for Java 5. As no language-changes are made between version 5 and 6 you can only run into problems, if you use APIs added or enhanced with the version-upgrade.
If you have the source, you could use backported libraries and code rewrite. There is a tool called Retroweaver which can convert 1.5 code to 1.4, but I doubt It works for 6 to 5.
there is an option somewhere to tell Netbeans to generate GUI with non-Java 6 classes. It is documented somewhere, sorry I don't remember. I've already switched to Netbeans 6.7 (RC3).
Check also usages of Desktop API, #Override in implementing interface methods, etc.
It is a good practice to build with a JDK5 in a CI server (like hudson).

Consequences of running a Java Class file on different JREs?

What are the consequences of running a Java class file compiled in JDK 1.4.2 on JRE 1.6 or 1.5?
The Java SE 6 Compatibility page lists the compatibility of Jave SE 6 to Java SE 5.0. Furthermore, there is a link to Incompatibilities in J2SE 5.0 (since 1.4.2) as well. By looking at the two documents, it should be possible to find out whether there are any incomapatibilities of programs written under JDK 1.4.2 and Java SE 6.
In terms of the binary compatibility of the Java class files, the Java SE 6 Compatibility page has the following to say:
Java SE 6 is upwards binary-compatible
with J2SE 5.0 except for the
incompatibilities listed below. Except
for the noted incompatibilities, class
files built with version 5.0 compilers
will run correctly in JDK 6.
So, in general, as workmad3 noted, Java class files compiled on a older JDK will still be compatible with the newest version. Furthermore, as noted by Desty, any changes to the API are generally deprecated rather than removed.
From the Source Compatibilities section:
Deprecated APIs are interfaces that
are supported only for backwards
compatibility. The javac compiler
generates a warning message whenever
one of these is used, unless the
-nowarn command-line option is used. It is recommended that programs be
modified to eliminate the use of
deprecated APIs, although there are no
current plans to remove such APIs
entirely from the system with the
exception of JVMDI and JVMPI.
There is a long listing of performance improvements in the Java SE 6 Performance White Paper.
Java classes are forward compatible , e.g. classes generated using 1.5 compiler will be loaded and executed successfully without any problems on JRE 1.6. Generally your classes genereated by today java compilers will be compatible with future JREs (for example Java7)
The inverse does not hold : you can not run classes generated by 1.6 on older JREs (1.3, 1.4, etc).
Java compilers specify source and target compliance levels. This way, you can compile for any JRE from any other higher-versioned JRE. You need to make sure to use these compliance levels because there are API differences between JREs. For example, JRE 1.5 introduced StringBuilder at the compiler level. This means any time you do:
String s = "string1" + "string2";
The compiler changes it to:
String s = new StringBuilder("string1").append("string2").toString();
Obviously, this will break with a NoClassDefFoundError when you attempt to construct the StringBuilder.
Theoretically, nothing. The JVM is supposedly backwards compatible. Myself, I've never had a problem in that direction.
Depends entirely on what parts of the java library you are using. It could be anything from 'absolutely fine, no difference whatsoever' to 'OMG!! WHY HAS IT JUST FORMATTED MY HARD DRIVE??' (Well, perhaps not this second one, but it serves to support the point of it going from nothing to possibly bad :)).
Your class could also pick up on bug fixes in the library as well, which would mean niggling bugs disappear (or could be introduced depending on if you were relying on buggy behaviour or not).
AFAIK though, the java bytecode is backwards compatible so you shouldn't get any issues with it just not doing anything.
One positive consequence is that the 1.4 classes will still take advantage of speed improvements made to the JVM (although not necesarily improvements made to library classes).
just ran into a problem like this myself. I was writing code that should work with 1.6 but the college had 1.3 installed. Lots of methods just don't work i.e
input = ""+ JOptionPane.showInputDialog(null,"Enter a four digit number to " + (b?"encrypt":"decrypt")+".",(b?"4086":"5317"));
wouldn't work but
input = ""+ JOptionPane.showInputDialog(null,"Enter a four digit number to " + (b?"encrypt":"decrypt")+".");
would. the inputdialog method that accepts three agruments doesn't seam to exist in 1.3.
this is just a long winded way of saying working with 1.6 api on 1.3 results in head slamming incidents.
It should work. I don't remember encountering any problems with it, except when parts of the Java API are deprecated, in which case it'll explain what they are anyway and you can hopefully write a workaround.
Of course, running a class file compiled with JDK 1.6 in JRE 1.5 would cause a problem - even a JRE only minor build revisions older will throw an error.

Categories