2009-10-11 107 views
7

我有一種情況,用戶的代碼在反射訪問的字段上拋出IllegalAccessException。在訪問該字段之前,調用setAccessible(true)。所以,在我看來,這種方法在默默地失敗。在什麼情況下,Java的field.setAccessible(true)會失敗?

在什麼情況下會發生這種情況?這可能與安全經理有關嗎?

這是導致異常的代碼片段:

private static Field levelField; 
public int getLevel() { 
    try { 
     if (levelField == null) { 
      levelField = MessageInfo.class.getDeclaredField("level"); 
      levelField.setAccessible(true); 
     } 
     return levelField.getInt(this); // <-- IllegalAccessException thrown here 
    } catch (Exception e) { 
     handleException(e); 
    } 
    return ICompilationUnit.NO_AST; 
} 
+1

打印出異常消息和stacktrace會有幫助。 – NawaMan 2009-10-11 04:03:35

回答

4

setAccessible被記錄爲拋出SecurityException。請注意,該文檔給出了即使沒有SecurityManager存在,也會拋出SecurityException的情況。當然,它也可能因異步異常而失敗:Thread.stop,NIO緩衝區相關異常或JVM錯誤。

該代碼的真正問題(除了它使用反射)是有一個可以設置爲部分初始化的字段。這會導致競爭條件(你有一個可變的靜態,因此你需要擔心線程(提示,避免可變的靜態!))。在調用setAccessible之前,另一個線程可能會在同一個Field上調用getInt。正如最初的提問者似乎已經發現的那樣,它也不是特別安全。在靜態初始化器中設置字段會更安全和更清晰。

+0

這對我很有意義。謝謝。我不知道這是否是我所看到的問題,但似乎可能,因爲我知道已知多個線程位於代碼的這一部分。但即使這不是真正的問題,我應該改變我的代碼。 – 2009-10-12 05:42:11

0

從Java自身documentationsetAccessible():如果標誌是真實的,但

一個SecurityException提出的任何元素的可訪問性的輸入數組可能不會改變(例如,如果元素對象是Class類的Constructor對象)。如果發生這種SecurityException,則將對象的可訪問性設置爲標記數組元素直到(並排除)發生異常的元素;超出(幷包括)發生異常的元素的元素的可訪問性不變。

不幸的是他們不提關於IllegalAccessException.

6

任何它不應該是一個安全管理問題 - 你會得到一個SecurityException或子類。

代碼levelField.getInt(*this*)不看的權利...

你應該傳遞的MessageInfo實例作爲參數。

你是否在MessageInfo這個課程中打過電話? (爲什麼?!?)或MessageInfo的子類? (試圖使一個超類行爲的私人領域,如果它的受保護?是否MessageInfogetLevel()方法嗎?如果是這樣,你可以調用super.getLevel()獲得的價值,而不是試圖這樣說的。)

如果不是MessageInfo或子類,這就是你的問題 - 你有MessageInfo類的level字段,你試圖從當前類中獲取該字段的值。雖然這應該是拋出IllegalArgumentExeception代替IllegalAccessException ...

如果它真的「IllegalAccessExeception」 - 試圖把一些日誌記錄if (levelField == null)塊內 - 確保它真正被exececuted。該字段是靜態的 - 可能有其他實例或方法在其上設置值。

+0

是的,這個類是MessageInfo類的一個子類,它是我正在使用的框架的一部分。所以,level字段是MessageInfo的一個封裝保護字段,沒有getter,所以它不能被我的子類訪問。 此代碼適用於許多許多用戶,但不是這個特定的代碼。所以,我想知道這個特定人員的設置是否可能存在一些特殊情況,使得通話在這裏失敗。這導致我認爲它可能是一個安全管理器的事情,但我想知道是否還有別的東西。 – 2009-10-11 16:52:16

+0

也許這個用戶在類路徑上有這個框架的更新/舊版本? MessageInfo.level不存在或名稱不同?附: - 它是什麼框架?可能幫助排除這個... – Nate 2009-10-11 22:43:53

+0

也許,但不太可能。我所描述的框架是Eclipse的JDT。這是我們至少3.3以來一直在使用的代碼(在我開始編寫項目之前)。我已經測試過Eclipse 3.5.1。如湯姆在接受的答案中所述,我相信這可能是一個線程問題。 – 2009-10-12 05:44:21

相關問題