Will JRE 1.4 support classes compiled with Java 1.5 & 1.6? - javac

Will code compiled using 1.5 and 1.6 run on a 1.4 JRE? We weren't sure which Java versions the 1.4 JRE supports.
We know that if the code in question implements 1.5 or 1.6 supported features then it definitely won't compile... and that there are some risks with "backwards compiling" but wasn't sure if the 1.4 JRE would refuse to even load the 1.5/1.6 compiled classes or not.
Update: I confirmed you get a java.lang.UnsupportedClassVersionError exception if you run an 1.6 class file on JRE 1.4.

You can cross-compile. This document shows you how:
http://java.sun.com/javase/6/docs/technotes/tools/solaris/javac.html#crosscomp-example
You must specify the specific major version you're targeting (1.4, it sounds like).
Using this technique, your best bet is to always use the newest javac you can find! That way you have all the latest bug fixes and performance improvements, and it's perfectly safe.
EDIT: note that this does address the problem of library incompatibilities, which was discussed in several answers!

Only if you compile with javac -target 1.4 switch.
Obviously you will not be able to use 1.5+ features, such as Generics, Executors, etc.

If you just build with the defaults of javac 1.6, your class files will not work on old versions of Java.
The best way to compile for older Java is just to use the older JDK releases. But if you really want to try to compile for older Java from newer, here are some instructions:
How to cross-compile for older platform versions
Source, target, class file version decoder ring

You also might be interested in http://en.wikipedia.org/wiki/Java_backporting_tools

I don't think it will.
Occasionally (for reasons too complicated to explain), I try to run code in a 1.5 JRE that I compiled in a 1.6 JDK. It typically throws a java.lang.UnsupportedClassVersionError exception.

Yes and no. You can run code compiled under Java 6 on a 1.4 jvm if you set the "source" and "target" javac options to the version you are targeting (e.g. 1.4) when you compile them. This will work in cases where you have not used any of the additional classes or language features that were added since the target version.
Good luck.

Yes, you can produce class files that are compatible with 1.4 with the 1.6 compiler (javac) however, simply doing this is not necessarily going to produce code that will work. The problem is that that will still compile against the 1.6 version of the API.
At first glance you would not expect this to be a problem since the contracts should not change but it is - I had a problem in that a new constructor that takes IIRC an integer was added to BigDecimal (in 1.5) and so at compile time the call to that constructor was specified however at runtime that constructor did not exist and so a runtime exception. You're probably going to have issues like this when methods are overloaded and you're relying on auto variable conversion.
The Javac app is in fact independent of the version of Java that it belongs to - you can specify a different API to use against 1.6 javac and in order to obviate any runtime issues this should be done.

Java 1.5 was a major release where it introduced enums,autoboxing and other stuffs.while compiling you will get exception saying unsupported class version.But if you compile with the command javac -source 1.4 -target 1._ claasname.java it will compile.
If you are using features of 1.5 like auto boxing and enums in that scenario it won't compile since these features are not available in 1.4.In this case we need to convert our code to older versions based on some tools.

Related

Understanding the Rascal support for Java

Is it possible to parse Java files that are external to the eclipse environment? I have only realised operations related to obtaining an AST(s) from Eclipse file (or projects).
Does the current version of Rascal support Java 8?
Yes to the first question:
you could use lang::java::m3::Core::createM3FromDirectory, or read its definition and make your own version.
this code uses setEnvironmentOptions to the JDT's Java compiler for controlling the classpath and the sourcepath of the compiler.
there is no dependency on Eclipse as a whole
To the second question:
No: the current stable release is pre Java 8
Yes: the current unstable release should work for Java 8. There are no specific tests for this yet, so you may be in for some early adopter surprises.

Is it possible to compile PDFRender to run on JRE 1.4?

I would like to use a PDF to image conversion API for Java, PDF-Renderer seems to be quite good. As it's been written for JRE 1.5 compliance, I get alot of compile errors when I try to compile down to 1.4. I have tried tweeking the compiler compatibility options without success. So, is there a 1.4 compatible build for PDF Renderer ? If not would like to know if there are any other options for a PDF=> image renderer in java that is compatible with JRE 1.4.2+
when you are running javac use command line option -target 1.4. Due to java 1.5 added generics and enum that both are compiler features I believe that javac will succeed to generate 1.4-compatible byte code.
But you will probably have some problems later. For example if PDFERenderer uses java classes from JDK 1.5 that cannot be found in JDK 1.4.... In this case you can try to add them to bootclasspath when you are running your application but I cannot guarantee success because classes may depend on other classes etc...
You can try but I'd personally recommend you to move forward to java 1.6. :)

