深入理解JVM(一)虛擬機內存


一 、前言

JVM是什么,我想諸位肯定都清楚。
好吧,我還是簡答說一下JVM即Java虛擬機(夠簡單吧 233333)。
雖然說,所有拋開操作系統,講虛擬機的內容,都是耍流氓。但是,貧僧不修善果,就愛殺人放火,就愛耍流氓。好吧,扯遠了。
言歸正傳,JVM這是第三遍重溫了。第一遍讀時,還是在飛機上讀的,就記得飛機上的陽光很刺眼,肚子很難受,從書中汲取的知識很少。第二遍讀時,是在做地鐵時看完的。地鐵很擠,書很好看。如今,距離上次讀完,已有一載有余,一年發生了很多事,朋友離開,公司散伙,親人重病。期間明白了很多道理。一個是,一定要好好的關愛你的親人。一個是,對於人重要的東西只有兩樣,健康的身體,以及獨立的靈魂。最近讀完了史鐵生的《我與地壇》對這兩點也是感觸頗多。
又扯遠了。下面進入正題。

二、 內存划分

總體划分如下:
在這里插入圖片描述

三、運行時數據區域

運行時數據區域,我們可以分為線程私有的數據區域,與線程共享的數據區域。線程私有,也就是線程內的數據,是能且僅能讓創建它的線程訪問。線程共享,是任何線程都可以訪問共享的此數據。

1、線程私有

(1)程序計數器
  • 程序計數器可以視為當前線程執行的字節碼行數指示器。(程序計數器是什么)
  • 多線程運行時,本質上,是線程的輪流切換。這一點,如果對操作系統還有記憶的同學,可能感覺如此之熟悉,是的單核的操作系統中,CPU在執行多任務時,就是將每個任務都執行一點,宏觀意義上來講,就達到了多任務同時進行的感覺。而當虛擬機中多線程執行時,線程執行了一半,就執行其他線程了,又一次回到此線程時,如何確保可以繼續執行線程,這里,就是程序計數器的意義所在了。(為什么要有程序計數器)
  • 一個線程有且僅有一個程序計數器。(有第一點和第二點而得出的結論)
(2)java虛擬機棧
[1]棧幀

在每個方法被創建時,同時也會創建一個棧幀。
一個方法被調用到被執行完畢的過程,就是一個棧幀,在虛擬機棧中,從入棧到出棧的過程。

[2]棧幀的數據結構

一個棧幀中包括了局部變量表、操作數棧、動態鏈接、以及方法出口
這里我們詳細的來說一下他的局部變量表
1)存放了基礎數據類型。
2)存放了對象的引用
3)存放了returnAddress:指向一條直字節碼令的地址

[3]基礎數據類型擴展

重溫此結的時候,突然想到了基礎數據的一個共同點。
他們都可以被轉為為int

    public static void main(String[] args) {
        int i = 1;
        short s = 1;
        float f = 1f;
        double d = 1;
        long l = 1L;
        char c = 63;
        byte b2 = 1;
        boolean b =  1;
		System.out.println("輸出char>>"+c);
    }

以上代碼在編譯期間,最后一行,也就是boolean會報錯,但是學過c或c++的都知道,bool類型,本質上,true為1,false為0。
而其他的都是可以正常賦值的。
char的賦值,大家可以猜猜,輸出的是多少。是63的ASCII值 "?"

輸出char>>?

(3)本地方法棧

本地方法棧,他與虛擬機棧類似(數據結構以及功能等方面)
不同的是,虛擬機棧執行的是java方法(編譯出的字節碼)。而本地方法棧執行的是Native方法。比如:

Thread類中的
private native void start0();

//調用dll或其他文件內方法
 public native static void  Hello();

有些虛擬機,他的本地方法棧與虛擬機棧會合並。

2、線程共享

(1)java堆
  • 堆內的數據,是所有線程共享的。
  • 幾乎所有的對象實例都在此存儲,因此,java堆又被稱為GC堆
(2)方法區
[1]方法區的數據結構

類信息:包括了類的版本、類中的字段、方法、接口以及常量池。常量池在編譯期就會確認並生成。
常量。
靜態常量。
編譯后的代碼。

[2] 邏輯上是堆的一部分,但他的別名是非堆。

2、非運行時數據區域

(1)直接內存

NIO使用此塊內存,以提高讀寫性能

四、參考

《深入理解java虛擬機》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM