成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊JVM基礎,快進來復習復習吧

開發 后端
本篇給大家介紹JVM、運行區數據、類加載機制。希望大家面試前能掌握和Jvm有關的知識。

[[375161]]

 大家好,今天總結了一下老生常談的 JVM,這也是面試必問的知識。

話不多說,整起來!

一、JVM 是什么?

1、Java 虛擬機(Jvm)是可運行 Java 代碼的假想計算機。

2、Jvm 充當著一個翻譯官的角色,我們平常所編寫出的 Java 程序,是不能夠被操作系統所直接識別的,這時候 JVM 的作用就體現出來了,它負責把我們的程序翻譯給系統“聽”,告訴它我們的程序需要做什么操作。

3、Jvm 針對每個操作系統開發其對應的解釋器,所以只要其操作系統有對應版本的 Jvm,那么這份 Java 編譯后的代碼就能夠運行起來,有句話大家一定聽說過:「Java 能一次編譯到處運行」,這就是原因所在。

二、Jvm 的體系架構?

Jvm 是這四部分組成:

  • 運行區數據
  • 類加載器
  • 執行引擎
  • 垃圾回收器

下面就聊聊這四個部分~~

2.1 運行區數據

Java 虛擬機在執行 Java 程序的過程中會把它所管理的內存劃分為若干個不同的數據區域,這些區域各有各的作用,各有各的生命周期。

有些區域隨著虛擬機進程的啟動而存在,有些區域則依賴用戶線程的啟動和結束建立和銷毀。

運行區數據的劃分:方法區、虛擬機棧,本地方法棧、堆、程序計數器


上面這張圖大家一定都見過,其實可以劃分的更細點,看下面的這兩張圖:


 


能看出 1.8 版本前后的差別么,下面就看看這些區域都干啥的~~

程序計數器

  • 其實你可以把它看作是當前線程執行的字節碼的行號指示器,在 Jvm 工作時,就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環,跳轉,異常處理,線程的恢復等工作都需要依賴程序計數器去完成。它就好像是一個路口的紅綠燈一樣。

特點:1、占用很小的內存 2、各線程私有

就比如下面字節碼一樣,每一行開頭的黃色數字,我們就可以認為它是程序計數器所存儲的內容:

  1. public void doSth1(); 
  2.    descriptor: ()V 
  3.    flags: ACC_PUBLIC 
  4.    Code: 
  5.      stack=2, locals=3, args_size=1 
  6.         0: ldc           #5 
  7.         2: dup 
  8.         3: astore_1 
  9.         4: monitorenter 
  10.         5: getstatic     #2 
  11.         8: ldc           #3 
  12.        10: invokevirtual #4 
  13.        13: aload_1 

虛擬機棧

  • 虛擬機棧,其描述的就是線程內存模型,也可以稱作線程棧,也是每個線程私有的,生命周期與線程保持一致。在每個方法執行的時候,jvm 都會同步創建一個棧幀去存儲局部變量表,操作數棧,動態連接,方法出口等信息。一個方法的生命周期就貫徹了一個棧幀從入棧到出棧的全部過程。

特點:1、隨線程而生、隨線程而死 2、先進后出

棧示意圖:


本地方法棧

  • 本地方法棧,和虛擬棧其實很相似的,我們知道,java 底層用了很多 c 的代碼去實現,而其調用 c 端的方法上都會有 native 來代表本地方法,而本地方法棧就是為其服務的。

特點:1、各線程私有 2、和本地方法有關

native 修飾的方法:

  1. public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5); 

  1. 堆可以說是 jvm 中最大的一塊內存區域了,它是所有線程共享,幾乎所有的對象實例都會在這里分配。
  2. java 堆是垃圾回收器主要回收的區域。從內存回收的角度來說,堆空間可以分為新生代和老年代,而新生代又可以分為伊甸區,Survivor 區。

特點:1、所有線程共享 2、占用大的內存空間 3、先進先出

堆的劃分:


