程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 深刻懂得Java渣滓收受接管機制和內存洩露

深刻懂得Java渣滓收受接管機制和內存洩露

編輯:關於JAVA

深刻懂得Java渣滓收受接管機制和內存洩露。本站提示廣大學習愛好者:(深刻懂得Java渣滓收受接管機制和內存洩露)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻懂得Java渣滓收受接管機制和內存洩露正文


媒介

在segmentfault上看到一個成績:java有完美的GC機制,那末在java中能否會湧現內存洩露的成績,和可否給出一個內存洩露的案例。本成績視圖給出此成績的完全謎底。

渣滓收受接管機制簡介

在法式運轉進程中,每創立一個對象都邑被分派必定的內存用以存儲對象數據。假如只是一直的分派內存,那末法式早晚面對內存缺乏的成績。所以在任何說話中,都邑有一個內存收受接管機制來釋放過時對象的內存,以包管內存可以或許被反復應用。

內存收受接管機制依照完成腳色的分歧可以分為兩種,一種是法式員手動完成內存的釋放(好比C說話)另外一種則是說話內建的內存收受接管機制好比本文將要引見的java渣滓收受接管機制。

Java的渣滓收受接管機制

在法式的運轉時情況中,java虛擬機供給了一個體系級的渣滓收受接管(GC,Carbage Collection)線程,它擔任收受接管掉去援用的對象占用的內存。懂得GC的條件是懂得一些和渣滓收受接管相干的概念,下文逐個引見這些概念。

對象在jvm堆區的狀況

Java對象的實例存儲在jvm的堆區,關於GC線程來講,這些對象有三種狀況。

1. 可觸及狀況:法式中還有變量援用,那末此對象為可觸及狀況。

2. 可回生狀況:當法式中曾經沒有變量援用這個對象,那末此對象由可觸及狀況轉為可回生狀況。CG線程將在必定的時光預備挪用此對象的finalize辦法(finalize辦法繼續或重寫子Object),finalize辦法內的代碼有能夠將對象轉為可觸及狀況,不然對象轉化為弗成觸及狀況。

3. 弗成觸及狀況:只要當對象處於弗成觸及狀況時,GC線程能力收受接管此對象的內存。

GC為了可以或許准確釋放對象,必需監控每個對象的運轉狀況,包含對象的請求、援用、被援用、賦值等,GC都須要停止監控,所以不管一個對象處於上文中的任何狀況GC都邑曉得。

上文說到,GC線程會在必定的時光履行可回生狀況對象的finalize辦法,那末什麼時候履行呢?因為分歧的JVM完成者能夠應用分歧的算法治理GC,所以在任什麼時候候,開辟者沒法預感GC線程停止各項操作(包含檢測對象狀況、釋放對象內存、挪用對象的finalize辦法)的機會。固然可以經由過程System.gc()和Runtime.gc()函數提示GC線程盡快停止渣滓收受接管操作,然則這也沒法包管GC線程立時就會停止響應的收受接管操作。

內存洩漏

內存洩露指因為毛病的設計形成法式未能釋放曾經不再應用的內存,形成資本糟蹋。GC會主動清算掉去援用的對象所占用的內存。然則,因為法式設計毛病而招致某些對象一直被援用,那末將會湧現內存洩露。

好比上面的例子。應用數組完成了一個棧,有入棧和出棧兩個操作。

 

import com.sun.javafx.collections.ElementObservableListDecorator;
import com.sun.swing.internal.plaf.metal.resources.metal_sv;

import java.beans.ExceptionListener;
import java.util.EmptyStackException;

/**
 * Created by peng on 14-9-21.
 */
public class MyStack {
  private Object[] elements;
  private int Increment = 10;
  private int size = 0;

  public MyStack(int size) {
    elements = new Object[size];
  }

  //入棧
  public void push(Object o) {
    capacity();
    elements[size++] = o;
  }

  //出棧
  public Object pop() {
    if (size == 0)
      throw new EmptyStackException();
    return elements[--size];
  }

  //增長棧的容量
  private void capacity() {
    if (elements.length != size)
      return;
    Object[] newArray = new Object[elements.length + Increment];
    System.arraycopy(elements, 0, newArray, 0, size);
  }

  public static void main(String[] args) {
    MyStack stack = new MyStack(100);
    for (int i = 0; i < 100; i++)
      stack.push(new Integer(i));
    for (int i = 0; i < 100; i++) {
      System.out.println(stack.pop().toString());
    }
  }
}

這個法式是可用的,支撐經常使用的入棧和出棧操作。然則,有一個成績沒有處置好,就是當出棧操作的時刻,並沒有釋放數組中出棧元素的援用,這招致法式將一向堅持對這個Object的援用(此object由數組援用),GC永久以為此對象是可觸及的,也就加倍談不上釋放其內存了。這就是內存洩露的一個典范案例。針對此,修正後的代碼為:

//出棧
  public Object pop() {
    if (size == 0)
      throw new EmptyStackException();
    Object o = elements[--size];
    elements[size] = null;
    return o;
  }

以上這篇深刻懂得Java渣滓收受接管機制和內存洩露就是小編分享給年夜家的全體內容了,願望能給年夜家一個參考,也願望年夜家多多支撐。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved