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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jvm虚拟机_一文入门jvm虚拟机

發布時間:2023/12/19 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jvm虚拟机_一文入门jvm虚拟机 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方「10分鐘編程」關注我呦

讓我們每天「博學」一點點

一文帶你理解JVM

1、jdk、jre、jvm的區別與聯系

jdk的全稱是Java Development kit(java開發工具包),我們可以把程序設計語言、java虛擬機、java類庫這三部分統稱為jdk,jdk是用于支持java程序開發的最小環境。Developer可以很容易的使用里面的方法以減少代碼量,里面同時包含jre和一些開發的小工具(如編譯工具javac),同時包含了jre。

jre的全稱是Java Running Environment(java運行時環境 ),可以把java類庫API中的javaSE的API子集和java虛擬機這兩部分統稱為JRE,JRE是支持java程序運行的標準環境。

jvm的全稱java virtual machine(java 虛擬機),它只認識XXX.class文件,虛擬機可以識別這種文件的字節碼指令并調用操作系統上的API,正是這個原因,java才可以跨平臺使用。

2、代碼是如何執行的

jvm是一個軟件,它幫我們屏蔽了底層的操作系統、硬件、CPU指令層的細節

它的口號是Write Once,Run Everywhere.我們來看一下代碼的執行流程。

圖中的Test.java文件是按照java語法規則編寫的源文件,是一種高級語言,.java文件經javac編譯后就生成字節碼文件,字節碼文件是用于給java虛擬機執行用的,該文件的格式規范受到java虛擬機的定義。而jvm的目的就是將字節碼文件Test.class翻譯為操作系統及硬件的指令,便于在不同的操作系統上執行。

NOTE:jvm虛擬機并不是僅僅只針對java語言,像一些其它編程語言如Groovy、Scala和Kotlin也可以在jvm虛擬機上運行上,這些語言僅僅需要實現一個編譯器,通過該編譯器把源代碼文件編譯成JVM能識別的字節碼文件即可。

3、JVM的內存結構

3.1類加載子系統

在java虛擬機中,負責查找并裝載類的部分稱為裝載子系統,裝載子系統用于定位和加載譯碼后的class文件。在加載階段,虛擬機需要完成以下事情

  • 通過一個類的全限定名來獲取定義此類的二進制字節流
  • 將這個字節流所代表的靜態存儲結構轉化為元空間中運行時的數據結構
  • 在內存中生成一個代表這個類的java.lang.Class對象,作為方法這個類的各種數據訪問入口

加載過程下圖所示

類的加載是通過查詢路徑的方式進行的,加載階段既可以使用虛擬機里內置的引導類加載器來完成,也可以由用戶自定義類加載器來完成。其加載順序如下

1、Bootstrap ClassLoader:啟動類加載器,加載存放在\lib目錄,或者被Xbootclasspath選項指定的jar包,如rt.jar、tools.jar

2、Extension ClassLoader:擴展類加載器,加載\lib\ext*.jar或者-java.ext.dirs指定目錄下的jar包

3、AppClassLoader:應用程序類加載器,加載Classpath或java.class.path所指定的目錄下的類和jar包

4、Custom ClassLoader:通過java.lang.ClassLoader的子類自定義加載class

實際上,上面描述的僅僅是類加載過程中的加載過程,類加載的整個過程包括:加載、驗證、準備、解析和初始化

字節碼--->加載--->驗證--->準備--->解析--->初始化,其中驗證、準備和解析階段可以統稱為鏈接階段。

下面我們講解每個階段的作用

  • 驗證:驗證是鏈接階段的第一步,這一階段的目的是確保Class文件的字節流包含的信息符合《java虛擬機規范》的全部約束要求,確保這些信息被當做代碼運行后不會危害虛擬機自身的安全
  • 準備:正式為類中定義的變量(靜態變量)分配內存并設置類變量初始值階段。
  • 解析:java虛擬機將常量池(元數據區的一部分)內的符號引用替換為直接引用過程
  • 初始化:類的初始化是類加載過程的最后一步,它的作用是真正開始執行類中編寫的java程序代碼

類加載會將類的信息加入到元數據空間。

如果一個類型從被加載到虛擬機內存開始,到出卸載為止,它的整個生命周期將在類加載的基礎上增加使用和卸載階段

3.2jvm內存部分(運行時數據區)

jvm在運行時會把它所管理的內存劃分為若干不同的數據區域,宏觀上可以劃分為兩部分

1、線程私有數據區(3個部分)

  • 程序計數器

①程序計數器是一塊內存較小的空間,它可以看做是當前線程執行的字節碼的行號指示器

②它是程序控制流的指示器,分支、循環、跳轉、異常處理、多線程恢復等基礎功能都需要依賴這個計數器來完成

③線程私有,各條線程之間計數器互不影響,獨立存儲,

④隨著線程的結束而結束,不需要垃圾回收

⑤不會出現OutOfMemoryError

  • 虛擬機棧

