Java 中將要刪除的功能:Applet、Security Manager和對象終止機(jī)制
隨著 Java 的不斷發(fā)展,為了減輕維護(hù)的壓力,一些功能會被聲明為廢棄,并最終從 Java 中刪除。我之前發(fā)了3個視頻,介紹 Java 中即將移除的功能。這里進(jìn)行一下總結(jié)。
Java 中刪除功能的流程
從 Java 中移除功能有一個標(biāo)準(zhǔn)的流程。在刪除之前,首先會聲明為廢棄的。相關(guān)的 API 會被加上 @Deprecated 注解。廢棄分成兩種:一種只是單純的廢棄,另外一種是廢棄之后會在今后的版本中被刪除。區(qū)別在于 @Deprecated 注解的屬性值 forRemoval 是否為 true。
聲明為廢棄待刪除的 API 會在之后的版本中被刪除。

Applet
Java 的 Applet 是一個極具爭議的技術(shù)。在 Java 的早期時代,Applet 確實(shí)是 Java 的一個殺手級應(yīng)用。直接在瀏覽器就可以下載應(yīng)用并運(yùn)行。隨著技術(shù)的發(fā)展,Applet的技術(shù)優(yōu)勢不再明顯,又帶來了很多的安全隱患。很多瀏覽器都已經(jīng)移除了對 Applet 的支持。失去了瀏覽器的支持,Applet 技術(shù)自然也就沒有了存在的必要。Applet 相關(guān)的API 在 Java 9 就已經(jīng)被聲明為廢棄的,在 Java 17 中進(jìn)一步被聲明為廢棄待刪除。雖然還沒有正式移除,但是我們已經(jīng)可以對 Applet 說再見了。


Security Manager
Java 中另外一個即將被刪除的功能是 Security Manager。Security Manager 在 Java 17 中被聲明為廢棄待刪除。雖然暫時不會被刪除,但是它的命運(yùn)已經(jīng)注定了。
為什么 Security Manager 被移除?最大的原因是 Applet 被移除了。Security Manager 在設(shè)計之初有兩個目標(biāo),分別是保證客戶端代碼和服務(wù)器端代碼的安全。這里的客戶端代碼指的是通過 Applet 下載到本地執(zhí)行的代碼。因?yàn)?Applet 是從遠(yuǎn)程不受信任的地址下載到本機(jī)的,因此只能運(yùn)行在受限的環(huán)境中。Security Manager 的作用就是確保這些代碼不會做一些壞的事情。具體的做法是通過權(quán)限機(jī)制來進(jìn)行限制,比如不能通過 Java I/O API 來操作本地文件。Applet 技術(shù)已經(jīng)被廢棄,也基本上沒有什么瀏覽器支持了。Security Manager就失去了存在的一個重要理由。
Security Manager 的第二個目標(biāo)是提供一套安全相關(guān)的標(biāo)準(zhǔn)API,給服務(wù)器端應(yīng)用來使用。這個出發(fā)點(diǎn)是好的,但是與安全相關(guān)的需求太復(fù)雜。從 Java 1.0 時代就存在的 Security Manager 在 API 設(shè)計上,存在太多局限性,無法滿足現(xiàn)在應(yīng)用的需求?;跈?quán)限的訪問控制已經(jīng)不流行了。相關(guān)的 API 使用起來十分繁瑣。Security Manager也會帶來性能問題。
基于上面兩個原因,Security Manager 存在的價值已經(jīng)很小,并且會帶來很高的維護(hù)成本。因此 Security Manager 即將被移除。


對象終止機(jī)制
對象終止機(jī)制(Finalization )從 JDK 1.0 就已經(jīng)存在。它的設(shè)計目標(biāo)是避免出現(xiàn)資源泄露。
JVM 的垃圾回收器負(fù)責(zé)進(jìn)行內(nèi)存的回收。有些對象表示的是操作系統(tǒng)的資源,比如文件句柄或原生內(nèi)存。這些資源需要被釋放回操作系統(tǒng)。在對象終止機(jī)制中,每個類可以聲明一個 finalize 方法。在該方法的實(shí)現(xiàn)中,添加釋放資源的邏輯,比如調(diào)用 close 方法。當(dāng)對象不可達(dá)時,GC 會首先調(diào)用 finalize 方法,再回收該對象。
對象終止機(jī)制雖然看上去很巧妙,但是在實(shí)際使用中存在很多問題。比如,finalize 方法被調(diào)用的時機(jī)是不確定的,甚至可能永遠(yuǎn)不會被調(diào)用,導(dǎo)致資源無法被及時釋放。finalize 方法還可能使得對象重生,造成一些不可預(yù)知的錯誤。
因?yàn)閷ο蠼K止機(jī)制的這些問題,目前已經(jīng)不推薦使用 finalize 方法。Effective Java 一書中有專門的一個條目,Avoid finalization 來討論這一點(diǎn)。
從 Java 18 開始,對象終止機(jī)制被聲明為廢棄待刪除。由于對象終止機(jī)制在 JDK 和流行的庫中被大量使用,對象終止機(jī)制仍然是默認(rèn)啟用的。JVM 啟動參數(shù) --finalization=disabled 可以禁用對象終止機(jī)制。通過這個參數(shù),可以測試應(yīng)用是否依賴對象終止機(jī)制。對象終止機(jī)制雖然在短期內(nèi)不會被移除,但是應(yīng)該考慮對已有的代碼進(jìn)行遷移,使之不再依賴對象終止機(jī)制。具體的做法是,改用 try-with-resources 來主動釋放資源,或使用 Java 9 增加的 Cleaner API。


如果你的應(yīng)用仍在使用這些將要被刪除的功能,盡早規(guī)劃替代方案。