2010-09-27 27 views
20

我創建的類「字符串」並放置在包的「java」 [實際上我想創造java.lang中看哪個類是由類加載器加載爲爲什麼`java.lang.SecurityException:禁止包名:java`是必需的?

一旦一個類被裝載到JVM中, 同一類(我重複,同一個類) 不會再次

加載從奧賴利引用。但是,這件事以後,爲什麼上運行這個類我得到
java.lang.SecurityException異常:禁止包名稱:的Java

對於其安全性的原因Java不是讓我在的Java包中的類?如果不存在這種檢查,可以做什麼?

回答

22

用戶代碼是從不允許允許將類放入其中一個標準Java包中。這樣,用戶代碼就無法訪問Java實現中的任何包 - 專用類/方法/字段。其中一些包專用對象允許訪問JVM內部。 (特別是我在考慮SharedSecrets)。

+3

原則上,我同意分析構成的風險,但請注意,如果您的類位於具有相同名稱的包中並且由同一個ClassLoader加載,則只能訪問包私有內容。 – 2010-09-27 19:34:11

+2

不,這不是原因,用戶代碼*可以通過Reflection API訪問'java'類中的私有成員,以及'javax'包下的代碼如何?JVM允許在那裏定義新的類。 – 2011-02-08 15:59:40

+0

@Rogerio:使用反射API訪問私人東西需要一個'SecurityManager'檢查。顯然,如果你沒有安裝安全管理器,所有的投注都是關閉的 – 2011-02-08 16:19:00

2

如果程序可以用木馬版本覆蓋JVM核心類,程序可以繞過安全措施。例如,字符串幾乎在任何地方都被使用。

6

java是一個保留的包名。只有JVM中的類可以駐留在這個包中。

如果任何人都可以在Java包中編寫代碼,那麼可能會導致庫通過自己的實現任意地替換核心Java類。這可能導致許多人認爲,從破壞核心Java功能到執行惡意代碼。

14

首先,這些類型的限制是爲了強制執行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就已經設置了一定程度,更不用說執行它了。

+2

這是最好的答案,但還有更多。使用java.lang。儀器API通過「Java代理」,可以*重新定義由任何類加載器加載的任何類,包括由引導類加載器定義的'java.lang.String'類。 – 2011-02-08 16:07:08

+0

@Rogerio,其他所有評論員如何使用-Xbootclasspath(例如,使用jsr166作爲java.util.ForkJoinPool)?如何編譯jsr jar? – 2012-01-03 23:24:46

8

您不能擁有「java。*」軟件包名稱。這實際上是在Java內核中硬編碼的,所以你甚至不能授予安全管理員權限來解決它(參見ClassLoader :: preDefineClass(...))。

0

可能在重構/補丁應用/等。你已經添加到包名字'java',這通常是一個包含軟件包的文件夾。

所以,你可以與結構結尾: SRC-> main-> Java的> java.com.yourpackage.name

它可能還發生了測試: SRC-> main->測試 - > java-> java.com.yourpackage.name

在你的IDE中驗證它並刪除「java」。部分

1

ClassLoader.defineClass(..)的javadoc:

...指定的類名稱不能以開頭,因爲在「Java中所有類*包只能由引導類加載器定義的「java」。

拋出:... SecurityException - 如果試圖將該類添加到包含由differen簽名的類包•一組證書比這個類,或者如果類名以「java。 「

相關問題