Can call java 7 compile java code from java 6 compiled code - java

I have program compiled on java 6. And library compiled on java 7. Can I call from java 6 compiled code to java 7 compiled code or I will have run time errors. I know that I will have errors on compilation, but i will change jar after compilation. I run my application on jvm 7.

In general Java 7 is backward compatible, so you can use libraries compiled with Java 6.
For example: If your library compiled with Java 6 uses a javax package, it will use the library comming with Java 7 and compiled with Java 7.
I use Apache CXF 2.4.6 (compiled with Java 5) with Java 7. Apache CXF calls Servlet API (compiled with Java 6) of JBoss 7.

Yes, you can, but there are issues with the classfile formats; see this question for the exact mapping of Java versions and classfile format versions.
Specifically, if you have source code A that you are compiling with JDK 6 but you have JAR in the compilation path that has .class files that are with major version 51, then the compilation will fail because the compiler will not be able to load the class files.
However, when compiling you can specify a '-target 1.6' flag so that the generated classfile is compatible with Java 6. If you have access to the source of your library you can recompile it with that target so that it's compatible with a 1.6 compiler.
Lastly (and obviously), the classfile format version must be understood by the JVM.

Related

Can the latest Java code run in 32b JRE 1.8?

I have code that uses Java 17 features and I am using JDK 17. Is it possible to make a JAR file with bytecode from this Java code that will be executable in 32b JRE 1.8?
Unfortunately, no.
You can instruct the compiler to generate bytecode for java 8, but then you can not use language features that were introduced after java 8. If you attempt to do so, your code will not compile.
Here are some details how to specify the target java version maven's pom.xml file.
Your only option is to re-write your code so that it compiles with java 8.

Compatibility and migration from Java 9 to Java 8

I'm reading the document about the new Java 9 module system.
The paragraph 3 Compatibility & migration explains how to migrate code
from Java 8 to Java 9, but says nothing on how "migrate" or run an application
written in Java 9 to pre Java 9 runtimes.
So, if I have, say a JAR application written in a modularity way (every module has a module descriptor) what does happen if I deploy it on, i.e, a JDK 8 runtime?
If your class files are compiled with --release 8 flag, then they should run fine on Java 8. module-info.class files will be ignored by the older JVMs.
If your Java 8 project is maven-based, you can easily configure it to include module-info.java: https://maven.apache.org/plugins/maven-compiler-plugin/examples/module-info.html
Also, take a look at JEP 238 (Multi-Release JAR Files). This allows you to take even more advantages of Java 9 features without breaking compatibility with Java 8.
You cannot start a Java application with a JRE which is less than the one it is built for.
If you just use javac without any special options it will produces classes which do run on JREs equal or bigger than the one of the used JDK.
However javac supports cross compilation. You can use JDK 8 to compile JDK 6 compatible class files. Search for Cross-Compilation Options in the javac docs.
Java Class files contain version information. As with any Java version it should not be possible to execute a class file (or jar) that was compiled with a newer major version than your runtime. See: https://stackoverflow.com/a/4692743/6239524

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.

JDK compliance - a false safety?

I have Java 7 installed but set my projects JDK compliance to Java 6. Unfortunately it turned out that this is not the same as compiling with Java 6.
For example, the interface javax.imageio.stream.ImageInputStream
extends Closable in Java 7 which is not the case in Java 6. Using an ImageInputStream where a Closable is expected compiles fine under my settings (Java 7 complying to Java 6) but gives an compile error when using Java 6.
Is this supposed to be this way?
In order to compile Java code for an older JRE, you need to do two things:
Set the compliance level appropriately. This, as explained by dystroy, makes sure the compiler produces bytecode that the old JVM can understand.
Use the old Java system libraries. This makes sure you compile against the version of the Java system libraries (java.lang.* , java.net.* etc.) that shipped with the old JRE.
You have covered the first point, but not the second, hence your problem.
How to do this depends on your build environment.
In Eclipse, the Java system library to use is set as part of the build path: Go to Project properties / Java Build Path / Libraries, then remove the wrong "JRE System Library" and add the right one using "Add Library...".
When compiling with plain javac, you use option -bootclasspath. Example: javac -target 1.5 -bootclasspath jdk1.5.0/lib/rt.jar OldCode.java (from the javac manpage, section "Cross-Compilation Options").
What you have set with the JDK compliance is mostly the class format.
There were several evolutions in the bytecode format of classes. A JDK can compile in a previous format while a VM can't execute a class compiled on a more recent format.
But the used libraries always are the one available in the JDK you use for execution. The JDK 6 version of javax.imageio.stream.ImageInputStream isn't bundled with Java 7.
Use the bootclasspath option when compiling. I thought the JDK 7 warned of not doing so, if doing cross-compilation.

Tomcat - UnsupportedClassException

I have a problem deploying compiled classes in a Tomcat web application: I'm deploying a class which is to be called from a servlet, but when I run the application it fails telling me of a ServletException: Error allocating the servlet instance due to an UnsupportedClassVersionError: Bad version number in .class file.
Tomcat is using Java 1.5.0_06 as reported by the manager. My class was compiled using Java 1.6.0_14. Running javap on any of the classes already present tells me "Major version 46, minor version 0" which should be 1.2.0 initial and which isn't available anymore for download. The oldest I can find is 1.2.1_004 which doesn't even compile.
Do i need to match my Java version to the Tomcat environment or to the classes already there? Re-compiling the whole project using more modern Java is not feasible for me at the moment, although I'd love to do so.
That's easy: You compiled your application with a later version Java compiler than the Java runtime underneath Tomcat.
Update
The java compiler, javac, supports the options
-source release
Specifies the version of source code accepted. The following values for release are allowed:
1.3 the compiler does not support assertions, generics, or other language features introduced after JDK 1.3.
1.4 the compiler accepts code containing assertions, which were introduced in JDK 1.4.
1.5 the compiler accepts code containing generics and other language features introduced in JDK 5. The compiler defaults to the version 5 behavior if the -source flag is not used.
5 Synonym for 1.5
...and even more importantly,
-target version
Generate class files that will work on VMs with the specified version. The default is to generate class files to be compatible with the JDK 5 VM. When the -source 1.4 or lower option is used, the default target is 1.4. The versions supported by javac are:
1.1 Generate class files that will run on VMs in JDK 1.1 and later.
1.2 Generate class files that will run on VMs in JDK 1.2 and later, but will not run on 1.1 VMs.
1.3 Generate class files that will run on VMs in JDK 1.3 and later, but will not run on 1.1 or 1.2 VMs.
1.4 Generate class files that will run on VMs in JDK 1.4 and later, but will not run on 1.1, 1.2 or 1.3 VMs.
1.5 Generate class files that are compatible only with JDK 5 VMs.
5 Synonym for 1.5
... which will allow you to compile code for a certain version of the JVM.
In other words, you can continue to use your 1.6 compiler, just throw these options at it and you can make it generate 1.5 code which Tomcat will be able to handle.
Do i need to match my Java version to the Tomcat environment or to the classes already there?
You need to ensure that your code is compiled with a version (less than or equals) supported by the JVM you are using; but no, this doesn't need to be the same version that the Tomcat code base was built from - the two code bases can be jvm version independent of each other, as long as they are both supported by the jvm you are using.
Instead of recompiling your source to be 1.5 compatible you could update the JDK that Tomcat is using to 1.6.
You should be able to change this by setting the JAVA_HOME environment variable to point to a Java 1.6 install.
I got the same UnsupportedClassVersionError issue a while ago. The root cause there was not my own compiled code, but some libraries that were needed, which were compiled with a newer JDK.

Categories