六大Java功能
我花了無數小時來對不同的應用程序進行故障排除。 通過經驗,我可以得出關于大多數開發人員應該遠離的幾個Java SE功能/ API的結論。 當我提到大多數開發人員時,我會想到常規的Java EE開發人員,而不是庫設計人員/基礎結構工程師。
全面披露:老實說,我確實認為,大多數團隊最好遠離以下功能。 但是像往常一樣,也有例外。 如果您有強大的團隊并且完全了解自己在做什么,請繼續。 但是,在大多數情況下,如果您開始在軍械庫中包括以下工具,從長遠來看,您會后悔的:
- 反射
- 字節碼操作
- ThreadLocals
- 類加載器
- 弱/軟引用
- 插座
但是足夠的介紹,讓我仔細閱讀警告標志列表,并附上潛在問題的解釋:
反思 。 在諸如Spring和Hibernate之類的流行庫中,反射有其應有的地位。 但是對業務代碼進行內省是一件很糟糕的事情,其原因有很多,我幾乎總是建議避免使用它:
首先是代碼可讀性/工具支持。 打開您喜歡的IDE,并在Java代碼中找到相互依賴的關系。 很簡單,不是嗎? 現在,將方法調用替換為反射并嘗試重復該過程。 當您開始修改通常應該封裝的狀態時,事情變得更加失控。 如果需要一個示例,請看以下代碼:
public class Secret {private String secrecy;public Secret(String secrecy) {this.secrecy = secrecy;}public String getSecrecy() {return null;} }public class TestSecrecy {public static void main(String[] args) throws Exception {Secret s = new Secret("TOP SECRET");Field f = Secret.class.getDeclaredField("secrecy");f.setAccessible(true);System.out.println(f.get(s));} }然后,您將錯過編譯時的安全性。 看到上面的相同示例,您已經可以看到,只有在運行時才發現在getDeclaredField()參數中輸入錯誤。 您可能還記得,發現運行時錯誤比被構建腳本拒絕要復雜得多。
最后,會有開銷。 JIT對反射調用進行了不同的優化。 有些優化需要更長的時間才能應用,有些甚至無法應用。 因此,有時對反射的性能損失可能是幾個數量級。 但是,在典型的業務應用程序上,您不會真正注意到開銷,因此,這絕對可以減少麻煩。
總而言之,我可以指出,業務代碼中唯一合理的(間接)反射用法是通過AOP 。 除此之外,您最好遠離反射。
字節碼操作 。 如果我看到您直接使用CGLIB或ASM您的Java EE應用程序代碼,我感覺我立即想逃脫。 考慮我在反射塊中闡述的原因,將影響倍增五倍,您可能會開始感到痛苦。
更糟糕的是,您在編譯期間看不到可執行代碼。 本質上,您不知道生產中實際上正在運行什么代碼。 因此,當遇到麻煩時,您將不得不進行運行時故障排除和調試-如果您與我一致,這將花費更多的時間。
ThreadLocals 。 為什么在業務代碼中看到ThreadLocals讓我感到顫抖,有兩個不相關的原因。 首先,在ThreadLocals的幫助下,您可能會開始感到使用變量的誘惑,而無需將它們顯式傳遞給方法調用鏈。 在某些情況下可能有用。 但是當您不小心的時候,我可以保證您最終會在代碼內創建許多意外的依賴項。
第二個原因與我的日常工作有關。 將數據存儲在ThreadLocals中可以建立一條通往內存泄漏的通道。 我所面對的10個Permgen泄漏中至少有1個是由廣泛的ThreadLocal使用引起的。 與類加載器和線程池結合使用 ,很好的舊“ java.lang.OutOfMemoryError:Permgen空間”指日可待。
類加載器 。 首先,類加載器是一個復雜的野獸。 您必須首先了解它們,層次結構,委派機制,類緩存等。即使您認為已理解它們,第一次(十次)嘗試仍將無法正常進行。 至少您最終會導致類加載器泄漏。 因此,我只能建議將此任務留給應用程序服務器。
軟參考和軟參考 。 剛剛了解了它們是什么以及它們如何工作? 好。 現在,您對Java內部的了解會更好一些。 有一個用軟引用重寫所有緩存的好主意嗎? 不好。 我確實知道,配備錘子會使您四處尋找釘子。
為什么我覺得對于這種錘子而言,緩存不是一個好主意,您可能會想知道。 畢竟,在軟引用上構建緩存可能是一個很好的示例,說明了如何將某些復雜性委托給GC而不是自己實現。
讓我們以任意緩存為例。 您可以使用值的軟引用來構建它,以便在內存用盡時可以進入GC并開始清潔。 但是,現在您無法控制從緩存中刪除了哪些對象,并且很有可能在下次緩存未命中時重新創建它們。 如果內存仍然不足,則觸發GC再次清理它們。 我想您會看到惡性循環的形成,并且您的應用程序在Full GC不斷運行的情況下成為CPU約束。
插座 。 普通的java.net.Socket太棘手,無法正確使用。 我確實認為它由于具有阻塞性而從根本上存在缺陷。 當使用基于Web的前端編寫典型的Java EE應用程序時,您需要高度的并發性來支持眾多用戶。 您現在不希望發生的事情是讓您的擴展池不那么可擴展,等待阻塞的套接字。
不過,還有許多出色的第三方庫可用于手頭的任務,因此,與其嘗試自己解決問題,不如去搶購Netty 。
翻譯自: https://www.javacodegeeks.com/2013/09/six-java-features-to-stay-away-from.html
總結
- 上一篇: 华兴定存宝福利券怎样用?
- 下一篇: Java DB中的Java存储过程