《Java應用程序性能調優技術》要點:
本文介紹了Java應用程序性能調優技術,希望對您有用。如果有疑問,可以聯系我們。
Java應用程序,不管他們部署到的應用程序服務器,往往會遇到同樣的問題集.作為Java EE調諧器,我已經裸露于各種環境,并對常見問題提出了一些意見.在這方面,我看到我的角色與汽車修理師的角色相似:你告訴你的技工,引擎是啁啾的; 那么他會問你一系列問題,指導你量化啁啾的性質,位置和情況.從這些信息中,他形成了一個關于問題的一些可能原因的好主意.
我會分享我在現場遇到的一些常見問題及其癥狀.這些步調將使我們能夠使代碼運行順利并避免性能問題.
1)使用StringBuilder
這應該是幾乎所有Java代碼中的默認值.盡量避免+運算符.當然,你可能會認為這只是StringBuilder的語法糖,如下所示:
String x = “a” + args.length + “b” ;
...編譯
0 新 的java .lang .StringBuilder [16]3 DUP4 LDC < 字符串 “ 一 ”> [18]6 invokespecial 的java .lang .StringBuilder(java的.lang .String)[20]9 aload_0 [參數] 10 arraylength 11 invokevirtual 的java .lang .StringBuilder .append(INT):的java .lang .StringBuilder [23] 14 LDC < 字符串 “ b ”> [27] 16 invokevirtual 的java .lang .StringBuilder .append(java的.lang .String):java的.lang . StringBuilder的 [29] 19 invokevirtual 的java .lang .StringBuilder 的ToString():的java .lang .String [32] 22 astore_1 [X]
但是,如果以后,您必要使用可選部分修改您的String?
String x = “a” + args.length + “b” ; if(args.length == 1)x = x + args [ 0 ];
現在你將有一秒鐘 StringBuilder
,只是不需要地消耗你的堆的記憶,給你的GC施加壓力.寫這個:
StringBuilder x = newStringBuilder(“a”);X.append(args.length);X.append(“b”);if(args.length == 1);X.append(args [ 0 ]);
在上面的例子中,如果你使用了顯式的StringBuilder實例,或者你依靠Java編譯器為你創立隱式實例,這可能是完全不相干的.但請記住,我們在NOPE分行.每個CPU周期,我們都浪費在像GC那樣愚蠢的東西,或者分配一個StringBuilder的默認容量,我們浪費了N x O x P次.
根據經驗,總是使用StringBuilder而不是+運算符.如果可以,請保持StringBuilder引用跨多個辦法,如果您的String更復雜的構建.
為了大聲哭泣,如果還有StringBuffer引用,請用StringBuilder替換它們.你真的幾乎不必要在正在創建的字符串上進行同步.
2)內存不敷錯誤
困擾企業應用程序的最常見問題之一是可怕的OutOfMemoryError.差錯通常是以下之一:
應用程序服務器瓦解.
性能下降.
一個似乎無休止的重復垃圾回收循環幾乎停止處理,通常會導致應用程序服務器瓦解.
無論癥狀如何,在性能恢復正常之前,您很可能必要重新啟動應用程序服務器.
內存不敷錯誤的原因
在嘗試辦理內存不足錯誤之前,首先了解如何發生錯誤是有益的.如果JVM在其進程內存空間(包括堆中的所有區域)以及永久內存空間中的內存不足,并且進程嘗試創建新的對象實例,則會執行垃圾回收器以嘗試釋放足夠的內存允許新對象的創建.如果垃圾收集器無法釋放足夠的內存來容納新對象,那么它會拋出一個OutOfMemoryError.
內存不足錯誤最常見于Java內存泄漏.從以前的討論中回顧一下,Java內存泄漏是維護對未使用對象的延續引用的結果:您完成了使用對象,但是由于一個或多個其他對象仍然引用該對象,因此垃圾收集器無法回收其內存.因此,該對象所占用的內存從可用堆中丟失.這些類型的內存泄漏通常發生在Web哀求期間,而一個或兩個泄露的對象可能不會使應用程序服務器崩潰,10,000或20,000個哀求可能會發生.此外,泄漏的大多數對象不是簡單的對象,如整數或雙精度,而是代表堆內的子圖.例如,您可能會無意中持有Person對象,并且該Person對象具有一個Profile對象,該對象具有多個PerformanceReview對象,每個對象都維護數據集.而不是丟失Person對象占用的100個字節的內存,您將丟失可能占用500 KB或更多內存的整個子圖.
為了識別此問題的根源,您必要確定是否存在真實的內存泄漏,或者是否將其他內容顯示為OutOfMemoryError.
做出這樣的決準時,我使用以下兩種技巧:
闡發深度內存統計信息.
反省堆的增長模式.
所有JVM(如Sun和IBM)的JVM調優過程都不相同,但存在一些配合點.
3)避免正則表達式
正則表達式比擬便宜便宜.但是,如果您在NOPE分支機構,那么他們是最糟糕的事情.如果絕對必須在計算密集型代碼段中使用正則表達式,至少緩存“模式”引用,而不是重新編譯它們:
staticFinalPattern HEAVY_REGEX = Pattern.compile(“(((X)* Y)* Z)*”);
然則如果你的正則表達式真的很傻,就像
String [] parts = ipAddress.split(“\\”);
那么你真的更好地采用普通 char[]
或基于索引的把持.例如,這個完全不可讀的循環也是一樣的:
intlength = ipAddress.length();toffset = 0 ;intpart = 0 ;for(inti = 0 ; i < length ; i ++){if(i == length - 1 || ipAddress.charAt(i + 1)== '.'){ parts [part] = ipAddress.substring(offset,i + 1); 部分+ +; offset = i + 2 ;}}
...這也顯示了為什么你不應該做任何過早的優化.與split()
版原形比 ,這是不可維護的.
4)不要使用iterator()
現在,這個建議真的不是一般用例,而只適用于NOPE分支.不過,你應該考慮一下.編寫Java-5風格的foreach循環很便利.你可以完全忘記循環的內部,并寫道:
對于(String value:strings){//在這里做一些有用的事情}
但是,每次遇到這個循環時,如果字符串是一個Iterable,您將創立一個新的Iterator實例.如果您使用的是ArrayList,那么將在堆上分配一個3個int的對象:
privateClassItr implementsIterator < E > { intcursor;
相反,您可以編寫以下等效循環和“浪費” int
堆棧上的單個 值,這是很廉價的:
intsize = strings.size();for(inti = 0 ; i < size ; i ++){字符串值:strings.get(i); //在這里做一些有用的事情
...或者,如果您的列表沒有真正轉變,您甚至可以在其陣列版本上操作:
對于(String value:stringArray){//在這里做一些有用的事情}
5.使用原語和客棧
上面的例子來自jOOQ,它使用了很多泛型,因此被強制使用包裝類型為byte,short,int和long,至少在Java 10和項目Valhalla中可以使用泛型之前.但你可能沒有這個約束在您的代碼,所以你應該采取一切步伐替換:
//去堆 整數i = 817598 ;
… 有了這個:
//在堆棧上保存inti = 817598 ;
使用數組時,事情會變得更糟.替換為:
//三堆工具!整數[] I = { 1337,424242 };
… 有了這個:
//一個堆對象.INT [] I = { 1337,424242};
當您深入您的NOPE分支時,您應該非常警惕使用包裝類型.有可能你會在你的GC上造成很大的壓力,因為它必需一直踢在一起清理你的混亂.
一個特別有用的優化可能是使用一些原始類型并創立它的大的一維數組,以及一些分隔符變量來指示編碼對象在數組上的位置.
一個優秀的原始集合庫,比您的平均int []更繁雜一點,它是與LGPL一起使用的trove4j.
這個規矩有一個例外:布爾值和字節有足夠的值被JDK完全緩存.你可以寫:
Boolean a1 = true ; // ...語法糖為:Boolean a2 = Boolean .valueOf(true);字節 b1 =(字節)123 ; // ...語法糖為:字節 b2 = 字節 .valueOf((字節)123);
其他整數基元類型的低值也同樣如此,包含char,short,int和long.但是,只有當你自動打包它們,或者調用TheType.valueOf()時,不是當你調用構造函數時!
結論
為了有效地診斷性能問題,您需要了解問題癥狀如何映射底層問題的根本原因.如果您可以將問題分解到應用程序代碼,那么您需要將問題轉發給應用程序支持代理,但如果問題出在環境中,則辦理問題是在您的控制之內.
問題的根源在很大程度上取決于許多因素,但是一些指標可以在診斷問題和完全消除其他問題時增加信心.我希望本文可以作為您的Java環境的開始故障排除指南,您可以隨著問題呈現,自定義您的環境.
大家可以點擊參加群:606187239【JAVA大牛學習交流】
里面有Java高級大牛直播講解知識點 走的便是高端路線
(如果你想跳槽換工作 然則技術又不夠 或者工作上遇到了
瓶頸 我這里有一個JAVA的免費直播課程 講的是高端的知識點
基礎欠好的誤入喲 只要你有1-5年的開發經驗
可以加群找我要講堂鏈接 注意:是免費的 沒有開發經驗誤入哦)
維易PHP培訓學院每天發布《Java應用程序性能調優技術》等實戰技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養人才。