简体   繁体   中英

How to use sun.reflect package in jdk9/java-9?

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));
}

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.

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.

Get the immediate caller class
 Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) .getCallerClass(); 
Get the n'th caller on the stack (eg 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)); 

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM