What is the best way to convert existing jar (without source) written in java 1.5 into java 1.4.x?
Take a look at Retroweaver. It will convert the classes or jar so that it can be run using a 1.4 JRE. Depending on the 1.5 features used, you won't need any additional retroweaver run-time.
Retroweaver uses byte code enhancement. It sounds mysterious but it works.
retrotranslator is another option similar to retroweaver
You could decompile it, then recompile. You'll probably have to fix incompatibilities by hand. Here's a thread on java decompilers.
My gut instinct would be to decompile the jar, then recompile as 1.4.
If there are no 1.5 specific API calls in the decompiled code, that should work fine.
If there are, you will need to re-engineer those sections to work in the earlier java version.
As well as decompiling, you'll likely have to refactor a few things in the source code - enums, generics (I don't think the generics will be in the decompiled code but that probably means you'll be missing some casts), boxing/unboxing, etc. etc.
as Rodeoclown said,
1) unzip the JAR
2) use a decompiler like jad(http://www.kpdus.com/jad.html) using options like these
jad -d src -f -ff -s .java -space -t4 ***.class
3) and from the generated source files, compile them using JDK 1.4's javac.
4) if the 1.4 compiler works OK, rebundle into new jar
5) if 1.4 compiler has issues, you need to use retroweaver(http://retroweaver.sourceforge.net/index.html). That might work in some cases BUT if the class expects changes in JVM, then you're in a tough spot. If the classes uses new threading facility, you can use the JDK 1.4 version of util.concurrent from http://g.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html.
Good Luck!
Related
My existing server is running on Java 1.6 and I cant upgrade it.
I need to use some third party jar/api that is compatible with Java 1.8, when I write some code to access its API, eclipse throws
Exception in thread "main" java.lang.UnsupportedClassVersionError: JVMCFRE003 bad major version
How I can proceed now? Not sure if this is duplicate question, if yes please provide some link on this.
The point is: Java virtual machines are not forward compatible.
A .class file that was generated by an "n+1" compiler can't be used on a "n" JVM. (unless you specifically instruct the compiler to compile for older versions of java)
Your choices:
see if you can acquire a version of that library compiled for Java 6
see if you can run your application on a Java 8 JRE (there is no problem running java6 classes on a newer JVM!)
Option 1 can get pretty ugly - as that library might have dependencies on system classes that Java6 doesn't have.
This is not possible to use multiples Java version or even multiples JVMs in the same project
If you really need this API, then you have just few choices, the best one is to upgrade all the project to use Java 1.8
No, you can't use jars compiled under java 1.8 in an environment running at java 1.6
As others have pointed out, you can't do this. However, you may be able to find older versions of the libraries you wish to use, and those libraries may support your particular version of Java. This potentially means that you will be adopting bugs into your software, but that's just how software evolves over time.
If you must use this 3rd party jar,
then you must compile the 3rd party jar using -target 1.6 (to target java 1.6).
Maybe you will get the source and compile it yourself or maybe you will get somebody else (the vendor, perhaps) to compile it.
All other options are:
Upgrade your JVM to Java 8.
Don't use that 3rd party jar. Either write or find one that is compatible with java 6.
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.
I am trying to recompile an existing Java project exported from Eclipse. It is necessary to recompile this because I am running simulations remotely on other machines where a different (older) version of Java is installed. I have tried recompiling my .java file which specifies the simulation in question. However, it appears that it is necessary to recompile all other classes etc as well. Has anyone got an idea how to do this WITHOUT using Eclipse (I am not the Admin on the other machines and thus Eclipse is unavailable to me) and not manually because the project is quite huge?
Thanks a lot for any suggestions!
I recommend you to always have an command line way to build an application. The usual way to do this in Java is using ANT (or Maven).
As #Santiago Lezica says, Eclipse can generate an Ant file.
I believe that Eclipse allows you to build for an older target platform than the one you are currently running. That way you can do all of your builds locally.
The second approach has the advantage that you can fix any problems arising from compiling for the older platforms (e.g. use of new language features, use of new classes / methods) from the comfort of your own ... workstation.
There is another option that you should consider: Tell Eclipse to generate code for the old Java version (see the compiler options). That way, you can create code that runs on Java 1.3, even if Eclipse uses Java 5.
Not sure what your requirements are, but you could set the compiler level for your projects at the (older) level of your Linux installs. This would cause Eclipse to recompile it at that version, instead of a newer version.
At my company we use IBM's Rational Application Developer (instead of pure Eclipse), but I am assuming the option is in the same spot. If you right-click on your project, you can go to the Java Compiler options and then set the compatibility to the level of that on Linux (1.3, 1.4, etc.).
Since compile Java byte-code is supposed to be portable (for the most part), this should get you past most of your problems.
Otherwise, the other option is to use something like Ant or Maven scripts (which can be kicked off by Eclipse) and then just use a property to set the compiler right before you run it. This way you don't have to switch properties on your projects all the time, if you truly do need "newer" compiled code and can't live with "older" code on both systems.
I have a java program consists of a jar for the "real program" and a sub-folder containing 20 jar library files (also have dependencies between them). I tried but without success ... I'm missing with the many options that gcj to compile :(. Does anyone know how to compile to native code so that a java program?
Thanks
Update: I have used the plugin for Eclipse (I'm using the 3.6 version of Eclipse and the plugin works well) http://gcjbuilder.sourceforge.net/ to generate a Makefile for the compilation. But now I have an another problem :(
Some libraries are not compiled (exit for error). The error is that GCJ considers all .class files inside .jar file, that have dependencies with other libraries do not exist. But for the purposes of my program, these classes are not used (that is, the java program it works properly). There is thus a way to force gcj to consider only the classes actually used in my java program?
I can only recommend that you don't use GCJ. It isn't Java. The compatiblity matrix on their web page is far from encouraging. It doesn't implement Java 1.2 completely yet, let alone all of 1.3, 1.4, 1.5, 1.6. The project appears to be falling further and further behind, and it never had 100% Java compatibility as a stated goal in the first place.
You may want to look at tools like autojar and firends to help resolve your dependencies and to make a single jar.
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.