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

想要徹底搞懂JVM虛擬機,看了這篇就夠了

云計算 虛擬化
本文從頭讀到尾就是一個虛擬機大部分知識點的框架,就像一顆搜索樹一樣,我們想要了解哪一部分知識,就從根節點開始搜索,直到找到我們想要了解的知識所在的葉節點或者子樹。

 [[272380]]

引言

本文的使用方法:

本文從頭讀到尾就是一個虛擬機大部分知識點的框架,就像一顆搜索樹一樣,我們想要了解哪一部分知識,就從根節點開始搜索,直到找到我們想要了解的知識所在的葉節點或者子樹。不過如果把所有的知識都在一篇文章中列出來那文章就太長啦,很容易把握不住整體框架,所以本文中對于知識點的詳細介紹都以鏈接的形式給出,大家可以通過本文回憶 JVM 相關的知識,遇到想不起來的點可以點開相應的鏈接查看,這樣像考試一樣的學習方式,可以加深我們的印象,記憶效果將遠遠好于盯著文字硬背。

Content

  • 說說 Java 的內存管理機制
  • 說說 Java 虛擬機程序執行
  • 說說虛擬機性能監控及故障處理
  • 說說 JIT 優化
  • 說說 Java 的內存模型(JMM)
  • 項目推薦

說說 Java 的內存管理機制

和 C++ 相比,Java 的內存管理機制可謂是一大特色,程序員們不需要自己去寫代碼手動釋放內存了,甚至你想自己干虛擬機都不給你干這個事情的機會(就是說,我們是沒有辦法自動觸發 GC 的),虛擬機全權包辦了 Java 的內存控制權力。這看起來挺美好的,不過也意味著,一旦虛擬機疏忽了(感覺不能賴虛擬機,畢竟虛擬機也不知道你能把程序寫成那樣啊……),發生了內存泄漏,問題都不好查,所以知道虛擬機到底是怎么管的內存就十分重要啦。

虛擬機對內存的管理,其實就是收拾哪些存放我們不會再用的對象的內存,把它們清了拿來放新的對象。所以它首先需要研究下以下幾個問題:

  • 這堆報廢了的對象到底被放哪了?(Java 堆和方法區)
  • 5 個數據區域:程序計數器、Java 虛擬機棧、本地方法棧、Java 堆、方法區。
  • 這堆放報廢對象的地方會不會內存泄漏?或者換一個洋氣點的叫法,會不會 OOM?(每個區的 OOM)
  • 對象是咋被放到這些地方的?(堆中對象的創建)
  • 對象被安置好了之后虛擬機怎么再次找到它?(堆中對象的訪問)

知道對象都放哪了,虛擬機就知道去哪里找報廢的對象了,接下來就涉及到了 Java 的一大超級特色:垃圾收集(GC)了,垃圾收集,正如其名,就是把這些報廢的對象給清了,騰出來地方放新對象,它主要關心以下幾個事情:

  • 哪些內存需要回收?
  • 放對象的地方需要垃圾回收:Java 堆和方法區。
  • 什么時候回收?(判斷對象的生死)
  • 判斷對象報廢了沒的算法(重點):引用計數法 和 可達性分析法。
  • 如何回收?
  • GC 算法原理(垃圾收集算法)
  • 基礎:標記 - 清除算法
  • 解決效率問題:復制算法
  • 解決空間碎片問題:標記 - 整理算法
  • 進化:分代收集算法
  • GC 算法的真正實現:
  • 7 個葫蘆娃,哦不,垃圾收集器
  • 新生代:Serial、ParNew、Parallel Scavenge
  • 老年代:Serial Old、Parallel Old、CMS
  • 全能:G1
  • HotSpot 虛擬機如何高效實現 GC 算法

說完了對象是怎么被回收的,現在才算是把 Java 的內存管理機制需要用到的小零件給補全了。也就是說,Java 的內存管理流程應該是這樣滴:

根據新對象是什么對象給對象找個地放

發現內存中沒地放這個新對象了就進行 GC 清理出來點地方

真找不著地了就拋 OOM ……

虛擬機一般都用的是進化版的 GC 算法,也就是分代收集算法,也就是說,虛擬機 Java 堆中的內存是分為新生代和老年代的,那么給新對象找地方放的時候放哪呢?具體怎么放呢?放好了之后的對象會不會換個地呆呀?GC 什么時候進行?清理哪呢?……預知 Java 的內存管理機制的詳情如何,可以看看我的往期文章。

