程序代碼中,內存有關的問題能夠分爲兩大類:內存訪問錯誤和內存使用錯誤。java
內存訪問錯誤包括讀內存錯誤和寫內存錯誤。讀內存錯誤可能讓程序模塊返回意想不到的結果,從而致使後續的程序模塊運行異常。web
內存使用錯誤主要是指程序模塊申請的內存沒有正確釋放,系統可用內存逐漸減小,使程序運行逐漸減慢,直至中止。編程
通常咱們常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的,使用完後必須顯示釋放該內存空間。服務器
應用程序通常使用malloc,calloc,realloc,new等函數從堆中分配到一塊內存,使用完後,程序必須負責相應的調用free或delete釋放該內存塊。函數
從用戶使用的角度來看,內存泄露自己不會形成什麼危害,通常用戶可能根本不會感受到內存泄漏的存在。可是內存泄漏是會積累的,只要執行的次數足夠多,最終會耗盡全部可用內存,使軟件的執行愈來愈慢,最後中止響應。工具
形成內存泄漏的緣由有不少,最多見的有如下幾種:性能
一、 分配完內存以後忘了回收。優化
二、 程序寫法有問題,形成沒辦法回收。spa
三、 某些API函數的使用不正常,形成內存泄漏。操作系統
四、 沒有及時釋放。
對於如何檢查程序是否內存泄漏,可使用一些專用的內存監控工具,如MemProof 、AQTime 、 Purify 、 BundsChecker 、 JProfiler等
這裏使用簡單的方法,即利用Windows自帶的Perfmon工具來健康程序進程的Handle Count 、Vritual Bytes 和 Working Set 3個計數器。
(1)、Handle Count記錄進程當前打開的句柄個數,監視這個計數器有助於發現程序是否存在句柄類型的內存泄漏。
(2)、Vritual Bytes 記錄程序進程在虛擬地址空間上使用的虛擬內存的大小,它通常總數值大於程序的Working Set。
(3)、Working Set 記錄操做系統爲程序進程分配的內存總量,若是這個值不斷地持續增長,而Vritual Bytes卻跳躍式地增長,則極可能存在內存泄漏問題。
JVM內存泄露診斷分析
對於任何應用程序來講,內存泄漏都是軟件的致命傷,就JAVA來講,JAVA平臺雖然有自動垃圾回收和內存託管機制,在編程上杜絕了不少內存管理的麻煩,可是一樣存在內存泄漏的問題,這種內存泄露包括堆棧內存泄漏、資源內存泄漏等類型,咱們真正追究到這些問題時,更應該對JAVA的JVM更多的關注。
JVM的Heap(堆)包括3部分Permanent Generation(簡稱PermGen)、New Generation 和 Tenured Generation(又叫Old區)
PermGen是JVM自用的區域,是內存的永久保護區,用於存放反射代理和Class,Class在被裝載時就會被放到這個區域中,因此若是web服務器應用的Class至關多時,就要考慮將這一塊區域放大一些。
New 和 Old區是JAVA應用的Heap區,用來存放類的實例的,其中New Generation的目標是儘量快速的收集那些生命週期短的對象,但它以能夠分爲Eden Space 、Form Space、 To Space 3塊,Eden Space 用於存放新建立的對象,當它滿時,JVM就會執行垃圾回收GC。而Old區用於存放長壽的對象,在New區中經歷了N次垃圾回收後仍然存活的對象就會被放到Old區,如那些與業務相關的對象(Http請求的Session、線程、Socket鏈接等)。固然,JVM執行垃圾回收是須要消耗必定的時間的。
所以,咱們在優化JAVA應用平臺過程當中,能夠設置JVM啓動參數的配置,特別注意Xmn 、Xmx 、Xms 的內存大小參數。
若是由於程序代碼的不合理寫法,也會致使一些數據不能被收集,如何經過JVM診斷並分析性能瓶頸呢?典型狀況以下:
一、 在HashMap中放置大量不用的數據,而沒有及時的清理;
二、 在web應用中,頁面的Session放置狀態數據沒有清理;
三、 在Class的Static變量中放置數據,不能被及時垃圾回收;
也能夠經過分析JVM GC log來診斷內存泄漏的問題。
注意:
當應用程序運行過程當中提示「java.lang.OutOfMemoryError PermGen space」時,若是web App下用了大量的第三方jar包,其大小 超過了JVM默認的大小,那麼就會產生此問題,須要修改Tomcat下的catalina.bat,JAVA_OPTS=….