How should I maintain JDK7 projects, so that they automatically could be downgraded for JDK6?

I have few own APIs with around 2000 classes overall. Some of them use the new Path API from JDK7. Most other classes, however, do not rely on any new JDK APIs or new language features. So most classes could be used in a JDK6 environment (which I plan to do). Let's assume, I've annotated all JDK7-only classes with #Java7Only.
What I need now, is a way to create a JDK6-only subset of all my projects more-or-less automatically, without introducing new version branching or product lines (would be too complicated to maintain).
All projects are created using Netbeans, thus using Ant. Many projects depend on others.
Please help me evaluate, which ideas according to my problem is most appropriate. Which problems could occur with each idea?
Common first step for all ideas
Let an annotation processor search for #Java7Only-annotated classes and store the list to a properties file.
Idea 1 (specific)
Write a tool which would use the properties file to recursively copy the whole project, except JDK7-only files.
Build the copied project using JDK6 by invoking ant, thus getting a JDK6-compliant jar.
Idea 2 (specific)
Write a second annotation processor which would use the properties file to pass everything except JDK7-only files to a JavaCompiler instance.
Either build a jar using Java APIs or use Ant API for that.
(This would be a Java-only idea, but probably too complicated)
Idea X (abstract)
Somehow influence the Ant build process (by overwriting some targets?) and for each JDK6-compliant class: let Ant compile two versions of it (one time with JDK6 compiler, another time with JDK7 compiler).
(JDK7-only classes would be compiled only once, using the JDK7 compiler, of course)
Package each bunch to a separate jar.
Possible common problems to the ideas
Some projects dependent on others, so some actions (such as packaging) should consider this.
Remember: the JDK7 compiler generates downward incompatible class files, that's why every possible idea has to happen on sources-level (before or during the build process, not afterwards).
My thoughts on Idea 2:
Essentially this is invoking a compiler within a compiler. Annotation processors are run as part of compilation. Can this be done safely? Is there any static state in Sun's javac that would cause problems. (I don't know the answer but from memory there might be some static state that could cause problems in this scenario).
Idea 1 seems simpler and better to me.
But taking a step back, is it possible to separate out all the JDK 7 specific stuff into a separate module and compile it separately, into a different JAR?
Have the 'main' project, compiled using JDK 6 (which JDK 7 would have no problems reading because it is backwards compatible)
The JDK 7 specific module(s), with source in a different directory, which includes the 'main' JAR on the compilation classpath, could be built separately, with a different build.xml if necessary.
This only partially applies but I'd thought I'd mention it anyway.
The problem with just using -source 1.6 -target 1.6 options for validation is that you can still use Java 7 API when compiled using JDK 7.
I've used the Animal Sniffer Maven Plugin for a few projects now and it has proved quite useful. This plugin scans byte-code of your classes for JDK API usage. That is, you can tell it to fail the build if you attempt to use JDK 7 API when you are targeting JDK 6. This wont help much for separating out classes as you need but it could be useful as a final validation step combined with -source 1.6 -target 1.6 compiler options.
There is also an animal sniffer Ant plugin, as mentioned from the Animal Sniffer main page.

Blackberry OS version

