簡體   English   中英

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

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

我正在使用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));
}

適用於較新的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。

這些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)); 

這個答案已經過時了 - 檢查一下這個

模塊系統的一個特性是它允許庫開發人員強烈封裝由於新的可訪問性規則而導致的實現細節。 簡而言之, sun.*com.sun.*包中的大多數類型將不再可訪問。 這與Sun和后來的Oracle一致,表明這些軟件包不適合公共消費。

解決方法是在編譯和啟動時使用命令行標志導出這些包:

--add-exports java.base/sun.reflect=ALL-UNNAMED

此導出包sun.reflect從模塊java.base到所有模塊包括未命名的模塊 ,這是收集類路徑上所有類的一個。

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

使用遷移文檔中提到的最新版本和更改來更新線程。 盡管如此,@ 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命令行選項中斷封裝。 (類似於@NIrav的回答 )。 盡管如文檔中所述, 此選項僅應用作遷移的臨時輔助工具。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM