Run java code with jdk11 but use tools.jar from jdk8 - java

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.

Related

How to exclude a particular jar from jdk/jre in favour of my own source code (jar)?

My dev java version is jdk-11. My dev IDE is eclipse and build tool is maven.
I want to exclude a particular jar/pacakge from jdk in favour of my own source code with some additional logging and functionality as well. (I know this might not be advisable to modify jdk source code and use part of it in the project directly. But I can ignore this for a while.)
Take for example, i want to add a modified source version of package javax.naming.
So i have extracted the src.zip from jdk installation directory. And added the source code under javax.naming package directly in my project.
Now the compiler warns me
The package javax.naming.directory conflicts with a package accessible
from another module: java.naming
Is there a way i can fix the above error.
Or exclude the jar/package java.naming from jdk while keeping the rest of jars from jdk/jre
or Any other approach i can take. I am not looking at inheritance or extension. My modified code is going to be throw away code eventually.

How to have the java8 code that uses Unsafe working on jdk8 and jdk9?

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.

Accessing com.sun.tools.javac.util from Java 9

I'm trying to access the List class from com.sun.tools.javac.util. This works fine with Java 8, but when switching to Java 9 I get the following error: Package 'com.sun.tools.javac.util' is declared in module "jdk.compiler", which does not export it to the unnamed module".
I tried adding requires jdk.compiler; to my module-info file, but this did not solve the issue.
In the longer run, the safe way to be dealing with such situation is to move away from using these internal APIs of the JDK.
One can make use of the jdk.compiler module's APIs as a replacement to the com.sun.tools.javac package.
Defines the implementation of the system Java compiler and its command
line equivalent, javac, as well as javah.
Specifically for com.sun.tools.javac.util.List, almost all of its non-overridden, self-defined methods could be derived from the implementation based on the interface java.util.List.
Migration guide's column about Removed java.* APIs state that -
The Java team is committed to backward compatibility. If an
application runs in JDK 8, then it will run on JDK 9 as long as it
uses APIs that are supported and intended for external use.
These include:
JCP standard, java.*, javax.*
JDK-specific APIs, some com.sun.*, some jdk.*
Supported APIs can be removed from the JDK, but only with notice. Find out if your code is using deprecated APIs by running
the static analysis tool jdeprscan.
Then to add to the highlighted risk above..
Compile Time
Internal APIs that are encapsulated in JDK 9 are not accessible at compile time, but can be made accessible at compile time via the --add-exports command-line option.
In your case :
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
Run Time
At the runtime, they remain accessible if they were in JDK 8 but in a future release, they will become inaccessible, at which point the --add-exports or --add-opens options can be used to make them accessible at runtime as well.
gradle.settings with below arg it might help
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
kotlin.code.style=official

Dependencies of a JAR

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?

How to use jaxp 3 with jdk 1.6?

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.

Categories