方法區

  1. 方法區,也是各個線程共享的內存區域,它是用來被存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯后的代碼等數據。
  2. 從上面的圖,可以看到 1.8 之前和之后,方法區所在的位置是有差別的。在 Java 8 之前有個永久代的概念,實際上指的是 HotSpot 虛擬機上的永久代,它用永久代實現了 JVM 規范定義的方法區功能,這部分由于是在堆中實現的,受 GC 的管理,不過由于永久代有 -XX:MaxPermSize 的上限,所以如果大量地調用 String.intern 方法 (將字段串放入永久代中的常量區)或 動態生成類(將類信息放入永久代),很容易造成 OOM。
  3. 所以,在 Java 8 中就把方法區的實現移到了本地內存中的元空間中,這樣方法區就不受 JVM 的控制了,這個區域也就不會進行 GC,也因此提升了性能,正因為放到了本地內存,也就不存在由于永久代限制大小而導致的 OOM 異常了。
  4. 另外,運行時常量池也是方法區的一部分,用來存放編譯期生成的各種字面量和符號引用,這部分內容在類加載后進入該常量池中。

特點:1、所有線程共享 2、1.8 之后移到了元空間 3、涉及到常量池

直接內存

從上面的圖中,看到有直接內存這個區域

  • 直接內存,并不是虛擬機運行時數據區的一部分,其實可以理解為堆外內存,在一些場景下,比如:NIO 類引入了一種基于通道(Channel)與緩沖區(Buffer)的 IO 方式,它可以使用 Native 函數庫直接分配堆外內存,然后通過一個存儲 Java 堆中的對象作為這塊內存的引用,這樣能夠顯著提高性能,因為避免了 Java 堆和 Native 堆中來回復制數據。

2.2 類加載器

1、什么是類加載機制?

JVM 運行時,java 虛擬機會把描述類的數據從 Class 文件加載到內存,并對數據進行校驗、轉換、解析和初始化,最終形成可以被 jvm 可以直接使用的類型,這就是類加載機制。

2、說說類加載的過程?

開局一張圖:


這張圖說明了類從加載到虛擬機內存開始,到卸載出內存為止,它的整個生命周期。

一般來說,我們把 Java 的類加載過程分為三個主要步驟:加載、鏈接、初始化,具體行為在 Java 虛擬機規范里有非常詳細的定義。

1、首先是加載階段

  1. 它是 Java 將字節碼(jar 包)數據從不同的數據源讀取到 JVM 中,并映射為 JVM 認可的數據結構(Class 對象),
  2. 重點:加載階段是用戶參與的階段,我們可以自定義類加載器,去實現自己的類加載過程。
  3. 通過字節流將類的.class 文件中的二進制數據讀入到內存。然后在堆中創建 java.lang.class 對象,用來封裝類在方法區的數據結構
  4. 只會創建一個 Class 對象,該 Class 對象來描述有哪些構造方法,都有哪些成員變量

2、第二階段是鏈接,這是核心的步驟,簡單說是把原始的類定義信息平滑地轉化入 JVM 運行的過程中。這里可進一步細分為三個步驟:

① 驗證

  1. 這是虛擬機安全的重要保障,JVM 需要核驗字節信息是符合 Java 虛擬機規范的,否則就被認為是 VerifyError,這樣就防止了惡意信息或者不合規的信息危害 JVM 的運行,
  2. 驗證階段有可能觸發更多 class 的加載。

② 準備

  1. 創建類或接口中的靜態變量,并初始化靜態變量的初始值。
  2. 但這里的“初始化”和下面的顯式初始化階段是有區別的,
  3. 測重點在于分配需要的內存空間,不會去執行更進一步的 JVM 指令

這里的初始化是指:

1、8 種基本數據類型的默認初始值是 0。

2、引用類型默認的初始值是 null。

3、對于有 static final 修飾的常量會直接賦值,例如:static final int x=123;則 x 直接會初始化為 123。

③ 解析

  1. 在這一步會將常量池中的符號引用(symbolic reference)替換為直接引用。
  2. 符號引用就是唯一的字符串,直接引用可以理解為一個地址值和偏移量

3、最后是初始化階段

這一步真正去執行類初始化的代碼邏輯,包括靜態字段動作,以及執行類定定義中的靜態初始化塊內的邏輯編譯器在編譯階段就會把這部分邏輯整理好,父類型的初始化邏輯優先于當前類型的邏輯。

初始化順序:

  • 先是父類靜態域(靜態成員變量)或者靜態代碼庫塊
  • 然后是子類靜態域或者子類靜態代碼塊
  • 所以最先初始化的總是 java.lang.Object 類