If I develop Blackberry application for OS version 6.0, will the application be compatible with OS version 4.5? If not, is there some way to port the application easily?
If you develop against a specific SDK (eg 6.0) your application will only be deployable to devices that use the matching OS version (6.0 in this case).
In order to develop applications that specifically target different OS versions, you must build separate deployable binaries for each version. Alternatively, you can build for the lowest common denominator -- if you want to support OS 4.5, build for 4.5 and your app will run (though not always gracefully) on all later BB OS versions.
Two open source projects that you can use for examples are BBSSH and LogicMail.
Neither of these uses preprocessor directives, however both take slightly different approaches to managing multiple target OS's; which solution is more appropriate is best determined by your own needs. Both use ant-based builds; and I think both target from OS 4.5 to 6.0. (Older versions of LogicMail target back to 4.1 I believe)
Build scripts can be found here:
BBSSH SVN (build.xml,build-impl.xml, build.properties)
LogicMail SVN (build.xml, build.properties)
Both projects can also be looked to for specific methods of handling things like utilizing features introduced in later OS versions seamlessly to your users -- either providing a custom implementation prior for earlier versions, or disabling the functionality as is appropriate.
Finally a quick note: if you continue to not accept valid answers, you'll soon find that people are less willing to answer you.
Try to use "Preprocessor Directives" to support multiple blackberry devices.
I m not 100% sure but probably not, because version 6.0 uses newer libraries.But try develope in lower version os and it will run at higher version.
hope it helps
Wblade
For an example of a quality open source project that supports many different BB OS versions, check out LogicMail.
The ant build.xml loads platform-specific classes based on the target:
<if><isset property="jde460.home"/><then>
<fileset id="bb460_fileset" dir="..">
<include .../>
...
As far as I can tell, this project does not rely on the preprocessor.

Enable generics in blackberry jde 4.5.0

When i compiled my application in blackberry it shows the following error.
generics are not supported in -source 1.3
(use -source 5 or higher to enable generics)
how to solve this
Java 1.3 is barbaric and no one should ever have to suffer its indignities. Fortunately, there is a solution!
Generics, enums, changing return signature in overrides, and pretty much everything that makes java usable was introduced in java 1.5. (see http://en.wikipedia.org/wiki/Java_version_history). Fortunately, most of java 1.5 was designed to be backwards compatible and not require JVM / bytecode changes. (or maybe this was unfortunate, as it lead Java's implementation of generics to be much weaker than C#. just try creating a generic class with static methods / fields that use the generic parameter)
This IBM article does a good job of explaining the background:
http://www.ibm.com/developerworks/java/library/j-jtp02277.html
But this JVM similarity allowed for creation of tools such as:
http://retrotranslator.sourceforge.net/
This is the section from my Ant buildfile that calls retrotranslator:
&lt java jar="${transformer.jar.exe}"
fork="true"
classpath="${epic-framework.dir}/tools/retrotranslator-runtime13-1.2.9.jar:${epic-framework.dir}/tools/retrotranslator-runtime-1.2.9.jar"
args="-srcjar ${build.dir}/classes5.jar -target 1.3 -destjar ${build.dir}/classes5to3.jar"
/>
Run the converted jar through preverify.exe and then give it to rapc.exe and you will have a working Blackberry app written with Java 1.5.
Edit: I missed a key detail in my original post. In addition to being Java 1.3, the Blackberry class hierarchy is missing many classes that would normally be a part of a Java SE 1.3 JDK. The one you will hit first is StringBuilder -- javac transforms ("string" + "otherstr" + "blah blah") into StringBuilder.append("string").append("otherstr").append("blah blah"). That class doesn't exist on BB, so you break. However, BB has StringBuffer, so writing an adapter between the two is pretty easy. The one catch is that BB disallows apps from adding classes into java.*. This can be very effectively fixed in the build process: 1) build your app against Java 1.5 w/ java.lang.StringBuilder on the classpath, 2) string transform java.lang.Stringbuilder (and everything else in your compat shim) to live in com.mycorp.java.lang.StringBuilder and build it into a JAR file. 3) Use that JAR file w/ retrotranslator and retrotranslator will update all bytecode references to java.lang.StringBuilder so that they now point to com.mycorp.java.lang.StringBuilder. Now you have a java 1.3 compatible bytecode that can be run on a Blackberry.
If anyone is interested in this stuff, contact me. I could look into open sourcing the compat library I have.
This is a limitation of J2ME, which uses a subset of the J2SE (no collections, reflection, etc.) and a Java language level of 1.3. Any code written for J2SE will most likely need to be manually ported.
It seems the JDK5 is not yet supported.
Same question was asked on the blackberrry forum but about enum support:
Sadly, the BlackBerry api is very behind in terms of Java versioning. There's no Generics, no Maps, no Enums - it's based around JDK 1.3.
I believe there is no way of enabling this feature within your BlackBerry app. If you find one, I'd be very interested to hear about it.

Resources