到此為止,Java 的內存管理機制也就說的差不多了。現在,我們已經知道一個對象是如何在虛擬機的操控下,在內存中走一遭的了。可是首先,對象肯定是根據我們寫的類創建的,那么我們寫的類到底是如何變為內存中的對象的呢?而且,我們創建對象當然是為了執行它里面的方法呀,那么這個方法是怎么被執行的呢?想要回答這些問題,就需要我們研究一下 Java 虛擬機是如何執行我們的程序的了。

說說 Java 虛擬機程序執行

想要執行 Java 程序,必然要先將 Java 代碼編譯成字節碼文件,也就是 Class 文件,這個編譯的過程我們暫且不談,主要說一下如果執行這個 Class 文件,所以首先我們要先來了解一下 Class 文件的組成結構。

在了解了組成結構之后,接下來需要考慮的事情是,我們該怎么把這個 .class 文件加載進內存,讓它變成方法區(Java 8 后變為了 Metaspace 元空間)的一個 Class 對象呢?(類的加載)。

虛擬機的類加載機制說頭可就多了,大家都喜歡揪著這問,其實主要就下面這 3 個過程:

  • 類加載的時機:在程序第一次主動引用類的時候。
  • 什么是主動引用和被動引用?
  • 什么是顯式加載和隱式加載?
  • 類的生命周期:加載 —— 驗證 —— 準備 —— 解析 —— 初始化 —— 使用 —— 卸載
  • 類加載器
  • 如何判斷兩個類 “相等”?
  • 類加載器的分類?
  • 什么雙親委派模型?
  • 破壞雙親委派模型?
  • 實現 Java 類的熱替換
  • 如何自定義類加載器?
  • 需要保留雙親委派模型:extends ClassLoader,重寫 findClass()
  • 破壞雙親委派模型:直接重寫 loadClass()

將類加載到內存之后,接下來就要考慮如何執行這個類中的方法了。我們知道 5 大內存區域中的 Java 虛擬機棧是服務與 Java 方法的內存模型,那么我們首先應該了解一下 虛擬機棧的棧幀到底是怎樣的結構,虛擬機棧的棧幀結構包括如下幾個部分:

  • 局部變量表(重要)
  • 操作數棧 & 動態連接 & 方法返回地址

了解了輔助方法執行的 Java 虛擬機棧的結構后,接下來就要考慮 Java 類中方法的調用了。就像將大象放進冰箱,方法的調用也不是上來就之間執行方法的,而是分為以下兩個步驟:

  • 方法調用:確定被調用的方法是哪一個
  • 基于棧的解釋執行:真正的執行方法的字節碼

為什么還要加一個方法調用的步驟呢?因為一切方法調用都是在 Class 文件中以常量池中的符號引用存儲的,這就導致了不是我們想要執行哪個方法就能立刻執行的,因為我們首先需要根據這個符號引用(其實就一字符串)找到我們想要執行的方法,而這一過程就叫做方法調用。當找到這個方法之后,我們才會開始執行這個方法,也就是基于棧的解釋執行。

想要調用一個方法,我們先來看一下虛擬機中有哪些指令可以進行方法調用:方法調用字節碼指令。

這些字節碼會觸發不同的方法調用,總體來說,有以下幾種:

  • 解析調用
  • 分派調用(沒有在解析調用中將符號引用轉化為直接引用的方法就只能靠分派調用了)
  • 靜態分派(方法重載)
  • 動態分派(方法重寫)

確定了要調用的方法具體是哪一個了之后,就可開始基于棧的解釋執行了,這個時候,方法才真正的被執行。

此外,還需要了解一下 Java 的動態類型語言支持。

說說虛擬機性能監控及故障處理

常用的 JDK 命令行工具:JDK 命令行工具。

JVM 常見的參數設置已經設置經驗可見:JVM 常見參數設置。

虛擬機調優案例分析可見:虛擬機調優案例分析。

說說 JIT 優化

JIT (Just In Time),也就是即時編譯,首先我們需要知道 什么是 JIT?

然后,對于 HotSpot 虛擬機內的即時編譯器運作過程,我們可以通過以下 5 個問題來研究它:

  • 為什么要使用解釋器與編譯器并存的架構?
  • 為什么虛擬機要實現兩個不同的 JIT 編譯器?
  • 什么是虛擬機的分層編譯?
  • 如何判斷熱點代碼,觸發編譯?
  • 什么是熱點代碼?(兩種)
  • 什么是 “多次” 執行?
  • HotSpot 采用的是基于計數器的熱點探測方法,并且為了對兩種熱點代碼進行探測,每個方法有 2 個計數器
  • 方法調用計數器
  • 回邊計數器
  • HotSpot 熱點代碼探測流程
  • 熱點代碼編譯的過程?

