I'm trying to migrate application from jdk 1.5 to jdk 1.6 without introducing any changes visible to the end user.
Application's output is an xml generated using jaxp which is a part of the jdk libraries. Since jaxp versions are different in jdk 1.5 and 1.6, the resulting xml looks different in each version.
An example: DatatypeFatory.newInstance().newDuration(60) produces 'PT2H17M0.000S' in jdk 1.5 and 'P0Y0M0DT2H17M0.000S' in jdk 1.6. Both are correct, but i want to avoid any visible changes.
Classes like DatatypeFactory have a mechanism which allows specifying which implementation should be used, but it relies on specifying full qualified class name. So theoretically i could download jaxp jars with the same version which is used in jdk 1.5 and let the application use them. Unfortunately the package and class names are the same in both versions, so i would have to somehow tell java to load classes from jar and not jdk. I was trying to put jaxp jars at the beginning of the classpath, but it didn't help.
Is it possible to tell java to load classes from external jar and not jdk libraries? Can i solve this problem in any other way?
Thanks in advance
Unfortunately the package and class names are the same in both versions, so i would have to somehow tell java to load classes from jar and not jdk.
it is all decide by classLoader.
1. you can't except the jdk lib.
2. your third jar has the same name and class name.
other thing you can do,rewrite with the third jar's packageName,and recompile.
Related
Program is compiled with JDK8. I want to run the code with JDK11(without recompilation of the code with JDK11).
Problem is that the program use classes from JDK8 tools.jar(classes that are now in the jdk.compiler module in jdk11,the tools.jar is added to the classpath). In JDK11 there is not separate jar for the tools but instead of its the part of the JDK11. So there is class clashes (class is in JDK11 and also in the tools.jar that is on classpath). The classes from JDK11 has precedence before classes from tools.jar. Is there any possibility to tell the JVM that it should use classes from tools.jar instead of the classes from JDK11.
Updates
As I said I can not recompile the code with JDK11.
I know about Java module system introduced in Java9.
What I ask is if there is possibility to tell the JVM to ignore the classes from the JDK11 module jdk.compiler and instead of that use the classes that he founds on the classpath.
Though I really don't recommend doing that, the thing you want is possible with --limit-modules option:
java --limit-modules java.se <rest of arguments>
This will exclude all modules except java.se and you will be able to use classes from tools.jar.
Again, this is terrible advice. It's much better to make your code compatible with new system classes rather than using the ones from JDK 8.
I am using sun.misc.Unsafe in my Java8 codebase. This does not work on Java9.
I would like to have the fix for Java9, but with the same codebase that runs on Java8. If I put module-info.java, it will not work, as my codebase is Java8.
What to do?
Andreas comment points in the correct direction, you can make use of the Multi-Release JAR Files.
You can create a packaging such that the classes with code common to both the Java JDKs are in the root JAR while the one for which you need to overwrite the implementation is in both the root jar as well as META-INF/versions/9. As noted from the JEP:-
In a JDK that does not support MRJARs, only the classes and resources in the root directory will be visible.
In a JDK that does support MRJARs, the directories corresponding to any later Java platform release would be ignored; it would search for classes and resources first in the Java platform-specific directory corresponding to the currently-running major Java platform release version, then search those for lower versions, and finally the JAR root.
For example, on a Java 9 JDK, it would be as if there were a JAR-specific classpath containing first the version 9 files, and then the JAR root; on a Java 8 JDK, this classpath would contain only the JAR root.
Edit:- Here is a sample project for a similar packaging created with the help of a JetBrains blog using IntelliJ2017.3.
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 created a Jar with Java 6. Now I'm creating a release document and recording the dependencies. How can I find the earliest version of Java that can successfully run the Jar, and the earliest version of Java that can successfully compile the source into a Jar?
I only know a manuel solution: try it out. There are, however, two things to consider.
For which version is the code language compatible?
For which JRE will it execute?
The first you can do with your current JDK, just iterate over the -source and -target arguments which you pass to your javac compiler. This will, however, not prevent you from using classes and methods from the JDK you are using. If you do, the code will not execute for a lower JRE, if you are using classes or methods that where not present back then.
The savest way would be to install all different JDKs along and try to compile the code with each of their compilers.
If you created the jar with java 6 and did not specify a different version of output bytecode, the generated class files will require Java 6 or greater. You can experiment to see what versions of bytecode you can generate with your source with the -target command line option if you're compiling manually, if you're using eclipse or some other IDE, most have settings that control the generated bytecode version in project options or somewhere similar.
A related post about determining the bytecode versions of class files: What version of javac built my jar?
The information on this page provides some good hints and general information, but nothing conclusive.
I know that javac.exe basically just launches 'sun.tools.javac.Main' from 'tools.jar' using Java. I also know that the Java API classes are stored in 'rt.jar' in 'jre/lib' under the JDK. Is this where 'javac.exe' loads the Java API classes from?
I'm wondering about this scenario in particular: suppose I installed jdk1.6.0_17, and later on I installed jdk1.6.0_25. If I run 'javac.exe' from jdk1.6.0_17, will it load the Java API classes from 'rt.jar' in 1.6.0_17 or 1.6.0_25?
The reason I want to know all of this is I'm in a situation where I know the code I'm compiling is going to run on a particular (not most recent) version of Java, and I want to compile using the same exact version of javac and the Java API to ensure compatibility.
By default, classes are compiled against the bootstrap(the runtime classes in rt.jar, internationalization classes in i18n.jar, and others) and extension classes of the platform that javac shipped with.So Yes If You run 'javac.exe' from jdk1.6.0_17, will it load the Java API classes from 'rt.jar' in 1.6.0_17 not from 1.6.0_25.
But javac also supports cross-compiling, where classes are compiled against a bootstrap and extension classes of a different Java platform implementation.
See more at : Cross Compilation if you want to use
Set the JAVA_HOME environment variable to the desired JDK. Also change your PATH environment variable to contain the desired JDK bin directory.