简体   繁体   English

如何在jdk9 / java-9中使用sun.reflect包?

[英]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 我正在使用jdk-9,我想在我的代码中使用sun.reflect.*包但我得到以下异常

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 当我使用JDK-9运行下面的示例代码时

public static void main(String args[]){
   System.out.println(Reflection.getCallerClass(3));
}

Works fine with newer OpenJDK 9 EA builds. 适用于较新的OpenJDK 9 EA版本。 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 . 似乎它是作为JDK-8137058的一部分在9-ea + 115版本中修复的 So probably you are using older EA build. 所以你可能正在使用旧的EA版本。 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. 一般来说,@ Holger是对的:这个API很有可能在将来的Java版本中完全消失,因此请考虑迁移到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. 这些sun.*包从来都不是官方API的一部分,并且不能保证存在,即使在Java 9之前的JVM中也是如此。为将来完全消失做好准备,甚至不能通过某些选项恢复。 Thankfully, there is an official API covering this functionality, eliminating the need for inofficial APIs. 值得庆幸的是,有一个官方API涵盖了这个功能,消除了对非官方API的需求。

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): 获取堆栈中的第n个调用者(例如,第三个,如您的示例中所示):
 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. 简而言之, sun.*com.sun.*包中的大多数类型将不再可访问。 This is in line with Sun and later Oracle stating that these packages are not meant for public consumption. 这与Sun和后来的Oracle一致,表明这些软件包不适合公共消费。

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. 此导出包sun.reflect从模块java.base到所有模块包括未命名的模块 ,这是收集类路径上所有类的一个。

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.* . Jigsaw(java-9)具有模块化概念,他们为compact-1设计了java.base包,它们封装了sun.reflect.* so sun.reflect.* can not be accessible outside. 所以sun.reflect.*无法在外面访问。 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. 尽管如此,@ Holger正确地指出了这一点。

The APIs in sun.reflect packages that remain accessible in JDK 9 are: 在JDK 9中仍可访问的sun.reflect包中的API包括:

  • sun.reflect.Reflection::getCallerClass(int) Instead, use the stack-walking API, see JEP 259: Stack-Walking API. sun.reflect.Reflection::getCallerClass(int)相反,使用stack-walking API,请参阅JEP 259:Stack-Walking API。
  • sun.reflect.ReflectionFactory.newConstructorForSerialization

These APIs are accessible by default at run time. 默认情况下,这些API在运行时可访问。 They have been moved to the jdk.unsupported module, which is present in the JRE and JDK images. 它们已被移动到jdk.unsupported模块,该模块存在于JRE和JDK映像中。 Modules that need these APIs must declare a dependency upon the jdk.unsupported module. 需要这些API的模块必须声明对jdk.unsupported模块的依赖性。

The remaining internal APIs in the sun.misc and sun.reflect packages have been moved, since they should not be accessible. sun.misc和sun.reflect包中的其余内部API已被移动,因为它们不应该被访问。 If you need to use one of these internal APIs, you can break encapsulation using the --add-exports command line option. 如果需要使用其中一个内部API,可以使用--add-exports命令行选项中断封装。 (similar to as answered by @NIrav ). (类似于@NIrav的回答 )。 Though as suggested in the docs, this option should only be used as a temporary aid to migration. 尽管如文档中所述, 此选项仅应用作迁移的临时辅助工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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