我們一起聊聊JVM優化:JVM概述
一、什么是JVM
JVM是Java Virtual Machine(Java虛擬機)的縮寫,JVM是一種用于計算設備的規范,它是一個虛構出來的計算 機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。
二、JVM與操作系統
Java 是一門抽象程度特別高的語言,提供了自動內存管理等一系列的特性。這些特性直接在操作系統上實現是不太 可能的,所以就需要 JVM 進行一番轉換。
從圖中可以看到,有了 JVM 這個抽象層之后,Java 就可以實現跨平臺了。JVM 只需要保證能夠正確執行 .class 文 件,就可以運行在諸如 Linux、Windows、MacOS 等平臺上了。 而 Java 跨平臺的意義在于一次編譯,處處運行,能夠做到這一點 JVM 功不可沒。比如我們在 Maven 倉庫下載同一 版本的 jar 包就可以到處運行,不需要在每個平臺上再編譯一次。 現在的一些 JVM 的擴展語言,比如 Clojure、JRuby、Groovy 等,編譯到最后都是 .class 文件,Java 語言的維護 者,只需要控制好 JVM 這個解析器,就可以將這些擴展語言無縫的運行在 JVM 之上了。
我們用一句話概括 JVM 與操作系統之間的關系:JVM 上承開發語言,下接操作系統,它的中間接口就是字節碼。
三、JVM、JRE、JDK 的關系
JVM 是 Java 程序能夠運行的核心。但是需要注意,JVM 自己什么也干不了,你需要給它提供生產原料(.class 文 件) 。
僅僅是 JVM,是無法完成一次編譯,處處運行的。它需要一個基本的類庫,比如怎么操作文件、怎么連接網絡等。 而 Java 體系很慷慨,會一次性將 JVM 運行所需的類庫都傳遞給它。JVM 標準加上實現的一大堆基礎類庫,就組成 了 Java 的運行時環境,也就是我們常說的 JRE(Java Runtime Environment) 對于 JDK 來說,就更龐大了一些。除了 JRE,JDK 還提供了一些非常好用的小工具,比如 javac、java、jar 等。它 是 Java 開發的核心,讓外行也可以煉劍!
我們也可以看下 JDK 的全拼,Java Development Kit。我非常怕 kit(裝備)這個單詞,它就像一個無底洞,預示著 你永無休止的對它進行研究。JVM、JRE、JDK 它們三者之間的關系,可以用一個包含關系表示。
四、Java虛擬機規范和 Java 語言規范的關系
左半部分是 Java 虛擬機規范,其實就是為輸入和執行字節碼提供一個運行環境。右半部分是我們常說的 Java 語法 規范,比如 switch、for、泛型、lambda 等相關的程序,最終都會編譯成字節碼。而連接左右兩部分的橋梁依然是 Java 的字節碼。
如果 .class 文件的規格是不變的,這兩部分是可以獨立進行優化的。但 Java 也會偶爾擴充一下 .class 文件的格式, 增加一些字節碼指令,以便支持更多的特性。
我們可以把 Java 虛擬機可以看作是一臺抽象的計算機,它有自己的指令集以及各種運行時內存區域,學過《計算 機組成結構》的同學會在課程的后面看到非常多的相似性。
最后,我們簡單看一下一個 Java 程序的執行過程,它到底是如何運行起來的
這里的 Java 程序是文本格式的。比如下面這段 HelloWorld.java,它遵循的就是 Java 語言規范。其中,我們調用了 System.out 等模塊,也就是 JRE 里提供的類庫。
使用 JDK 的工具 javac 進行編譯后,會產生 HelloWorld 的字節碼。 我們一直在說 Java 字節碼是溝通 JVM 與 Java 程序的橋梁,下面使用 javap 來稍微看一下字節碼到底長什么樣子。
Java 虛擬機采用基于棧的架構,其指令由操作碼和操作數組成。這些 字節碼指令 ,就叫作 opcode。其中, getstatic、ldc、invokevirtual、return 等,就是 opcode,可以看到是比較容易理解的。 JVM 就是靠解析這些 opcode 和操作數來完成程序的執行的。當我們使用 Java 命令運行 .class 文件的時候,實際上 就相當于啟動了一個 JVM 進程。
然后 JVM 會翻譯這些字節碼,它有兩種執行方式。常見的就是解釋執行,將 opcode + 操作數翻譯成機器代碼;另 外一種執行方式就是 JIT,也就是我們常說的即時編譯,它會在一定條件下將字節碼編譯成機器碼之后再執行。