與程序計數器一樣,java虛擬機棧也是線程私有的,不會被GC回收,它的生命周期與線程相同,java虛擬機棧描述的是java方法執行線程的內存模型:每個方法被執行的時候(一個方法對應著一個棧幀),java虛擬機棧都會同步創建一個棧幀用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。當棧的深度大于虛擬機所允許的深度,將拋出StackOverflowError異常,如果java虛擬機的容量可以動態擴展,當棧擴展時無法申請到足夠的內存時將會拋出OutOfMemoryError異常。棧里面運行方法,存放方法的局部變量名,變量名所指向的值(常量值、對象值等)都存放在堆上。每一個方法被調用直至執行完畢的過程,就對應著一個棧幀在虛擬機棧從入棧到出棧的過程。

①局部變量表:是一組變量的存儲空間,用于存放方法的參數和方法內部定義的局部變量,局部變量分為兩種,分別是基本數據類型和引用類型(引用類型指向堆中對象的地址),常量值指向元空間。

②操作棧:操作棧也被稱為操作數棧,它是一個后入先出的棧。當一個方法剛開始執行的時候,這個方法的操作數棧是空的,在方法的執行過程中,會有各種字節碼指令往操作數棧中寫入和提取內容,也就是出棧和入棧操作,一個完整的方法執行期間往往包含多個這樣入棧和出棧的過程。操作數棧中元素的數據類型必須與字節碼指令的序列嚴格匹配。

③動態鏈接:每個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用,持有這個引用是為了支持方法調用過程中的動態鏈接。一個方法要調用其它方法,需要將這些方法的符號引用轉化為其內存地址的直接引用,而符號引用存在于方法區中的運行時常量池,所有需要在運行時動態的將這些符號引用轉化為直接引用。

④返回地址:方法不管是正常執行結束還是異常退出,需要返回方法被調用的位置。

  • 本地方法棧

本地方法棧與虛擬機棧所發揮的作用是非常相似的,其區別在于虛擬機棧為虛擬機執行java方法(也就是字節碼)服務,而本地方法棧則是為虛擬機使用到的本地(Native)方法服務。與虛擬機棧一樣,本地方法棧也會在棧深度溢出或者棧擴展失敗時分別拋出StackOverflowError和OutOfMemoryError。線程私有,不會被GC回收。

有的虛擬機直接將虛擬機棧和本地方法棧合二為一,不在單獨考慮。

總結:線程私有的三個部分都是隨著線程執行結束而結束(JVM就銷毀了虛擬機棧里面的棧幀)。

2、線程公有數據區(2個部分)

  • 元空間

在jdk1.8之前,元空間所在的區域被稱為方法區,方法區在jdk1.7時合并到了堆。

jdk1.8時,方法區所在的區域被稱為元空間,但是1.8仍然保留著方法區的概念,只不過實現方式不同,元空間與堆不相連,但與堆共享物理內存,邏輯上可以認為在堆中。

元空間的特點

①線程共享

②存儲類信息、常量、運行時常量池、靜態變量、即時編譯器編譯后的代碼等數據

③在jdk1.7之前,在HotSpot虛擬機上將方法區成為永久代,在jdk1.8時,完全放棄了永久代,改用了元空間

④因為效率問題,無垃圾回收

⑤空間不夠時,OutOfMemoryError

⑥設置元空間的大小--XX:Metaspace=10M-XX:MetaspaceSize=10M

運行時常量池的特點

運行時常量池是元空間的一部分,Class文件除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池表,用于存放編譯期生成的各種字面量的符號引用,這部分內容將在類加載后存放到元空間的運行時常量池中。

總結

jdk1.6及之前:有永久代,常量池在方法區

jdk1.7:從某個版本開始去除永久代,常量池1.7放入堆中

jdk1.8及之后:無永久代,常量池1.8在元空間。

java堆(heap)是虛擬機所管理的內存中最大的一塊,java堆是被所有線程共享的一塊內存區域,在虛擬機啟動時創建,幾乎所有的對象實例和數組都在堆上分配。

java堆是垃圾收集器管理的內存區域,從回收的角度看,由于現代垃圾收集器大部分都是基于分代收集理論設計的,所以java堆可以分為新生代和老年代,新生代又可以分為Eden空間、From Survivor空間和To Survivor空間,無論怎樣劃分,都是為了更好的進行垃圾回收。

java堆可以被實現成固定大小的,也可以是擴展的(通過-Xmx和-Xms設定)。如果在java堆中沒有內存完成實例分配,并且堆無法在擴展時,java虛擬機將會拋出OutOfMemory異常。

在堆中加載實例對象的順序

當老年代空間滿時,將會拋出OutOfMemory異常。

java堆溢出

不斷創建對象又不釋放,當對象到達一定數量時,無堆空間時將會產生堆溢出

內存泄漏:GC Roots到對象之間有可達路徑卻無法回收(存在對象引用,卻沒有釋放)

內存溢出:內存溢出是指應用系統中存在無法回收的內存或使用內存過多,最終使得程序運行要用到的內存大于能提供的最大內存。在Java虛擬機中,GC Roots到對象之間無可達路徑,可以被收集,但對象還存活著,此時可以根據物理機內存適當的調大虛擬機參數-Xms、-Xmx,分析代碼是否對象生命周期過長。對象是否持有狀態時間過長。

參考文獻

[1]周志明.深入理解java虛擬機

[2]https://www.bilibili.com/video/BV13J411n72m?from=search&seid=7875422419866373500

看了這篇文章,你是否「博學」了點個「在看」,是對我最大的鼓勵!

總結

以上是生活随笔為你收集整理的jvm虚拟机_一文入门jvm虚拟机的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。