三、什么時候會對類進行初始化?

通過 new 關鍵字實例化對象、讀取或設置類的靜態變量、調用類的靜態方法

通過反射發生上面的三種行為

初始化子類時,會觸發父類的初始化

作為程序入口運行,就是指的 main 方法

四、類加載器有哪些?

啟動類加載器:負責加載環境變量下 jre/lib 下面的 jar 文件

擴展類加載器:負責加載環境變量下 jre/lib/ext 目錄下面的 jar 包

應用類加載器:就是加載我們熟悉的 classpath 的內容

自定義加載器:繼承 ClassLoader 就可以實現

五、了解雙親委派模型嗎?


這是一張很經典的圖,通常情況下,各個類加載器的協作關系就是這樣的。

概念:就是說一個類加載器收到了類加載的請求,不會自己先加載,而是把它交給自己的父類去加載,層層迭代。

用上圖來說明就是如果應用程序類加載器收到了一個類加載的請求,會先給擴展類加載器,然后再給啟動類加載器,如果啟動類加載器無法完成這個類加載的請求,再返回給擴展類加載器,如果擴展類加載器也無法完成,最后才會到應用類加載器。

好處:1、避免重復加載 Java 類型 2、沙箱安全機制:保證核心的類不會被篡改。

六、classLoader與class.forName區別

  • class.forName()除了將類的.class 文件加載到 jvm 中之外,還會對類進行解釋,執行類中的 static 塊,當然你可以指定是否執行靜態塊。
  • classLoader 只干一件事情,就是將.class 文件加載到 jvm 中,不會執行 static 中的內容,只有在 newInstance 才會去執行 static 塊。

七、腦圖

最后送大家一張自己總結的腦圖呀


今天就寫到這里啦!!

給大家介紹了JVM、運行區數據、類加載機制。希望大家面試前能掌握和Jvm有關的知識。

 

責任編輯:姜華 來源: 狂聊Java
相關推薦

2020-03-27 08:43:20

Vueprops開發

2021-01-31 16:01:43

對象引用原始值

2009-10-15 09:40:00

CCNA復習攻略CCNA

2014-03-03 16:44:57

算法

2020-09-04 07:33:12

Redis HashMap 數據

2023-07-14 12:28:07

JVM優化操作

2010-09-02 14:40:06

華為認證

2009-06-18 09:51:25

Java繼承

2022-11-02 13:47:20

Redis進程內存

2023-09-01 08:59:57

2009-09-11 10:50:36

CCIE認證筆試經驗

2013-02-21 16:09:38

惠普打印機

2009-08-24 15:48:53

Java連接池

2012-01-11 13:04:40

JavaJVM

2011-01-18 11:53:50

軟件水平考試

2022-11-09 17:10:47

JVM內存區域

2020-02-24 21:43:36

avaJVM 級鎖線程安全

2023-07-31 07:48:43

Java內存虛擬機

2010-05-13 10:31:28

數據庫及其應用

2023-04-24 14:54:09

JVM性能調優
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩高清在线一区 | 91色综合 | 免费一区二区三区在线视频 | 九九九久久国产免费 | 久久久精品网 | 国产精品一区二区三区在线 | 亚洲成人毛片 | 在线视频h | 欧美美女二区 | 大香网伊人 | 精品中文字幕一区二区 | 成人 在线| 四虎成人精品永久免费av九九 | 久久精品国产一区二区三区不卡 | 色婷婷综合久久久中字幕精品久久 | 久草综合在线视频 | 国产av毛片 | av免费看在线 | 国产激情精品视频 | 国产高清久久久 | 亚洲精品在线看 | 91精品国产综合久久久久 | 99爱视频 | 国产欧美精品区一区二区三区 | 午夜爽爽爽男女免费观看影院 | 国产在线观看一区二区 | 亚洲国产一区二区三区在线观看 | 亚洲天天干| 99热这里都是精品 | 成人在线小视频 | 亚洲最大成人综合 | 欧美a级成人淫片免费看 | av国产精品毛片一区二区小说 | 三级国产三级在线 | 日韩在线看片 | 国产9 9在线 | 中文 | 久国久产久精永久网页 | 中文字幕一区二区三区四区五区 | 麻豆视频在线免费看 | 亚洲精品在线播放 | 狠狠狠|