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.
Related
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.
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.
Can anybody tell me the jsr14 target option of javac will be still available with JDK7/8?
Say,
$ javac -source 1.5 -target jsr14 Hello.java
We are heavily using -jsr14 in OSGi because it allows us to use generics in our API but still deploy on 1.4 environments, which are still popular in embedded. Unfortunately, they made JDK 7 not backward compatible with Java 6 and 5. Javac 1.7 ignores the generic information that is actually present in the JAR files. There is fortunately no problem at run-time as this info is ignored anyway. And it is not as if this was some undocumented feature ...
Unfortunately, people at the front often have very little regard for the people that cannot just update to the latest and the greatest. Guess Oracle really does not care about the embedded markets anymore.
We will likely now have to ship two JARs, one for the embedded and one for JDK 7. Sucks.
This is the bug report we filed: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7078419
The latest OpenJDK source bundle (openjdk-7-ea-src-b130-18_feb_2011.zip) still contains the flag in the source (langtools/src/share/classes/com/sun/tools/javac/jvm/Target.java), but it has never been supported, so relying on it is a bad idea.
Why do you need it?
That flag has been abandoned since the beta stages of 1.5.
It was only included to allow the 1.5 beta compiler to bypass generics checking/parsing by default while the generics specification wasn't finalised.
Once 1.5 was released, that flag became meaningless. New compiler versions may not give errors on encountering it but will most likely silently ignore it.
I've compiled my source with java version 1.6 using the parameters -source 1.5 and -target 1.5, and the compiler doesnt complain at all.
Still, the application won't run with java 1.5 due to missing methods. Ofcourse I could rewrite some of my source code to be 1.5 compliant, but what I don't understand is; shouldn't the java bytecode in the bottom be "frontwards" compliant?
Aren't the methods converted into bytecode? Is it possible to compile the 1.6 libs/methods (formely String.isEmpty()) to 1.5 bytecode and pack it all into the archive?
If you mean base Java library methods, then no, those methods are not converted to byte code when you compile; they've already been compiled to byte-code by Sun (or the third-party JVM distributer) and installed on your operating system. They are referenced and used by your compiled code.
The full set of command line options you need are:
java -source 1.5 -target 1.5 -bootclasspath /usr/jdk/jdk1.5.0_17/jre/lib/rt.jar
(Change bootclasspath to however your machine is setup.)
Of course, APIs enhancements in 1.6 will not be in 1.5. 1.5 is most of its way through its End of Service Life period, so you might want to consider a 1.6 minimum anyway.
I don't believe java will recompile the native java code backwards. So, if you make a 1.6 call - you will not be able to access it in 1.5
You can change the library you are compiling against to be an older library. In packages like eclipse, each installed JDK should appear in a "Select library" window, you can choose which one you wish to compile against.
If not, you should be able to override it in your ant file or CLI compile command.
If targeting an older JVM, this really has to be done or you may use calls that will not be available.
The source parameter only makes the compiler check at a language syntax level (source=1.4 would for example complain if it encounters generics) but won't restrict you to only using APIs available in the specified Java version.
The target parameter will make the compiler output class files that can be used by a runtime of the specified version but won't (just like -source) validate any API conformity.