I've read that the bytecodes that the JDK generate are generic. What I say is that they only do things like memory mapping, calling, etc... So if that's true, it would mean that I can, for example, if write a program with characteristics of JDK 1.7, I don't need to worry about if it can run in a user with JRE 1.6? (It's an example, it could happen with more exagerated cases).
So, my question is: Can I write a program with new things from 1.7 and run it in 1.6?
Can I write a program with new things from 1.7 and run it in 1.6?
No. Java is not backward compatible.
Note that it is possible to create code compatible with a Java 1.6 JRE in a 1.7 JDK by using the cross-compilation options, but that code can only use the classes, attributes, methods and language features available in version 1.6.
Can I write a program with new things from 1.7 and run it in 1.6?
The short answer is yes, but it is not officially supported. You'll have to resort to some hacks, but you can get it to work if you really want to. I wouldn't recommend doing this in a major project though.
In general bytecode is not backwards compatible because each classfile contains a version field. The JVM will refuse to run classes with a higher version than it was built for (lower versions are of course ok). By default, the javac that comes with Java 7 will create classes with version 51.0, which means they can only be executed by the JVM that comes with Java 7 or higher.
However, this doesn't mean it's impossible if you really want to create Java 6 compatible code. You can tell the compiler to generate classfiles with an earlier version. All this means is that you won't be able to use library and bytecode level features introduced in the new version.
Luckily, version 51.0 did not actually introduce any new bytecode features used by javac. All of the new features in Java 7 are implemented at compile time - the bytecode isn't any different except for the version! This means that any Java 7 class can be made to work as long as it doesn't rely on standard library updates (for example Try With Resources requires library support).
Unfortunately, javac refuses to compile Java 7 to version 50.0. But you can always change the bytecode version field yourself, either manually or with a tool. Since there were no new bytecode features, it will work just fine.
P.S. Memory mapping is down by the VM. There's no bytecode instructions for it. But you have the right idea.
Related
In a conversation with someone else, they claimed that the version of JDK being used to compile the code does not matter vs. the JVM version being used to run the compiled code.
That seems strange to me - are there never instances where the JDK version matters? Is functionality always only dependent on the JVM the code is running on, and not on how the code is being compiled?
https://stackoverflow.com/a/19554706/2687324 talks about backwards compatibility. Is Java code also forwards compatible?
No, you can't necessarily run code compiled with a new JDK on an old JRE. Compiled classes contain a version number for the class file format; if this is newer than the runtime expects, it will refuse to load the class.
Most Java compilers support an option to target an older JRE, generating an older class file format than the compiler was built for. However, you can still run into trouble if you don't also compile against an older version of the Java runtime library. Your code might use new API that isn't in the older version of Java. The compiler, with its current version of the API, won't catch this even when you specify an older target.
For the standard javac compiler in OpenJDK, these options are -target and -bootclasspath. You might also want to set the -source option to catch usage of newer language features that require support the older class files don't provide.
I am currently working on java 1.7 standard version, and I am really fun of the new features:
Nio(new input out put)
non redundant code with collections
...
I want to know if there is a way to switch the class I want to execute depending on the version of (JRE)java runtime environment it will be deployed.
You first need to create some sort of launcher app in order to check the JRE version of the environment, then you can lauch the JAR compiled for those version of the JRE. Your code cannot be compiled to newer versions of the JRE and be executed in an older one. That's why you need to complie the launcher app targeting a very old JRE.
As a side note, you can obtain the JRE version in which your program is running using:
System.getProperty("java.version")
The Java class file(s) are almost always binary compatible with new versions of the language (and the few exceptions, like using enum before the keyword was added, are fairly rare). If you restrict your usage of features to the "lowest common denominator" it is possible to compile back to an arbitrary version. That being said, Java 7 is now quite long in the tooth and I've found Java 8 to be remarkably stable. Finally, if you do choose to use new language features (like lambdas) you cannot use the earlier version of the language.
You can create two compiled build for both version to use language feature differently and have them running on jre 7, but you should just upgrade code compatibility and runtime to 1.8 (Even better)
I'm working on a university project which is based in cloudsim3.0 project. I'm using jdk 7 while the cloudsim uses jdk 1.3. So I have to change everything: generics, for-each loops , etcetera. Some of the errors I received from NetBeans are:
Generics are not supported in -source1.3 (use -source7 or higher ...)
Strings in switches are not supported in -source1.3 (use -source7 or higher ...)
...
How can I change the jdk version from 1.3 to 7?
Thanks
Generally you want to be very careful with developing in a higher Java version than you deploy to. The java compiler in the JDK which is what Netbeans uses do not support compiling Java 7 source to 1.3 bytecode, so you need to use another compiler which do.
I spent some time a while back investigating this for targetting Java 1.4, and you can use the Eclipse compiler either directly inside Eclipse or as ecj (which is a javac drop in replacement from the command line) which can be used inside ant, or you can use Retroweaver which actively converts byte code to an earlier version.
You might consider just biting the bullet and use Java 1.3 for your project, as it removes all these magic bullets from what you need to investigate if your code for any reason does not work.
Your question is a bit confused, but it makes most sense if you are asking how to compile Java 7 source code for JDK 1.3.
And the answer is that you can't. Those constructs (generics, for-each loops, string switches) all require a more modern target platform.
In theory, you've got two possible solutions:
Remove all the Java 5,6,7-isms from your code and compile with -source 1.3 -target 1.3. (Or download and install an old Java 1.3 JDK.)
Run the CloudSim3.0 code using a Java 7 JVM. It should work, unless it depends on old bugs that have been fixed.
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
I've recently moved to Java 7 in one of my projects. I claim that it can run on Java 1.5 simply because there's nothing I depend on that is in Java 6 or 7. However when compiling today I noticed this:
bootstrap class path not set in conjunction with -source 1.5
Google has found little information on this warning. Does this mean that you can't compile to Java 1.5 from Java 1.7?
This Oracle blog explains the warning:
http://blogs.oracle.com/darcy/entry/bootclasspath_older_source
The reason is, that if you fail to set rt.jar for the older platform, then:
If the second step is not taken, javac will dutifully use the old
language rules combined with new libraries, which can result in class
files that do not work on the older platform since references to
non-existent methods can get included.
Does this mean that you can't compile to Java 1.5 from Java 1.7?
No it doesn't. It means that there is a right way and a wrong way to do this ... and you are doing it the wrong way.
The right way to compile for the Java 1.5 on a Java 1.7 JDK is:
Get hold of a copy of the "rt.jar" from Java 1.5 and put it on the compilation bootclasspath.
Compile with -source 1.5 and -target 1.5.
The warning message is telling you that you haven't done the first of these.
The way that you are building right now is implicitly using the 1.7 version of "rt.jar" for the Java runtime APIs. This may work! (Indeed, it should work assuming that you've made no changes to the code since it last built on 1.5.) However, there is a risk that you may accidentally introduce dependencies on classes or methods added in Java 1.6 or 1.7. That would result in runtime errors when you try to run your application on Java 1.5.
You better be setting -source and -target 1.5.
To be really sure that you aren't accidentally incorporating dependencies on newer classes, methods, or fields, use the maven-animal-sniffer plugin or something like it.
--source 1.5 will make sure the source files comply with Java 5 conventions. --target 1.5 will make sure the generated class files comply with Java 5 conventions. Neither of these will protect you from using Java 6 or 7 library methods. You must either compile against the appropriate rt.jar using --bootclasspath, or use something like the animal-sniffer-plugin (if you are using maven) which will inspect everything's type signature, and compare with published profiles.
With the animal-sniffer-plugin, you may be in for a treat, because you can bump into 3rd party libraries that use Java 6 APIs, which may cause your build process to fail given you are pursing Java 5.