由一次異常引發(fā)的思考:為什么在自己編寫的Java代碼中包名不能以"java."開頭?

java.lang.SecurityException

今天在閱讀Spring源碼的時(shí)候用junit跑了個(gè)單元測(cè)試,然后發(fā)現(xiàn)報(bào)了上面這個(gè)異常。很明顯,編譯器提示現(xiàn)在的包名是被禁止使用的。后來我把包名前面的"java."刪除后就能正常運(yùn)行了。為什么package name不能以"java."開頭呢?我打算在等外賣的這段時(shí)間探究一下這個(gè)問題。

ps:在進(jìn)一步探究這個(gè)問題之前,我首先要向大家安利一下餓了么最近上線的超級(jí)會(huì)員----餓了么的超級(jí)會(huì)員每個(gè)月只要8塊錢,能領(lǐng)4個(gè)金額5元的零門檻紅包,并且每下滿5單之后還能領(lǐng)取1個(gè)5元紅包,真的超級(jí)優(yōu)惠??!(餓了么的公關(guān)看到之后請(qǐng)支付廣告費(fèi)hhhhh)

餓了么超級(jí)會(huì)員
餓了么超級(jí)會(huì)員

好了,言歸正傳,下面開始進(jìn)入ClassLoader源碼。
我們所編寫的Java類通常是交由應(yīng)用類加載器(Application ClassLoader,也通常被稱為系統(tǒng)類加載器)來進(jìn)行加載的。系統(tǒng)類加載器是通過直接調(diào)用loadClass(name)方法來加載一個(gè)類的。在破壞雙親委派模型中,拓展一個(gè)類加載器通常是繼承它然后把自己的類加載邏輯寫到findClass()方法中,然后調(diào)用defineClass()之后返回。所以我們直接查看源碼:

loadClass(String name)源碼
protected的loadClass方法
findClass

我們?cè)谏厦婵吹絣oadClass方法調(diào)用了findClass方法,而findClass方法的返回又是通過defineClass方法完成的,所以我們直接查看difineClass方法的源碼:

defineClass
defineClass

到了這里其實(shí)我有點(diǎn)納悶,因?yàn)橐稽c(diǎn)也沒看出哪里對(duì)包名進(jìn)行了限制。別急,我們一起來看一下在defineClass函數(shù)中第一行調(diào)用的函數(shù):

調(diào)用preDefineClass函數(shù)
preDefineClass函數(shù)源碼

很明顯,從上面的函數(shù)源碼中我們可以看出在這里對(duì)以"java."開頭的用戶自定義包名進(jìn)行了限制,
那么類加載器為什么要這么做呢?我猜測(cè)原因是這樣的:由于JDK中的包名都是以"java."開頭的,假如在用戶編寫的代碼中也允許使用以"java."開頭的包名,那么在虛擬機(jī)類加載的“類或接口解析”的過程中可能發(fā)生沖突----比如說我們自己編寫了一個(gè)Integer類,并且把它放在自己創(chuàng)建的java.lang包中,那么它就會(huì)和jdk中java.lang.Integer發(fā)生沖突了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容