我正在使用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
当我使用JDK-9
运行下面的示例代码时public static void main(String args[]){
System.out.println(Reflection.getCallerClass(3));
}
答案 0 :(得分:7)
适用于较新的OpenJDK 9 EA版本。例如:
$ 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
似乎它已作为JDK-8137058的一部分在9-ea + 115版本中修复。所以你可能正在使用旧的EA版本。一般来说,@ Holger是对的:这个API很有可能在将来的Java版本中完全消失,所以请考虑迁移到StackWalker API。
答案 1 :(得分:5)
这个答案已经过时 - 检查THIS ONE INSTEAD!
模块系统的一个特性是它允许库开发人员强烈封装由于新accessibility rules而导致的实现细节。简而言之,sun.*
和com.sun.*
包中的大多数类型将无法再访问。这与Sun和后来的Oracle一致,声称这些软件包不适合公共消费。
解决方法是使用命令行标志在编译和启动时导出这些包:
--add-exports java.base/sun.reflect=ALL-UNNAMED
这会将软件包sun.reflect
从模块 java.base 导出到所有模块,包括unnamed module,这是收集类路径上所有类的模块。 / p>
答案 2 :(得分:5)
这些sun.*
软件包从来都不是官方API的一部分,并且不能保证存在,即使在Java 9之前的JVM中也是如此。为将来完全消失做好准备,甚至不能通过某些选项恢复。值得庆幸的是,有一个官方API涵盖了这个功能,消除了对非官方API的需求。
Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.getCallerClass();
获取堆栈中的第n个调用者(例如,第三个,如您的示例中所示):
Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk(s ->
s.map(StackWalker.StackFrame::getDeclaringClass).skip(3).findFirst().orElse(null));
答案 3 :(得分:3)
java -cp classes -XaddExports:java.base/sun.reflect Test
Jigsaw(java-9)具有模块化概念,他们为compact-1设计了java.base包,它们封装了sun.reflect.*
。所以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
为了提供向后兼容性,他们提供了使用该软件包的方法,如下所示。
java -cp classes -XaddExports:java.base/sun.reflect Test
答案 4 :(得分:0)
使用最新版本更新线程,并更新Migration documentation中提到的更改。已经恰当地正确地pointed out by @Holger了。
JDK 9中仍可访问的sun.reflect
包中的API包括:
sun.reflect.Reflection::getCallerClass(int)
相反,请使用 stack-walking API,请参阅JEP 259: Stack-Walking API.sun.reflect.ReflectionFactory.newConstructorForSerialization
默认情况下,这些API在运行时可访问。它们已移至jdk.unsupported
模块,该模块存在于JRE和JDK映像中。需要这些API的模块必须声明对jdk.unsupported
模块的依赖。
sun.misc和sun.reflect包中的其余内部API
已被移动,因为它们不应该被访问。如果需要使用其中一个内部API,可以使用--add-exports
命令行选项中断封装。 (类似于answered by
@NIrav)。
尽管如文档中所述,此选项仅应用作迁移的临时辅助工具。