論 Java 中的內存分配

-------------------------------------------------------------------------java

Java內存分配主要包括如下幾個區域:程序員

1. 寄存器:咱們在程序中沒法控制安全

2. :存放基本類型的數據和對象的引用,但對象自己不存放在棧中,而是存放在堆中spa

3. :存放用new產生的數據線程

4. 靜態域:存放在對象中用static定義的靜態成員指針

5. 常量池:存放常量code

6. 非RAM(隨機存取存儲器)存儲:硬盤等永久存儲空間對象

 ------------------------------------------------------------------------------------blog

一. 寄存器(Registers):接口

     這是速度最快的存儲場所,由於寄存器位於處理器內部,這一點和其餘的存儲媒介都不同。不過寄存器個數是有限的。

    在內存中的寄存器區域是由編譯器根據須要來分配的。咱們程序開發人員不可以經過代碼來控制這個寄存器的分配。

    因此說,這第一個存儲區域寄存器,咱們只可以看看,而不可以對其產生任何的影響。,也沒辦法在程序裏頭感受到寄存器的任何存在跡象。

    JVM只設置了4個最爲經常使用的寄存器。
  pc程序計數器
  optop操做數棧頂指針
  frame當前執行環境指針
  vars指向當前執行環境中第一個局部變量的指針
  全部寄存器均爲32位。
  pc用於記錄程序的執行。optop,frame和vars用於記錄指向Java棧區的指針。

 

二. 棧(Stack):

 又稱堆棧

   位於通常的RAM中。處理器經由指針提供直接支持。

   當程序配置一塊新的內存時,stack指針便日後移;釋放內存時,指針則往前移。

   這種方式不只很快,效率也高,速度僅次於寄存器。

   用於存放對象引用以及基本的數據類型對象,不能用於存儲Java對象自己。


三. Heap):
   一種通用的內存空間,用來存放Java對象。

   Heap不一樣於stack之處在於,編譯器不需知道究竟得從heap中配置多少空間,也不需知道從heap上配置的空間究竟須要存在多久。

   所以,自heap配置存儲空間能夠得到高度的彈性。每當你須要產生對象,只需在程序中使用new,那麼執行的時候,便會自heap配置空間。

   固然,你得爲這樣的彈性付出代價:從heap配置空間,比從stack配置,所耗費的時間多了很多。

 

 單論內存空間中的堆和棧:

   1.棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。Java自動管理棧和堆,程序員不能直接地設置棧或堆。

   2.優缺點:

      棧:

  棧的優點是,存取速度比堆要快,僅次於直接位於CPU中的寄存器

  但缺點是,存在棧中的數據大小與生存期必須是肯定的,缺少靈活性。另外,棧數據在多個線程或者多個棧之間是不能夠共享的,可是在棧內部多個值相等的變量是能夠指向一個地址的

      堆:

  堆的優點是能夠動態地分配內存大小,生存期也沒必要事先告訴編譯器,Java的垃圾收集器會自動收走這些再也不使用的數據。

  但缺點是,因爲要在運行時動態分配內存,存取速度較慢。

   3.棧有一個很重要的特殊性,就是存在棧中的數據能夠共享

 

四. 靜態域:

    靜態存儲區域就是指在固定的位置存放應用程序運行時一直存在的數據,Java在內存中專門劃分了一個靜態存儲區域來管理一些特殊的數據變量如靜態的數據變量,須要明確的一點就是,Java對象是不保存在這個地方的,而只是把對象中的一些特殊元素放置這。

    類變量也叫靜態變量,也就是在變量前加了static 的變量;
    實例變量也叫對象變量,即沒加static 的變量;
  區別在於:
     類變量和實例變量的區別在於:類變量是全部對象共有,其中一個對象將它值改變,其餘對象獲得的就是改變後的結果;而實例變量則屬對象私有,某一個對象將其值改變,不影響其餘對象;

  特色:

      這兒的「靜態」(Static)是指「位於固定位置」(儘管也在RAM裏)。程序運行期間,靜態存儲的數據將隨時等候調用。可用static關鍵字指出一個對象的特定元素是靜態的。但Java對象自己永遠都不會置入靜態存儲空間
    例:

public class A{
    static int a = 0; //類變量
    private int b = 0; //實例變量
}

public class B{
    public void main (String[] args){
        A a1 = new A();
        A a2 = new A();
        a1.a = 3; // 等同於 A.a = 3;
        a1.b = 4 ;
        System.out.println(a2.a); //結果爲3
        //類變量是針對全部對象的,因此a1改變a,a2的a也改變
        System.out.println(a2.b); //結果爲0
        //實例只改變自身的,因此a1對象的b改變,不影響對象a2的b變量
    }
} 

   

五. 常量池:

  常量池在java用於保存在編譯期已肯定的,已編譯的class文件中的一份數據。它包括了關於類,方法,接口等中的常量,也包括字符串常量,如String s = "java"這種申明方式;固然也可擴充,執行器產生的常量也會放入常量池,故認爲常量池是JVM的一塊特殊的內存空間。

  背景:

    在Java對象中還有一類特殊的元素,咱們叫作常量。因爲常量的值是穩定不變的,如圓周率。爲此把他們放在代碼的內部是可行的。

    不過有些時候,在進行一些嵌入式系統開發的時候,咱們每每不這麼作。而是會把常量元素跟代碼分開來保存。

    如咱們會根據狀況把常量的值存放在一些只讀存儲器中。這主要是爲了一些特殊的功能考慮的。

    如出於版權控制的須要。如在打印機上爲了保護原裝耗材的版權,每每把常量跟代碼分開存放

特色:

    在Java程序中,有不少的東西是永恆的,不會在運行過程當中變化。

          好比一個類的名字,一個類字段的名字/所屬類型,一個類方法的名字/返回類型/參數名與所屬類型,一個常量,還有在程序中出現的大量的字面值。

   常數值一般直接置於程序代碼內部。這樣作是安全的,由於它們永遠都不會改變。有的常數須要嚴格地保護,因此可考慮將它們置入只讀存儲器(ROM)。

 

六.  非RAM存儲:

  若數據徹底獨立於一個程序以外,則程序不運行時仍可存在,並在程序的控制範圍以外。其中兩個最主要的例子即是「流式對象」和「固定對象」。對於流式對象,對象會變成字節流,一般會發給另外一臺機器。而對於固定對象,對象保存在磁盤中。

  即便程序停止運行,它們仍可保持本身的狀態不變。對於這些類型的數據存儲,一個特別有用的技巧就是它們能存在於其餘媒體中。一旦須要,甚至能將它們恢復成普通的、基於RAM的對象

   背景:  

  有時候,有些程序運行所須要的數據咱們還會放置在其餘地方。如在一些系統中須要用到流對象,這個對象的數據並無保存在上面所談到的任何一個存儲區域,這個對象直接被轉爲爲字節流,發送到其餘的主機上去了。另外有一種叫作持久化的對象,其是被存儲在硬盤中的

 

七. 論各種型內存的執行速度:

  寄存器 > 堆棧 > 堆 > 其餘

 

 

(C) 房上的貓 。 保留全部權利。
 https://www.cnblogs.com/lsy131479/

如需轉載,請註明出處!!!

相關文章
相關標籤/搜索