java區域
『壹』 java線程存放在jvm的哪個區域方法又存放在哪個區呢
聊到JAVA中的方法,大多數人對於方法存儲在方法區還是棧區(虛擬機棧)是很迷茫的。其實方法是存在方法區的下面我們就細細說一下JVM中的 方法區 VS 棧區方法區:用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據,方法編譯出的位元組碼也是保存在這
『貳』 java虛擬機中內存規劃為哪些區域
一,jvm內存區域1,程序計數器一塊很小的內存空間,作用是當前線程所執行的位元組碼的行號指示器。2,java棧與程序計數器一樣,java棧(虛擬機棧)也是線程私有的,其生命周期與線程相同。通常存放基本數據類型,對象引用(一個指向對象起始
『叄』 java虛擬機規范中,哪個內存區域
Java虛擬機在執行Java程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。這些區域都有各自的用途,以及創建和銷毀的時
間,有的區域隨著虛擬機進程的啟動而存在,有些區域則是依賴用戶線程的啟動和結束而建立和銷毀。根據《Java虛擬機規范(第2版)》的規
定,Java虛擬機所管理的內存將會包括以下幾個運行時數據區域
『肆』 java內存模型和運行時的數據區域的區別
(1).程序計數器:
是一塊較小的內存空間,其作用可以看作是當前線程所執行的位元組碼的行號指示器,位元組碼解析器工作時通過改變程序計數器的值來選取下一條需要執行的位元組碼指令。程序的分支、循環、跳轉、異常處理以及線程恢復等基礎功能都是依賴程序計數器來完成。
Java虛擬機的多線程是通過線程輪流切換並分配處理器執行時間片來實現,在任何一個時刻,一個處理器只會執行一條線程指令,因此,為了確保線程切換之後能恢復到正確的執行位置,每條線程都需要一個獨立的程序計數器,因此程序計數器是線程私有的內存。
程序計數器是java虛擬機中唯一一個沒有規定任何內存溢出OutOfMemoryError的內存區域。
(2).java虛擬機棧:
Java虛擬機棧也是線程私有的,它的生命周期與線程相同。虛擬機棧描述的是java方法執行的內存模型:每個方法被執行時都會同時創建一個棧幀用於存放局部變數表、操作數棧、動態連接和方法出口等信息。每個方法被調用直至執行完成過程,就對應著一個棧幀在虛擬機中從入棧到出棧的過程。
Java虛擬機棧的局部變數表存放了編譯器可知的8種java基本類型數據、對象引用(注意不是對象實例本身)、方法返回地址returnAddress。
Java虛擬機棧的局部變數表空間單位是槽(Slot),其中64位長度的double和long類型會佔用兩個slot,其餘的數據類型只佔用一個slot。局部變數表所需內存空間在編譯期間完成分配,當進入一個方法時,該方法需要在幀中分配多大的局部變數空間是完全確定的,在方法運行期間不會改變局部變數表的大小。
Java虛擬機棧有兩種異常狀況:如果線程請求的棧深度大於虛擬機所允許的最大深度時,拋出StackOverflowError異常;如果虛擬機棧可以動態擴展,當擴展時無法申請到足夠內存時會拋出OutOfMemoryError異常。
(3).本地方法棧:
本地方法棧與java虛擬機棧作用非常類似,其區別是:java虛擬機棧是為虛擬機執行java方法服務,而本地方法棧是為虛擬機調用的操作系統本地方法服務。
Java虛擬機規范沒有對本地方法棧的實現和數據結構做強制規定,Sun HotSpot虛擬機直接把java虛擬機棧和本地方法棧合二為一。
與java虛擬機棧類似,本地方法棧也會拋出StackOverflowError異常和OutOfMemoryError異常。
(4).堆:
堆是java虛擬機所管理的內存區域中最大一塊,java堆是被所有線程所共享的一塊內存區域,在java虛擬機啟動時創建,堆內存的唯一目的就是存放對象實例。幾乎所有的對象實例都是在堆分配內存。
Java堆是垃圾收集器管理的主要區域,從垃圾回收的角度看,由於現在的垃圾收集器基本都採用的是分代收集演算法,因此java堆還可以初步細分為新生代和年老代。
Java虛擬機規范規定,堆可以處於物理上不連續的內存空間中,只要邏輯上是連續的即可。在實現上即可以是固定大小的,也可以是可動態擴展的。如果在堆中沒有內存完成實例分配,並且堆大小也無法在擴展時,將會拋出OutOfMemoryError異常。
(5).方法區:
方法區與堆一樣,是被各個線程共享的內存區域,它用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯後的代碼等數據。雖然java虛擬機規范把方法區描述為堆的一個邏輯部分,但是方法區卻有一個別名叫Non-Heap(非堆)。
Sun HotSpot虛擬機把方法區叫永久代(Permanent Generation),方法區中最重要的部分是運行時常量池。Class文件中除了有類的版本、欄位、方法、介面等描述信息外,還有一項信息是常量池,用於存放編譯期生成的各種字面變數、符號引用、直接引用等,這些內容將在類載入後存放到方法區的運行時常量池中,另外在運行期間也可以將新的常量存放到常量池中,如String的intern()方法。
方法區和運行時常量池在無法滿足內存分配時,也會拋出OutOfMemoryError異常。
(6).直接內存:
直接內存並不是java虛擬機運行時數據區的一部分,也不是java虛擬機規范中定義的內存區域,但是在java開發中還是會使用到。
JDK1.4中新引入的NIO(new I/O),引入了一種基於通道(Channel)和緩沖區(Buffer)的I/O方式,可以使用操作系統本地方法庫直接分配堆外內存,然後通過一個存儲在java堆裡面的DirectByteBuffer對象作為堆外直接內存的引用進行操作,避免了java堆內存和本地直接內存間的數據拷貝,可以顯著提高性能。
雖然直接內存並不直接收到java虛擬機內存影響,但是如果java虛擬機各個內存區域總和大於物理內存限制,從而導致直接內存不足,動態擴展時也會拋出OutOfMemoryError異常。
java虛擬機內存結構中的程序計數器、虛擬機棧和本地方法棧這三個區域隨線程創建而生,隨線程銷毀而滅,因此這三個區域的內存分配和回收是確定的,java垃圾收集器重點關注的是java虛擬機的堆內存和方法區內存。
『伍』 主內存與java內存區域(堆,方法區)有什麼區別
這兩天看了一下深入淺出JVM這本書,推薦給高級的java程序員去看,對你了解JAVA的底層和運行機制有
比較大的幫助。
廢話不想講了.入主題:
先了解具體的概念:
JAVA的JVM的內存可分為3個區:堆(heap)、棧(stack)和方法區(method)
堆區:
1.存儲的全部是對象,每個對象都包含一個與之對應的class的信息。(class的目的是得到操作指令)
2.jvm只有一個堆區(heap)被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身
棧區:
1.每個線程包含一個棧區,棧中只保存基礎數據類型的對象和自定義對象的引用(不是對象),對象都存放在堆區中
2.每個棧中的數據(原始類型和對象引用)都是私有的,其他棧不能訪問。
3.棧分為3個部分:基本類型變數區、執行環境上下文、操作指令區(存放操作指令)。
方法區:
1.又叫靜態區,跟堆一樣,被所有的線程共享。方法區包含所有的class和static變數。
2.方法區中包含的都是在整個程序中永遠唯一的元素,如class,static變數。
為了更清楚地搞明白發生在運行時數據區里的黑幕,我們來准備2個小道具(2個非常簡單的小程序)。
AppMain.java
public class AppMain
//運行時, jvm 把appmain的信息都放入方法區
{
public static void main(String[] args) //main 方法本身放入方法區。
{
Sample test1 = new Sample( " 測試1 " ); //test1是引用,所以放到棧區里, Sample是自定義對象應該放到堆裡面
Sample test2 = new Sample( " 測試2 " );
test1.printName();
test2.printName();
}
}
Sample.java
public class Sample //運行時, jvm 把appmain的信息都放入方法區
{
/** 範例名稱 */
private name; //new Sample實例後, name 引用放入棧區里, name 對象放入堆里
/** 構造方法 */
public Sample(String name)
{
this .name = name;
}
/** 輸出 */
public void printName() //print方法本身放入 方法區里。
{
System.out.println(name);
}
}
OK,讓我們開始行動吧,出發指令就是:「java AppMain」,包包里帶好我們的行動向導圖,Let』s GO!
系統收到了我們發出的指令,啟動了一個Java虛擬機進程,這個進程首先從classpath中找到AppMain.class文件,讀取這個文件中的二進制數據,然後把Appmain類的類信息存放到運行時數據區的方法區中。這一過程稱為AppMain類的載入過程。
接著,Java虛擬機定位到方法區中AppMain類的Main()方法的位元組碼,開始執行它的指令。這個main()方法的第一條語句就是:
Sample test1=new Sample("測試1");
語句很簡單啦,就是讓java虛擬機創建一個Sample實例,並且呢,使引用變數test1引用這個實例。貌似小case一樁哦,就讓我們來跟蹤一下Java虛擬機,看看它究竟是怎麼來執行這個任務的:
1、 Java虛擬機一看,不就是建立一個Sample實例嗎,簡單,於是就直奔方法區而去,先找到Sample類的類型信息再說。結果呢,嘿嘿,沒找到@@,這會兒的方法區里還沒有Sample類呢。可Java虛擬機也不是一根筋的笨蛋,於是,它發揚「自己動手,豐衣足食」的作風,立馬載入了Sample類,把Sample類的類型信息存放在方法區里。
2、 好啦,資料找到了,下面就開始幹活啦。Java虛擬機做的第一件事情就是在堆區中為一個新的Sample實例分配內存, 這個Sample實例持有著指向方法區的Sample類的類型信息的引用。這里所說的引用,實際上指的是Sample類的類型信息在方法區中的內存地址,其實,就是有點類似於C語言里的指針啦~~,而這個地址呢,就存放了在Sample實例的數據區里。
3、 在JAVA虛擬機進程中,每個線程都會擁有一個方法調用棧,用來跟蹤線程運行中一系列的方法調用過程,棧中的每一個元素就被稱為棧幀,每當線程調用一個方法的時候就會向方法棧壓入一個新幀。這里的幀用來存儲方法的參數、局部變數和運算過程中的臨時數據。OK,原理講完了,就讓我們來繼續我們的跟蹤行動!位於「=」前的Test1是一個在main()方法中定義的變數,可見,它是一個局部變數,因此,它被會添加到了執行main()方法的主線程的JAVA方法調用棧中。而「=」將把這個test1變數指向堆區中的Sample實例,也就是說,它持有指向Sample實例的引用。
OK,到這里為止呢,JAVA虛擬機就完成了這個簡單語句的執行任務。參考我們的行動向導圖,我們終於初步摸清了JAVA虛擬機的一點點底細了,COOL!
接下來,JAVA虛擬機將繼續執行後續指令,在堆區里繼續創建另一個Sample實例,然後依次執行它們的printName()方法。當JAVA虛擬機執行test1.printName()方法時,JAVA虛擬機根據局部變數test1持有的引用,定位到堆區中的Sample實例,再根據Sample實例持有的引用,定位到方法去中Sample類的類型信息,從而獲得printName()方法的位元組碼,接著執行printName()方法包含的指令。
『陸』 在Java中,為什麼靜態區域的方法不能調用非靜態區域的方法
理解起來很簡單,因為兩者的載入時機不同,靜態區的先載入,非靜態區的後載入。
具體說:
靜態區的方法,在虛擬機載入類文件(.class)的時候,就載入了,而非靜態區的方法,是直到有對象被new出來的時候才會載入。
也就是說,如果在非靜態區的方法載入之前就調用了它,顯然是無法調用到的。所以才會規定靜態方法中不能調用非靜態的。
『柒』 Java內存模型和Java內存區域的區別和聯系
內存模型就是各個區域的職責劃分,說起來是一個事情。
Java虛擬機在執行Java程序的過程中會把它所管理的內存劃分為若干個不同的數據區.這些區域有各自的用途,以及創建和銷毀時間,有的區域隨著虛擬機進程的啟動而存在,有的依賴用戶線程的啟動和結束而建立和銷毀,概括來說Java虛擬機包括以下幾個運行時數據區域,程序計數器,Java虛擬機棧,本地方法棧,Java堆,方法區,運行時常量池,(直接內存)
『捌』 java設計中如何編輯特定區域
可以使用Intellij Idea 2017編輯器對JAVA特定區域進行編輯。具體操作如下:
1、打開文件編輯,啟用活動編輯。