日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

什么是 JVM

發(fā)布時(shí)間:2024/8/26 综合教程 41 生活家
生活随笔 收集整理的這篇文章主要介紹了 什么是 JVM 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

什么是 JVM

先來(lái)看下百度百科的解釋:

JVM 是 Java Virtual Machine(Java 虛擬機(jī))的縮寫,JVM 是一種用于計(jì)算設(shè)備的規(guī)范,它是一個(gè)虛構(gòu)出來(lái)的計(jì)算機(jī),是通過在實(shí)際的計(jì)算機(jī)上仿真模擬各種計(jì)算機(jī)功能來(lái)實(shí)現(xiàn)的。

晦澀難懂有沒有,簡(jiǎn)單理解就是說虛擬機(jī)是物理機(jī)的軟件實(shí)現(xiàn)。

Java 的設(shè)計(jì)理念是 WORA(Write Once Run Anywhere,一次編寫到處運(yùn)行)。編譯器將 Java 文件編譯為 Java .class 文件,然后將 .class 文件輸入到 JVM 中,JVM 執(zhí)行類文件的加載和執(zhí)行,最后轉(zhuǎn)變成機(jī)器可以識(shí)別的機(jī)器碼進(jìn)行最終的操作。

為什么要學(xué)習(xí) JVM

每個(gè) Java 開發(fā)人員都知道字節(jié)碼經(jīng)由 JRE(Java 運(yùn)行時(shí)環(huán)境)執(zhí)行。但他們或許不知道 JRE 其實(shí)是由 Java 虛擬機(jī)(JVM)實(shí)現(xiàn),JVM 分析字節(jié)碼,解釋并執(zhí)行它。作為開發(fā)人員,了解 JVM的 架構(gòu)是非常重要的,因?yàn)樗刮覀兡軌蚓帉懗龈咝У拇a。

但是 JVM 在幫我們實(shí)現(xiàn) Write Once Run Anywhere 的同時(shí),有利有弊,因?yàn)樵谶@個(gè)過程中涉及到了內(nèi)存管理,尤其是多線程情況下的內(nèi)存管理問題,所以我們更應(yīng)該學(xué)習(xí) JVM 的知識(shí)來(lái)幫助自己寫出更好的代碼。

根據(jù)上邊對(duì) JVM 的概念介紹我們知道,JVM 的主要作用在于以下兩方面,之后我們的介紹也會(huì)以此著手。

軟件層面的機(jī)器碼翻譯
內(nèi)存管理

最近也在學(xué)習(xí)《深入理解 Java 虛擬機(jī)》這本書,此處貼個(gè)書中的圖過來(lái):

下邊就詳細(xì)介紹一下這張圖中的各個(gè)組件

運(yùn)行時(shí)數(shù)據(jù)區(qū)

這個(gè)區(qū)域描述的是 Java 代碼運(yùn)行時(shí)的狀態(tài),是我們非常關(guān)注的一個(gè)狀態(tài)-程序運(yùn)行狀態(tài),因?yàn)槲覀儗懘a就是為了運(yùn)行,不運(yùn)行的狀態(tài)對(duì)我們是沒什么吸引力的。說白了 Java 代碼不外乎數(shù)據(jù) 指令 控制這三類型語(yǔ)句,所以我們將 JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)可以劃分為如下兩大類:

數(shù)據(jù)

方法區(qū)
堆(Heap)

指令

虛擬機(jī)棧
本地方法棧
程序計(jì)數(shù)器

程序計(jì)數(shù)器

定義:指向當(dāng)前線程正在執(zhí)行的字節(jié)碼指令的地址也就是行號(hào)。

注意:我們需要思考一個(gè)問題,我的當(dāng)前線程本身已經(jīng)在執(zhí)行了,為什么還要找個(gè)寄存器把他的執(zhí)行行號(hào)記錄下來(lái)呢?

因?yàn)槲覀兂绦驁?zhí)行的最小單位是線程,而線程在 CPU 上執(zhí)行的時(shí)候是搶占式的,這樣的話就存在線程被掛起的情況,例如:有 A B 兩個(gè)線程,如果 A 線程執(zhí)行過程被 B 線程搶占了 CPU,則需要把掛起的 A 線程 當(dāng)前執(zhí)行到的行號(hào)存儲(chǔ)下來(lái),等到 A 重新獲得 CPU 時(shí)間片執(zhí)行權(quán)的時(shí)候去程序計(jì)數(shù)器獲得上一次執(zhí)行的行號(hào)以便于繼續(xù)執(zhí)行這個(gè)程序。

所以,每個(gè)線程都有自己的 程序計(jì)數(shù)器,而且是互不干擾的,屬于線程私有區(qū)域

如果執(zhí)行的是一個(gè) Java 方法,計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址
如果執(zhí)行的是一個(gè) Native 方法,計(jì)數(shù)器的值則為空(undefined)

虛擬機(jī)棧

定義:存儲(chǔ)當(dāng)前線程運(yùn)行方法所需要的數(shù)據(jù)、指令和返回地址,生命周期與線程相同,同樣屬于線程私有區(qū)域。

每個(gè) Java 方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀用于存儲(chǔ)局部變量、操作數(shù)棧、方法出口等信息,

如下所示,這個(gè)棧幀會(huì)存儲(chǔ)的信息包括:

局部變量表

操作數(shù)棧

動(dòng)態(tài)鏈接

出口

… …

每一個(gè)方法從調(diào)用直至執(zhí)行完成的過程,其實(shí)真正對(duì)應(yīng)的是一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過程。

其中局部變量表存放了編譯器可知的各種基本數(shù)據(jù)類型、引用對(duì)象等。需要注意的是因?yàn)榫植孔兞勘砜臻g長(zhǎng)度只有 32 位,如果是 long 和 double 類型的話會(huì)占用 2 個(gè)局部變量表空間,其他數(shù)據(jù)類型只占用 1 個(gè)。

注意:局部變量表所需的內(nèi)存空間在編譯期間就會(huì)車隊(duì)分配完成,因?yàn)樵谶M(jìn)入一個(gè)方法時(shí),這個(gè)方法需要在棧幀中分配多大的局部空間是完全確定的,方法運(yùn)行期間局部變量大小是不會(huì)改變的。

本地方法棧

和虛擬機(jī)棧類似,只不過他存儲(chǔ)的是當(dāng)前線程調(diào)用的本地方法所需要的數(shù)據(jù)、指令和返回地址等,本地方法時(shí)標(biāo)識(shí)有 Native 關(guān)鍵字的方法,此處就不展開描述了,參考上述虛擬機(jī)棧的介紹。

另外,根據(jù)《深入理解 Java 虛擬機(jī)》這本書的介紹,有些虛擬機(jī)(如 Sun HotSpot 虛擬機(jī))直接就把本地方法棧和虛擬機(jī)棧合二為一了。

方法區(qū)

這塊區(qū)域?qū)儆诰€程共享群與,主要存儲(chǔ)的信息包括已被虛擬機(jī)你加載的類信息(類的元信息)、常量、靜態(tài)變量、JIT(編譯器編譯后的代碼)等數(shù)據(jù)。

方法區(qū)有一塊區(qū)域我們稱之為運(yùn)行時(shí)常量池,存放編譯期生成的各種字面量和符號(hào)引用,運(yùn)行時(shí)常量池有一個(gè)重要特征是具備動(dòng)態(tài)性,也就是說在運(yùn)行期間依然可以將新的常量放入池中,我們開發(fā)常用的有 String 類的 intern() 方法

堆(Heap)

屬于線程共享區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建,是虛擬機(jī)管理的內(nèi)存中最大的一塊。它的唯一作用就是存放對(duì)象實(shí)例。

根據(jù)虛擬機(jī)規(guī)范的描述是:所有的對(duì)象實(shí)例及數(shù)組都要在堆上分配。當(dāng)然隨著現(xiàn)在技術(shù)的發(fā)展優(yōu)化這個(gè)也變得沒有那么絕對(duì),后續(xù)會(huì)進(jìn)行分享。

這塊區(qū)域也是垃圾收集器管理的主要區(qū)域,現(xiàn)如今流行的垃圾回收器基本都采用的是分代收集算法,所以也就衍生了一些分代方式,

比如對(duì)于內(nèi)存模型的劃分,在 JDK1.8 以前的版本基本是這樣的:

新生代

Eden
s0
s1

老年代

永久代

在 JDK 1.8 以后的版本:

新生代

老年代

Meta Space

此處小提一下,之所以在 JDK 1.8 以后 有了 Meta Space,其設(shè)計(jì)的目的在于規(guī)避永久代溢出的問題,因?yàn)?Meta Space 是可以自動(dòng)擴(kuò)容的,就跟 Java 中的集合一樣。

以上種種的劃分方式,都是為了更好地回收內(nèi)存或者分配內(nèi)存,從下一篇開始就開始學(xué)習(xí)內(nèi)存分配及垃圾回收相關(guān)算法啦!

總結(jié)

JVM 負(fù)責(zé)軟件層面的機(jī)器碼翻譯,可以把我們寫的 .java 文件翻譯成機(jī)器可以識(shí)別的機(jī)器碼
JVM 負(fù)責(zé)內(nèi)存管理
JVM 的運(yùn)行時(shí)數(shù)據(jù)區(qū)包括方法區(qū)、堆、虛擬機(jī)棧、本地方法棧和程序計(jì)數(shù)器
JVM 中的方法區(qū)和堆區(qū)是所有線程共享的,其他區(qū)域都是線程獨(dú)享的

總結(jié)

以上是生活随笔為你收集整理的什么是 JVM的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。