问题
I am using jdk-9 and I want to use sun.reflect.*
package in my code but I am getting the below exception
Exception in thread 'main' java.lang.IllegalAccessError : class Test (in moudle: Unnamed Module) cannot access class sun.reflect.Reflaction (in module:java.base), sun.reflect is not exported to Unnamed module
when I run below sample code using JDK-9
public static void main(String args[]){
System.out.println(Reflection.getCallerClass(3));
}
回答1:
These sun.*
packages were never part of the official API and not guaranteed to be present, even in JVMs before Java 9. Be prepared for them to vanish completely in the future, not even be recoverable via some options. Thankfully, there is an official API covering this functionality, eliminating the need for inofficial APIs.
Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.getCallerClass();
Get the n’th caller on the stack (e.g. third, like in your example):
Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk(s ->
s.map(StackWalker.StackFrame::getDeclaringClass).skip(3).findFirst().orElse(null));
回答2:
Works fine with newer OpenJDK 9 EA builds. For example:
$ java -version
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+138)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+138, mixed mode)
$ javac Test.java
Test.java:5: warning: Reflection is internal proprietary API and may be removed in a future release
System.out.println(Reflection.getCallerClass(3));
^
Note: Test.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
1 warning
$ java Test
null
Seems that it was fixed in 9-ea+115 build as a part of JDK-8137058. So probably you are using older EA build. In general @Holger is right: there are big chances that this API will disappear completely in future Java versions, so consider migrating to StackWalker API.
回答3:
THIS ANSWER IS OUTDATED - CHECK THIS ONE INSTEAD!
A feature of the module system is that it allows library developers to strongly encapsulate implementation details due to the new accessibility rules. In a nutshell, most types in sun.*
and com.sun.*
packages will no longer be accessible. This is in line with Sun and later Oracle stating that these packages are not meant for public consumption.
A workaround is to export these packages at compile and launch time with a command line flag:
--add-exports java.base/sun.reflect=ALL-UNNAMED
This exports the package sun.reflect
from the module java.base to all modules including the unnamed module, which is the one that collects all classes on the class path.
回答4:
java -cp classes -XaddExports:java.base/sun.reflect Test
Jigsaw (java-9) has modularity concept in which they have designed java.base package for compact-1 and they have encapsulated sun.reflect.*
. so sun.reflect.*
can not be accessible outside.
Due to that reason it giving the exception
Exception in thread 'main' java.lang.IllegalAccessError : class Test (in moudle: Unnamed Module) cannot access class sun.reflect.Reflaction (in module:java.base), sun.reflect is not exported to Unnamed module
Still to provide backward compatibility, they have provided the way to use that package like below.
java -cp classes -XaddExports:java.base/sun.reflect Test
回答5:
Updating the thread with the latest release and changes brought in as mentioned in the Migration documentation as well. Appropriately correctly pointed out by @Holger already though.
The APIs in sun.reflect
packages that remain accessible in JDK 9 are:
sun.reflect.Reflection::getCallerClass(int)
Instead, use the stack-walking API, see JEP 259: Stack-Walking API.sun.reflect.ReflectionFactory.newConstructorForSerialization
These APIs are accessible by default at run time. They have been moved to the jdk.unsupported
module, which is present in the JRE and JDK images. Modules that need these APIs must declare a dependency upon the jdk.unsupported
module.
The remaining internal APIs in the sun.misc and sun.reflect packages
have been moved, since they should not be accessible. If you need to use one of these internal APIs, you can break encapsulation using the --add-exports
command line option. (similar to as answered by
@NIrav).
Though as suggested in the docs, this option should only be used as a temporary aid to migration.
来源:https://stackoverflow.com/questions/41820144/how-to-use-sun-reflect-package-in-jdk9-java-9