讓你脫胎成技術大神的JAVA開發技巧
開發過程中,那些被稱為“666”的大神,領先你的,往往也只有幾個快捷鍵的距離。一些簡單的技巧和開發習慣,往往能讓你在開發過程中事半功倍。
避免重複建立物件
為什麼?
更少的物件會需要更少的垃圾回收
使用的空間越少,應用的效能越好
怎麼做?
重複利用一個物件,而不是在每次需要的時候都去建立一個功能一樣的物件
(這樣做)
String s = “No longer silly”;
(不要這樣)
String s = new String(“silly”);
不可變類中既提供建構函式,又提供了靜態工廠方法的,優先考慮使用靜態工廠方法。複用那些一旦初始化(使用靜態初始化)就不會改變的物件。+++
避免迴圈引用
為什麼
一組相互引用的物件,如果他們沒有被其他物件直接引用的話,它們會變得不可達,這樣會導致它們一直都保留在記憶體裡。
怎麼做
你可以使用強引用來表示“父到子“的引用關係,使用弱引用來表示“子到父”的引用關係。
瞭解和學習一下 JVM 記憶體管理
為什麼
有些人認為Java 程式設計師不需要知道內部 JVM 記憶體管理。毫無疑問,這種觀點明顯是錯誤的,如果想拓寬知識面和提升排除故障能力,你就必須要了解和學習一下 JVM 記憶體管理
怎麼做?
JVM 記憶體分為 3 個記憶體空間
Java Heap:適用於所有的JVM廠商,通常用來拆分 YoungGen(幼苗 ) 和OldGen(終身享用)空間。
PermGen(永久代):適用於SunHotSpot VM((PermGen 空間在 Java7 或者Java8 更新中將會被刪除)
Native Heap(C-Heap):適用於所有的JVM廠商。正如你所看到的,JVM記憶體管理比使用 Xmx 設定最大值更為複雜。你需要檢視每個角度,包括本地和PermGen 需求以及從主機上檢視實體記憶體可用性(CPU core)。
使用==操作符來替代equals(Object)方法
為什麼
==操作符的效能更好
例如,對於字串比較,equals()方法會去比較字串物件裡的字元。==操作符會比較兩個物件的引用,來比較它們是否指向同一個例項。
怎麼做:
當且僅當a==b 的時候才會有a.equals(b)
例如,對於重複呼叫的地方,使用靜態工廠方法來返回相同的物件。
避免使用finalizer
為什麼
垃圾回收器需要單獨記錄等待終結的物件
呼叫finalize方法也有一定的開銷
Finalizer是不安全的,因為它有可能會復活一個物件,這樣會干擾垃圾回收。
避免使用引用物件
為什麼
和finalizer一樣,垃圾回收器需要特別處理軟引用、弱引用以及幽靈引用。
儘管引用物件在某些方面很有作用,例如,簡化cache的實現,但是大量引用物件的存在會使得垃圾回收執行緩慢。
記錄一個引用物件的開銷遠遠超過一個普通物件(強引用)的開銷.
避免使用物件池
為什麼
物件池不僅會使得更多的資料物件保持活動,同時會使得物件的存活時間延長.
值得注意的是,大量存活的資料物件的處理是GC的瓶頸,GC被優化成適合於處理許多壽命較短的物件
並且,建立新的物件而不是保持舊的物件存活,會對快取的區域性性有益.
不過,在一個包含大量大物件的環境下,例如大的陣列,效能或許會因為使用物件池而有所提升。
選擇好的演算法和資料結構
為什麼
考慮一下通過連結串列來實現佇列的場景
即使你的程式不需要遍歷整個連結串列,但是垃圾回收器還是需要這樣做的。
如果元素的封裝者沒有把元素沒有把元素放在記憶體中鄰近的位置,這樣會破壞快取區域性性。因而會導致程式長時間的暫停,尤其是物件的指標分散在一個很大的堆區時,垃圾回收器會在標記階段追隨指標的時候頻繁遭遇快取失效。
避免使用System.gc
為什麼
Java語言規範裡沒有保證呼叫System.gc會做什麼。如果它規定了的話,或許會超出你的期望,也或許每次呼叫都做不同的事情。
避免使用太多的執行緒
為什麼
程序上下文切換的次數會隨著要排程的程序的數目相應地增長,這樣會對效能有隱性的影響。
例如,IntelA-64處理器上的本地執行緒上下文的大小大概是幾千KB。
回顧靜態佔用需求
為什麼
設法對靜態記憶體佔用進行合理的評估,在真正進行資料測試之前,設定一些 JVM 能力起點是非常有用的。
怎麼做
應用程式以及相關資料將決定 Java堆空間佔用需求。通過靜態記憶體,可預測下面的記憶體需求:
確定將會有多少不同的應用程式部署到預先計劃的一個單獨的 JVM 程序上,確定有多少個類需要在執行時載入:包括第三方 API。確定資料快取佔用,如應用程式載入內部快取資料結構(和第三方 API)。 確定允許建立的中介軟體執行緒數量。
在 JVM 程序上部署的應用程式越多,對本地記憶體和 PermGen 空間的要求就越高。資料快取並不是序列化為一個磁碟或資料庫,它將從 OldGen 空間裡面需要額外的記憶體。設法對靜態記憶體佔用進行合理的評估,在真正進行資料測試前,設定一些JVM能力起點是非常有用的。對於32 位JVM, 通常不推薦一個Java堆大小超過2GB(-Xms2048m,-Xmx2048m),對於 JavaEE應用程式和執行緒來說這樣將需要足夠的記憶體和本機堆 PermGen。這個評估是非常重要因為太多的應用程式部署在一個32 位JVM程序上很容易導致本機堆耗盡;尤其是在多重執行緒環境。對於64位JVM, 一個3GB或者4GB 的 Java 堆/JVM 程序是推薦的起點。
避免不需要的異常
為什麼
異常處理會佔用一定的事件,並且會打斷程式的正常執行流程。
作者曾經遇到這樣一場景,在客戶的應用裡,一個正常的執行流程每秒會丟擲成千上萬的NullPointerException。這個錯誤被糾正後,應用的效能裡面有了一個數量級的提升。
避免使用大物件
為什麼
大物件有時候需要直接在堆而不是線上程本地儲存區(thread local areas, TLA)進行記憶體分配。
大物件直接在堆上分配是有壞處的,因為它會更快地產生記憶體碎片。在虛擬機器(例如JRockit)上分配大物件會降低效能,因為分配記憶體的時候會使用堆的全域性鎖。
為了讓學習變得輕鬆、高效,今天給大家免費分享一套Java入門教學資源。幫助大家在成為Java架構師的道路上披荊斬棘。需要資料的歡迎加入學習交流群:9285,05736
