內存溢出與內存泄漏
一.內存泄漏:
內存泄漏指對象已經沒有被應用程序使用,但是垃圾回收器無法移除它們,因為還在被引用著。
出現內存泄漏的情況和防止:長生命周期的對象持有短生命周期對象的引用就很可能發生內存泄露,盡管短生命周期對象已經不再需要,但是因為長生命周期對象持有它的引用而導致不能被回收,這就是java中內存泄露的發生場景。
1.當將HashMap,ArrayList,Vector等集合定義為靜態的時候,他們的聲明周期將會和應用程序一樣長。他們所引用的所有的對象Object也不能被釋放,因為他們也將一直被Vector等引用著。靜態變量是全局的,GC不會回收。
2.事件監聽器,當一個監聽器在使用的時候被註冊,但不再使用時被反註冊,會出現內存泄漏。
3.如果一個類自己管理內存,常一些成員變量引用其他對象,初始化的時候需要置空。
4.JDK6中的substirng()方法容易導致內存泄漏。
5.各種連接 :
比如數據庫連接(dataSourse.getConnection()),網絡連接(socket)和io連接,除非其顯式的調用了其close()方法將其連接關閉,否則是不會自動被GC 回收的。
解決方法:通過工具查看泄漏對象到GC Roots的引用鏈,就能找到泄露對象是怎樣的路徑與GC Roots相連並導致垃圾回收器無法自動回收。
二.內存溢出
內存溢出是指應用系統中存在無法回收的內存或使用的內存過多,最終使得程序運行要用到的內存大於虛擬機能提供的最大內存。
出現內存溢出的情況:
1.內村中加載的數量過大,如一次從數據庫中取出多條數據:
2.棧溢出:線程請求棧的深度大於虛擬機所允許的最大深度(即無限遞歸出現棧溢出)或虛擬機擴展棧時無法申請到足夠的空間(創建過多的線程出現內存溢出)。
3.堆溢出:不斷地創建對象,並保證GC Root到對象之間有可達路徑來避免垃圾回收機制清除這些對象,那麽在對象數量達到最大堆的容量後就會產生內存溢出。
解決方案:從代碼上檢查是否存在某些對象聲明周期過程,持有狀態的時間過長等,嘗試減少程序中運行期的內存消耗。
內存溢出與內存泄漏