如何在高性能服務器上進行JVM調優;以便充分利用高性能服務器的硬件資源,有兩種JVM調優方案。服務器
1、 採用64位操做系統,併爲JVM分配大內存網絡
分析:若是JVM中堆內存過小,那麼就會頻繁地發生垃圾回收,而垃圾回收都會伴隨不一樣程度的程序停頓。負載均衡
a) 優勢:擴大堆內存的話能夠減小垃圾回收的頻率,從而避免程序的停頓。所以,人們天然而然想到擴大內存容量。而32位操做系統理論上最大隻支持4G內存,64位操做系統最大能支持128G內存,所以咱們可使用64位操做系統,並使用64位JVM,併爲JVM分配更大的堆內存異步
b) 缺點:堆內存變大後,雖然垃圾收集的頻率減小了,但每次垃圾回收的時間變長。若是Full GC頻繁發生,那麼對於一個網站來講是沒法忍受的。性能
c) 應對辦法:所以,對於使用大內存的程序來講,必定要減小Full GC的頻率,若是天天只有一兩次Full GC,並且發生在半夜, 那徹底能夠接受。要減小Full GC的頻率,就要儘可能避免太多對象進入老年代,能夠有如下作法:(1)確保對象都是「朝生夕死」的,一個對象使用完後應儘快讓他失效,而後儘快在新生代中被Minor GC回收掉,儘可能避免對象在新生代中停留太長時間。(2)提升大對象直接進入老年代的門檻網站
d) 注意:操作系統
1) 64位JDK支持更大的堆內存,但更大的堆內存會致使一次垃圾回收時間過長。線程
2) 現階段,64位JDK的性能廣泛比32位JDK低。代理
3) 堆內存過大沒法在發生內存溢出時生成內存快照對象
4) 相同程序,64位JDK要比32位JDK消耗更大的內存
2、 採用32位JVM集羣:針對64位JDK的種種弊端,咱們更多的選擇32爲JDK集羣來充分利用高性能機器的硬件資源。
a) 如何實現:在一臺服務器上運行多個服務器程序,這些程序都運行在32位的JDK上。而後再運行個服務器做爲反向代理服務器,由它來實現負載均衡。因爲32位JDK最多支持2G內存,所以每一個虛擬結點的堆內存能夠分配1.6G,一共運行10個虛擬結點的話,這臺物理服務器能夠擁有16G的堆內存。
b) 有啥弊端:
1) 多個虛擬節點競爭共享資源時容易出現問題
2) 很難高效地使用資源池
3) 每一個虛擬節點最大內存爲2G
3、 直接內存也會致使內存溢出?
a) 問題分析:在32位JDK中,將1.6G分配給了堆,還有一部分分配給了JVM的其它內存,只有少於0.4G的內存爲非JVM內存。咱們知道,若是使用了NIO,那麼JVM會在JVM內存以外分配內存空間,這部份內存也叫「直接內存」。所以,若是程序中使用了NIO,那麼就要當心「直接內存」不足時發生內存溢出異常了!
b) 直接內存的垃圾回收過程:直接內存雖然不是JVM內存空間,但它的垃圾回收也有JVM負責。直接內存的垃圾回收發生在Full GC時,只有當老年代內存滿時,垃圾收集器纔會順便收集一下直接內存中的垃圾。若是直接內存已滿,但老年代沒滿,這時直接內存先是拋出異常,相應的catch塊中調用System.gc()。因爲System.gc()只是建議JVM回收,JVM可能不立刻回收內存,那麼這時直接內存就拋出內存溢出異常,使得程序終止。
4、 JVM崩潰的緣由:當內存溢出時,JVM僅僅會終止當前運行的程序,那麼何時JVM會崩潰呢?
5、 異步請求如何形成JVM崩潰:若是一個Web應用使用了較多的異步請求(AJAX),每次主線程發送完請求後都將TCP鏈接交給一條新的線程去等待服務器回信,那麼若是網絡不流暢時,這些受委託的線程遲遲等不到服務器的回信,所以保持着TCP鏈接。當TCP鏈接過多時,超過JVM的承受能力,JVM就發生崩潰。
6、 如何處理大對象:
a) 在寫程序的時候儘可能避免大對象
b) 儘可能縮短大對象的有效時間。對象使用完以後儘快讓他失效,以便於垃圾收集器儘快對它進行回收以避免在新生代待的時間過長而進入到老年代。