首先,這些類型的限制是爲了強制執行Java沙箱。也就是說,在受信任的環境中運行不受信任的代碼。例如,從您的瀏覽器的計算機(受信任的環境)運行某個站點(您不一定信任)的applet。目的是禁止不受信任的代碼訪問包可以幫助它逃離沙盒的私人包。
通常情況下,這些限制是由SecurityManager強制執行的,所以當您在命令行上運行自己的應用程序時(除非您明確指定使用SecurityManager),它們不應該發生。當你控制環境時,你可以去編輯你的Java的rt.jar中的String.class定義(並且從技術上說,無論如何,你不知道什麼是許可說的)。正如我所說的,限制通常在SecurityManager中,但是關於java。*包的特定規則在ClassLoader類中。
回答你的問題:我的猜測是,java。*檢查是因爲 a)歷史原因 b)在Java核心的某處檢查類的名稱,如:所有類從java開始*獲得特殊待遇。
但是,即使您設法創建了一個名爲java.lang.String的類,它也不會與Java內核定義的java.lang.String類相同。這只是一個名字完全相同的課程。類的身份不僅僅是類的名字,儘管除非你真的使用類加載器,否則這可能會很難理解。
因此,通過在包java.lang中的應用程序類加載器加載一個類,不會有接入到核心的java.lang包私人的東西。
爲了說明這一點,嘗試用main方法創建一個名爲javax.swing.JButton的類並執行它。你會得到java.lang.NoSuchMethodError: main
。這是因爲java在你的課程之前找到了「真正的」JButton,而真正的JButton沒有一個主要的方法。
在您可能能夠通過使用通過反射和setAccessible直接調用的私有本地defineClassx方法之一來繞過這個限制的Java的獨立應用程序。
BTW:核心java.lang.String中保證你的代碼以往任何時候執行,因爲它無處不在引用時,你就不會與你的用戶代碼那裏首先被加載。在甚至試圖加載你的類之前,JVM就已經設置了一定程度,更不用說執行它了。
原則上,我同意分析構成的風險,但請注意,如果您的類位於具有相同名稱的包中並且由同一個ClassLoader加載,則只能訪問包私有內容。 – 2010-09-27 19:34:11
不,這不是原因,用戶代碼*可以通過Reflection API訪問'java'類中的私有成員,以及'javax'包下的代碼如何?JVM允許在那裏定義新的類。 – 2011-02-08 15:59:40
@Rogerio:使用反射API訪問私人東西需要一個'SecurityManager'檢查。顯然,如果你沒有安裝安全管理器,所有的投注都是關閉的 – 2011-02-08 16:19:00