When I programme I don't take care if I'm using the features in Java 7 or Java 5. But as far as I think if I use only Java 5 features my complied byte codes should be run also on a JRE version 5. But how can I check if my compiled code will be compatible with JRE v. 5 or even earlier or no.
I'm interested to know the answer of this question more generally for Web and Enterprise applications.
You can compile your code with a specific version using the -target option
Try compiling with different targets to see which compiles and which doesn't
http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html
Related
Can I use a jar, compiled in Java 7 as a dependency in a project that is compiled for compatibility with Java 6? I do not have the source code of the dependency. I have the compiled jar as a maven dependency.
Can I use a jar, compiled in Java 7 as a dependency in a project that is compiled for compatibility with Java 6?
Let's unpick this:
You have a project that is compiled so that will run on a Java 6 JRE. (Lets suppose that you only use Java 6 APIs in that project.) The .class files for this project must have a classfile format major version less or equal to 50 ... otherwise a Java 6 JRE won't be able to load them.
Then you have a dependency that is "compiled in Java 7". That could mean one of two things:
It could have been compiled using a Java 7 tool chain but with a target version of Java 6.
It could have been compiled using a Java 7 tool chain for Java 7.
In both subcases above above, you should be able to use the dependency in your Java 6 project if you run the project on a Java 7 JRE1. A Java 7 JRE can load and run classfiles compiled for Java 6. In one of the subcases, you will be loading classes with two (or more) class version numbers. But that is OK.
On the other hand, if you try to run the code on a Java 6 JRE, then:
Subcase 1 will work provided that the Java 7 dependency doesn't make use of any Java 7 (or later) APIs; i.e. it only uses Java standard classes, methods, etc that were present in Java 6 or earlier.
Subcase 2 will not work. The Java 6 JRE won't be able to load the dependency. Indeed, if the dependency is static (i.e. the project source code has compile time dependencies on the APIs of the dependent), then the project code won't build ... because the Java 6 compiler should refuse to read the dependency's newer version classfiles.
The most advisable approach is to migrate your project and your execution platform to Java 7. Or better still to Java 8 or Java 11, since Java 7 is EOL'd
If you can't do that, the next best thing would be to avoid using the Java 7 dependency ... until you can upgrade.
If you have customers who insist they you continue to support Java 6, then they are impeding your ability to progress your product line. They should be charged a premium for that.
If you have decided to avoid upgrading your Java platform for internal reasons, this decision is accumulating technical debt ... that your organization will need to "pay down" that debt in the long term.
1 - .... or JDK. A JDK is equivalent to a JRE for the purposes of running code.
In your case you actually ask if there is Forward Compatibility between Java 6 and Java 7. Generally speaking Java does not support Forward Compatibility as the 1.7 JVM cannot run code compiled with 1.6. This happens mainly because the version of 1.7 compiled Java bytecode is not known by the older version (1.6).
I have a project using scala for several microservices. We are planning to move to Java 8, but due to the limitation of gradle's Scala plugin and the compatibility between scala and Java 8, those micro services will still be compiled on JDK 7. My question is will they run on JVM 8 without any modification or specific configurtion?
Scala 2.11 which is just released is not yet compatible with Java 8 bytecode. However JVM 8 is backward compatible, so as long as you are still compiling your Scala code on JDK 7 and you just drop it in JVM 8, everything will be working fine.
Might not be applicable to you, but latest Scala only works with JDK 6+, so nothing lower than JDK 6.
Yes, they will. So will those compiled on Java 6 or 5. I am not sure about earlier versions, but would still expect them to work.
My question is if Java JDK and JREs have to be compatible to run?
I mean: will Java applications written using JDK version 8 in future work with current JRE's?
It is possible to use cross-compilation options when compiling. Do that and it will be possible to compile code with SDK 8 that is compatible with Java 1.1. It won't be very advanced code for 1.1, but it will run.
The short answer is No.
If you develop your application in JDK 8 and run it with JRE 7, you would get an UnsupportedClassVersionError.
This question is two part:
JDK vs JRE
forward / backward compatibility.
JRE is the acronym for Java Runtime Environment. JDK is the acronym for Java Development Kit: a set of tools which you use to develop Java programs. The JDK also contains a full JRE. In general there is no compatibility issue between the two. But you might want to take care not to use libraries which are only available in the JDK (for example code generation or the tools.jar)
Java itself is compiling to bytecode, which is forward compatible. That means you can use bytecode of any Java version and run it with any newer version. The other way around generally doesn't work and is checked by using the class file version ("java.lang.UnsupportedClassVersionError: Test : Unsupported major.minor version 51.0").
Then there are Java libraries, including the core libraries. So far there was never anything removed from them, so they are forward compatible. This is probably going to change with Java 9 where a very small usually unused library functions are removed.
Regarding to backwards compatibility, this is possible by setting the Java compiler to produce Bytecode of an older version. Up until Java 8, the compiler was always able to produce bytecode of the last two major versions as well. However, you might successfully compile a Java 8 source to Java 6, but not be able to run it. That is the case when you use libraries that are only available on a never Java. For such cases there is for example the maven animalsniffer plugin which will verify that when you compile against an older version, you actually only use libraries existing in said version.
I have a PowerMac and it is giving me bad version number on some .jars. I would love to make it seem like I am running Java 6. How would I spoof the version? Let me also say I am running PowerPC and Leopard
The most likely problem is that you have Java 6 JAR files and you are trying to run them on an old Java installation.
How would I spoof the version?
The answer to your question is that you can't. The way to run Java 6 specific JAR files it to use a Java 6 (or later) JRE or JDK.
The problem is that the format of Java class files has changed, and your installation can't cope with the new format. And this is not a gratuitous change that you can pretend doesn't exist. Java 6 (actually Java 5) has support for generic types, enums, annotations and other things. Assuming that the JARs contain code that uses these new language features, an older JRE simply won't know what to do with them.
There are two solutions:
Upgrade your Java installations to the required level on all machines. This is the best solution ... if it is an option ... because it means your users will get the benefit of security and bug fixes and performance enhancements. (And progress of your project won't be held back by the constraint of supporting legacy platforms.)
Compile all of your code for compatibility with the oldest version of Java that you still have to use. Either compile on the corresponding old JDK, or on a more recent JDK using appropriate -source / -target / -Xbootclasspath options ... as described by the javac manual page.
The catch with the second solution is that if the source code for the JAR files in question uses recently added Java language features or APIs, then recompiling for the older platform will fail. To fix this you will need to rewrite your code to replace the nice modern stuff with archaic stuff. Not a good solution, IMO.
The other possibility is that you are seeing corrupted JAR files. This is unlikely, but it can happen if you are using applets or webstart, and the server is delivering error pages instead of JAR files.
The third possibility is that you simply haven't configured your Mac's Java installation's correctly. Making Java 7 the default should allow you to run everything without class version problems. (Thanks #paulsm4) Note that I can't help you with that ... 'cos I don't use Java on a Mac.
If I compile an application using Java 5 code into bytecode, are the resulting .class files going to be able to run under Java 1.4?
If the latter can work and I'm trying to use a Java 5 framework in my Java 1.4 application, is there anything I should watch out for?
Nope! .class files are forward compatible only. Java 5 introduced new classfile attributes and format changes, to handle Varargs, enums, and generics. Java 4 would just fail when processing these.
However, there is the unsupported -target jsr14 option on javac that generates JDK 1.4-compatible bytecode for some Java 5 language features.
Also, there are projects (e.g. Retroweaver, Retrotranslator) that convert Java 5 classfiles into Java 4 files.
EDIT: I found this good resource: Using Java 5 language features in earlier JDKs
No. You can only move upwards - Java 1.4 bytecode will work on Java 5 runtimes. However, if you aren't using any functionality not found in Java 1.4, you can compile using the -target and -source options of javac.
If you want to use Java 5 to write an application that can be run on Java 4, you can't use any features that weren't present before Java 5.
No they are not. .class files are forward compatible only.
Java5 framework implies that your library is probably using generics or annotations that are incompatible with your 1.4 environment. You have to evaluate how much risk there is for you to run your 1.4 application under a 1.5 JVM to enable use of the frameworks you require.
In general I've found moving to 1.5 to be mostly painless, but diligent testing is called-for.