1. 程式人生 > >Java堆疊儲存以及Java Heap Space

Java堆疊儲存以及Java Heap Space

一,java記憶體分配

1.暫存器:程式無法控制

2.棧記憶體:存放基本型別的資料,以及物件的引用,但物件本身存放在堆記憶體中(自己總結:存放基本型別的變數資料和常量以及物件的引用)

3.堆記憶體:存放由new建立的物件和陣列

4.靜態域:存放物件中用static定義的靜態成員

5.常量池:存放基本常量和字串常量

6.非RAM儲存:磁碟等永久儲存空間

堆和棧:

           堆是由垃圾回收來負責的,可以動態分配記憶體大小,生存期不必告訴編譯器,缺點就是存取速度慢

           棧的存取速度較快,當程式執行到其作用域之外,就可以被釋放,棧的資料可以被共享

字串:  

          對於字串,如果是編譯器已經建立好的(String a=“qq”)就儲存在常量池中,如果是執行期建立的(通過new)就儲存在堆當中

成員變數和區域性變數在記憶體中的分配

  對於成員變數和區域性變數:成員變數就是方法外部,類的內部定義的變數;區域性變數就是方法或語句塊內部定義的變數。區域性變數必須初始化。 形式引數是區域性變數,區域性變數的資料存在於棧記憶體中。棧記憶體中的區域性變數隨著方法的消失而消失。 成員變數儲存在堆中的物件裡面,由垃圾回收器負責回收。

class BirthDate {
    private int day;
    private int month;
    private int year;

    public BirthDate(int d, int m, int y) {
        day = d;
        month = m;
        year = y;
    }
    // 省略get,set方法………
}

public class Test {
    public static void main(String args[]) {
        int date = 9;
        Test test = new Test();
        test.change(date);
        BirthDate d1 = new BirthDate(7, 7, 1970);
    }

    public void change(int i) {
        i = 1234;
    }
}

複製程式碼

對於以上這段程式碼,date為區域性變數,i,d,m,y都是形參為區域性變數,day,month,year為成員變數。下面分析一下程式碼執行時候的變化:    

  1. main方法開始執行:int date = 9; date區域性變數,基礎型別,引用和值都存在棧中。
  2. Test test = new Test();test為物件引用,存在棧中,物件(new Test())存在堆中。 
  3. test.change(date);  i為區域性變數,引用和值存在棧中。當方法change執行完成後,i就會從棧中消失。
  4. BirthDate d1= new BirthDate(7,7,1970); d1為物件引用,存在棧中,物件(new BirthDate())存在堆中,其中d,m,y為區域性變數儲存在棧中,且它們的型別為基礎型別,因此它們的資料也儲存在棧中。day,month,year為成員變數,它們儲存在堆中(new BirthDate()裡面)。當BirthDate構造方法執行完之後,d,m,y將從棧中消失。 
  5. main方法執行完之後,date變數,test,d1引用將從棧中消失,new Test(), new BirthDate()將等待垃圾回收。

問題分析:Java heap space

Java 記憶體洩漏的原因

     1.記憶體洩漏是指無用物件持續佔有記憶體或者無用物件得不到即使釋放

      2.長生命週期的物件持有段生命週期的引用就有可能發生記憶體洩漏

不健壯程式碼的特徵以及解決辦法

1.儘早釋放無用物件的引用,好的辦法就是使用臨時變數的時候,讓引用變數退出活動域後,自動設定為null,暗示垃圾回收來收集該物件,防止記憶體洩漏

2.避免使用大量的字串處理,避免使用String,因為String物件都得獨立佔用記憶體中的一塊區域,應該使用StringBudder代替

3.儘量少使用靜態變數,gc不會回收

4.避免集中建立物件,尤其是大物件,jvm會突然需要大量記憶體,這是必然會觸發gc優化系統環境,顯示的宣告陣列空間,而且申請數量還極大

5.儘量運用物件池技術以提高系統性能,例如大集合物件擁有大量資料量的業務物件的時候,可以考慮分塊處理

6.不要在經常呼叫的方法中建立物件,尤其是忌諱在迴圈中建立物件,可以適當的使用hashtable,vertor建立一組物件容器,然後從容器中去取那些物件,而不用每次new之後又丟棄

堆疊溢位一般調整的引數說明:

-Xss:單個執行緒的堆疊大小,jdk1.5以後每個堆疊大小為1m

-Xms:啟動應用時,堆疊記憶體的初始值大小

-Xmx:應用執行時,jvm(java虛擬機器)的極限值,為了不消耗擴大jvm堆控制元件分配的開銷,將此引數和-xms這倆個值設定為相等,一般設定為總記憶體的80%

-Xmn:此引數硬性規定堆記憶體新生代空間大小,推介為堆記憶體大小的1/4

-XX:PermSize應用伺服器啟動時,永久儲存區的初始值大小

-XX:MaxPermSize 應用伺服器執行期,永久儲存區的極限值大小

-XX:UserParNewGC 選擇垃圾收集器為並行收集器,此配置對年輕代有效,如果你的伺服器有多個CPU,開啟此引數,多個CPU併發垃圾回收

-XX:ParalleGCThreads 年輕代並行垃圾收集的前提下的執行緒數,即:同時多少個執行緒一起進行垃圾回收

-Xnoclassgc 每次永久儲存區滿了以後,一般gc演算法在做拓展分配記憶體前都會都會出發一次full gc,除非設定了-Xnoclassgc