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.
Related
In a project that I'm working on, we're running into an issue that
relates to incompatibility of a class across different versions of Java.
The suggested fix is to apply cross-compilation: Not only should we we specify the -target and -source arguments to the compiler, we should also explicitly define the correct bootstrap classpath and extension directories.
My question: What benefit does this have over simply using the compiler from the older JDK?
I see mainly two reasons/benifits
If you have parts of the source that uses newer language features, they cannot be compiled with the older version
Eventually there is compiler bugs that might be fixed in newer version
Other than that I see no reason not to use the old compiler.
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'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.
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.
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.