此外,JIT 并不是簡單的將熱點代碼編譯成機器碼就收工的,它還會對代碼的執行進行優化,主要有以下幾種經典的優化技術:

  • 公共子表達式消除【語言無關】
  • 數組范圍檢查消除【語言相關】
  • 方法內聯【最重要】
  • 逃逸分析【最前沿】

說說 Java 的內存模型(JMM)

這部分內容主要與并發編程的內容相關,所以詳細介紹會跳到另一個 repo:Java-Concurrency-in-Practice。

Java 的內存模型主要就是研究一個變量的值是怎么在主內存、線程的工作內存和 Java 線程(執行引擎)之間倒騰的。就是說雖然 Java 內存模型規定了所有變量都存儲在主內存中,但是每個線程都有一個自己的工作內存,里面存著從主內存拷貝來的變量副本,Java 線程要對變量進行修改,都是先在自己的工作內存中進行,然后再把變化同步回主內存中去。

這樣做是由于計算機的存儲設備和處理器的運算速度有著幾個數量級的差距,所以需要在主內存和 Java 線程間加入一個工作內存作為緩沖,但這也同時會導致主內存和工作內存間的緩存一致性問題,所以當兩個工作內存中關于同一個變量的值發生沖突時,需要一定的訪問規則來確定主內存以怎樣的順序同步這個變量,也就是說該聽哪個工作內存的。而 Java 的內存模型的主要目標就是定義這個規則,即虛擬機如何將變量存儲到內存或是從內存中取出的。

簡單的來講,就是掌握 Java 內存模型中的 8 個原子操作,并且知道 Java 內存間是如何通過這 8 個操作進行變量傳遞的。

其實 Java 的內存模型就是圍繞著在并發的過程中如何處理 原子性、可見性、有序性 這 3 個特征建立的。同時 Java 除了可以依靠 volatile 和 synchronized 來保證有序性外,它自己本身還有一個 Happens-Before 原則,依靠這個原則,我們就可以判斷并發環境下的兩個操作是否可能存在沖突了。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2018-09-11 14:47:51

面試Java虛擬機

2024-07-05 11:01:13

2022-02-22 08:55:29

SelectPoll/ Epoll

2020-09-09 12:55:28

Nginx高并發性能

2020-09-10 09:31:34

Nginx HTTP代理服務器

2022-04-07 13:02:53

前端緩存

2017-03-30 22:41:55

虛擬化操作系統軟件

2019-07-10 15:15:23

JVM虛擬機Java

2022-03-13 09:31:43

MQ消息隊列ActiveMQ

2019-08-16 09:41:56

UDP協議TCP

2021-09-30 07:59:06

zookeeper一致性算法CAP

2010-09-17 15:12:57

JVMJava虛擬機

2025-02-14 08:53:24

2019-10-31 09:48:53

MySQL數據庫事務

2021-05-07 07:52:51

Java并發編程

2022-03-29 08:23:56

項目數據SIEM

2020-05-08 16:55:48

Java虛擬機JVM

2011-06-22 13:35:55

JVM

2015-11-02 09:49:04

Android屏幕適配官方指導

2021-10-13 16:54:22

IPv6網絡5G
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一区二区三区四区五区中文 | 国产亚洲精品久久yy50 | 91精品国产综合久久久久久漫画 | 欧美精品二区 | 91免费在线视频 | 日本不卡免费新一二三区 | 亚洲精品国产一区 | 精品国产一级片 | 亚洲国产成人精品女人久久久野战 | 午夜色播 | 在线观看中文字幕视频 | 欧美视频中文字幕 | 日韩视频在线观看中文字幕 | 国产亚洲欧美另类一区二区三区 | 四虎影院新网址 | 毛片免费看 | 久久久国产视频 | 天天操天天摸天天爽 | 亚洲精品第一 | 国产精品免费一区二区三区四区 | 国产中文字幕亚洲 | 精品久久久久久久 | 久草资源网站 | 二区在线观看 | 免费在线观看91 | 欧美一页 | 久久久久国产 | 日日做夜夜爽毛片麻豆 | 在线一区 | www成人啪啪18 | 国产a区 | 国产在视频一区二区三区吞精 | 一区二区三区电影网 | 俺去俺来也www色官网cms | 久久久女| 亚洲一区二区三区四区五区午夜 | 欧美一区二区三区在线看 | 亚洲精品久久久久久久久久久久久 | 亚洲国产成人av | 新疆少妇videos高潮 | 成人h视频在线 |