Reputation: 1454
I have code that was compiled with jdk8 as target and source for java 1.8 and use Unsafe. I tried to run this program with jdk9 but it fails with following exception:
java.lang.NoSuchMethodError: sun.misc.Unsafe.getByte
Package sun.misc.Unsafe is not removed from jdk9, so I expected the code to run. I can not recompile the code with jdk9, I expected that java should be backward compatible.
I create little test that is not working for me. Test class:
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
System.out.println("before");
Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafeField.get(null);
unsafe.getByte(new Object(), 4);
System.out.println("after");
}
}
Then I compile the code with jdk8.
C:\Java-IDE\jdk1.8.0_121\bin\javac.exe Test.java
Then if I run it with jdk8 it works:
C:\Java-IDE\jdk1.8.0_121\bin\java.exe Test
before
after
If i run it with jdk9 it throws exception:
C:\Java-IDE\jdk-9.0.4_windows-x64_bin\bin\java.exe Test
before
Exception in thread "main" java.lang.NoSuchMethodError: sun.misc.Unsafe.getByte(Ljava/lang/Object;I)B
at Test.main(Test.java:13)
I believe it should be also possible to run it under jdk9. Is it possible?
Upvotes: 1
Views: 781
Reputation: 298459
The method byte Unsafe.getByte(Object, int)
has been removed in Java 9, but recompiling fixes the issue, as it will cause the invocation of byte Unsafe.getByte(Object, long)
then, which is indeed the intended replacement.
Note that even besides the fact that Unsafe
is an unofficial, unsupported API that should not be used by applications, the methods using int
offsets are deprecated in favor of methods using long
since 1.4.1
, which means that there were one and a half decades time to adapt old code, but your statement that the code “was compiled with jdk8 as target” indicates that it is actually even younger than that.
Given the fact that the planned entire removal of sun.misc.Unsafe
has been announced multiple times, there will be no way around changing the code, if it shall run on future JVM versions. If you are not able to recompile it, ask yourself, how the future maintenance of code that you can’t recompile should look like. If the code is supposed to be frozen, freeze the JVM version as well. Otherwise, you need to find a way to recompile it or replace it.
Upvotes: 3
Reputation: 2054
Yes java is backward compatible, but it is for the java API. The package sun.misc is one of the packages that Sun/Oracle advertised as moveable/updatable/deletable without any prior warning.
So it was
To answer your question, you will need to update your code
EDIT:
Like Alan Bateman said in his comment the obvious solution would be to recompile
But if you can't and if you're not against ugly hacks you can :
get the source of sun.misc.Unsafe and insert your needed/missing methods
create a custom classloader which will essentialy do the same as the system classloader but when sun.misc.Unsafe will be requested for loading will load your version of Unsafe instead
Start your application with your custom classloader
java -Djava.system.class.loader=com.xxx.MyCustomClassLoader xxx
Ugly but may work without recompiling
Upvotes: -1