国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

深入理解Java虛擬機到底是什么

宋華 / 1319人閱讀

摘要:由虛擬機加載的類,被加載到虛擬機內(nèi)存中之后,虛擬機會讀取并執(zhí)行它里面存在的字節(jié)碼指令。虛擬機中執(zhí)行字節(jié)碼指令的部分叫做執(zhí)行引擎。

什么是Java虛擬機?

作為一個Java程序員,我們每天都在寫Java代碼,我們寫的代碼都是在一個叫做Java虛擬機的東西上執(zhí)行的。但是如果要問什么是虛擬機,恐怕很多人就會模棱兩可了。在本文中,我會寫下我對虛擬機的理解。因為能力所限,可能有些地方描述的不夠欠當。如果你有不同的理解,歡迎交流。

我們都知道java程序必須在虛擬機上運行。那么虛擬機到底是什么呢?先看網(wǎng)上搜索到的比較靠譜的解釋:

虛擬機是一種抽象化的計算機,通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的。Java虛擬機有自己完善的硬體架構,如處理器、堆棧、寄存器等,還具有相應的指令系統(tǒng)。JVM屏蔽了與具體操作系統(tǒng)平臺相關的信息,使得Java程序只需生成在Java虛擬機上運行的目標代碼(字節(jié)碼),就可以在多種平臺上不加修改地運行。

這種解釋應該算是正確的,但是只描述了虛擬機的外部行為和功能,并沒有針對內(nèi)部原理做出說明。一般情況下我們不需要知道虛擬機的運行原理,只要專注寫java代碼就可以了,這也正是虛擬機之所以存在的原因--屏蔽底層操作系統(tǒng)平臺的不同并且減少基于原生語言開發(fā)的復雜性,使java這門語言能夠跨各種平臺(只要虛擬機廠商在特定平臺上實現(xiàn)了虛擬機),并且簡單易用。這些都是虛擬機的外部特性,但是從這些信息來解釋虛擬機,未免太籠統(tǒng)了,無法讓我們知道內(nèi)部原理。

從進程的角度解釋JVM

讓我們嘗試從操作系統(tǒng)的層面來理解虛擬機。我們知道,虛擬機是運行在操作系統(tǒng)之中的,那么什么東西才能在操作系統(tǒng)中運行呢?當然是進程,因為進程是操作系統(tǒng)中的執(zhí)行單位。可以這樣理解,當它在運行的時候,它就是一個操作系統(tǒng)中的進程實例,當它沒有在運行時(作為可執(zhí)行文件存放于文件系統(tǒng)中),可以把它叫做程序。

對命令行比較熟悉的同學,都知道其實一個命令對應一個可執(zhí)行的二進制文件,當敲下這個命令并且回車后,就會創(chuàng)建一個進程,加載對應的可執(zhí)行文件到進程的地址空間中,并且執(zhí)行其中的指令。下面對比C語言和Java語言的HelloWorld程序來說明問題。

首先編寫C語言版的HelloWorld程序。

#include   
#include   
 
int main(void) {  
   printf("hello world
");  
   return 0;  
}

編譯C語言版的HelloWorld程序:

gcc HelloWorld.c -o HelloWorld

運行C語言版的HelloWorld程序:

zhangjg@linux:/deve/workspace/HelloWorld/src$ ./HelloWorld   
hello world

gcc編譯器編譯后的文件直接就是可被操作系統(tǒng)識別的二進制可執(zhí)行文件,當我們在命令行中敲下 ./HelloWorld這條命令的時候, 直接創(chuàng)建一個進程, 并且將可執(zhí)行文件加載到進程的地址空間中, 執(zhí)行文件中的指令。

作為對比, 我們看一下Java版HelloWord程序的編譯和執(zhí)行形式。

首先編寫源文件HelloWord.java :

public class HelloWorld {  
 
   public static void main(String[] args) {  
       System.out.println("HelloWorld");  
   }  
}

編譯Java版的HelloWorld程序:

zhangjg@linux:/deve/workspace/HelloJava/src$ javac HelloWorld.java   
zhangjg@linux:/deve/workspace/HelloJava/src$ ls  
HelloWorld.class  HelloWorld.java

運行Java版的HelloWorld程序:

zhangjg@linux:/deve/workspace/HelloJava/src$ java -classpath . HelloWorld   
HelloWorld

從上面的過程可以看到, 我們在運行Java版的HelloWorld程序的時候, 敲入的命令并不是 ./HelloWorld.class 。 因為class文件并不是可以直接被操作系統(tǒng)識別的二進制可執(zhí)行文件 。 我們敲入的是java這個命令。 這個命令說明, 我們首先啟動的是一個叫做java的程序, 這個java程序在運行起來之后就是一個JVM進程實例。

上面的命令執(zhí)行流程是這樣的:

java命令首先啟動虛擬機進程,虛擬機進程成功啟動后,讀取參數(shù)“HelloWorld”,把他作為初始類加載到內(nèi)存,對這個類進行初始化和動態(tài)鏈接(關于類的初始化和動態(tài)鏈接會在后面的文章中介紹),然后從這個類的main方法開始執(zhí)行。也就是說我們的.class文件不是直接被系統(tǒng)加載后直接在cpu上執(zhí)行的,而是被一個叫做虛擬機的進程托管的。首先必須虛擬機進程啟動就緒,然后由虛擬機中的類加載器加載必要的class文件,包括jdk中的基礎類(如String和Object等),然后由虛擬機進程解釋class字節(jié)碼指令,把這些字節(jié)碼指令翻譯成本機cpu能夠識別的指令,才能在cpu上運行。

從這個層面上來看,在執(zhí)行一個所謂的java程序的時候,真真正正在執(zhí)行的是一個叫做Java虛擬機的進程,而不是我們寫的一個個的class文件。這個叫做虛擬機的進程處理一些底層的操作,比如內(nèi)存的分配和釋放等等。我們編寫的class文件只是虛擬機進程執(zhí)行時需要的“原料”。這些“原料”在運行時被加載到虛擬機中,被虛擬機解釋執(zhí)行,以控制虛擬機實現(xiàn)我們java代碼中所定義的一些相對高層的操作,比如創(chuàng)建一個文件等,可以將class文件中的信息看做對虛擬機的控制信息,也就是一種虛擬指令。

編程語言也有自己的原理, 學習一門語言, 主要是把它的原理搞明白。 看似一個簡單的HelloWorld程序, 也有很多深入的內(nèi)容值得剖析。

JVM體系結構簡介

為了展示虛擬機進程和class文件的關系,特意畫了下面一張圖:

根據(jù)上圖表達的內(nèi)容,我們編譯之后的class文件是作為Java虛擬機的原料被輸入到Java虛擬機的內(nèi)部的,那么具體由誰來做這一部分工作呢?其實在Java虛擬機內(nèi)部,有一個叫做類加載器的子系統(tǒng),這個子系統(tǒng)用來在運行時根據(jù)需要加載類。注意上面一句話中的“根據(jù)需要”四個字。在Java虛擬機執(zhí)行過程中,只有他需要一個類的時候,才會調(diào)用類加載器來加載這個類,并不會在開始運行時加載所有的類。就像一個人,只有餓的時候才去吃飯,而不是一次把一年的飯都吃到肚子里。一般來說,虛擬機加載類的時機,在第一次使用一個新的類的時候。后面的文章會具體討論Java中的類加載器。

由虛擬機加載的類,被加載到Java虛擬機內(nèi)存中之后,虛擬機會讀取并執(zhí)行它里面存在的字節(jié)碼指令。虛擬機中執(zhí)行字節(jié)碼指令的部分叫做執(zhí)行引擎。就像一個人,不是把飯吃下去就完事了,還要進行消化,執(zhí)行引擎就相當于人的腸胃系統(tǒng)。在執(zhí)行的過程中還會把各個class文件動態(tài)的連接起來。關于執(zhí)行引擎的具體行為和動態(tài)鏈接相關的內(nèi)容也會在后續(xù)的文章中進行討論。

我們知道,Java虛擬機會進行自動內(nèi)存管理。具體說來就是自動釋放沒有用的對象,而不需要程序員編寫代碼來釋放分配的內(nèi)存。這部分工作由垃圾收集子系統(tǒng)負責。

從上面的論述可以知道, 一個Java虛擬機實例在運行過程中有三個子系統(tǒng)來保障它的正常運行,分別是類加載器子系統(tǒng), 執(zhí)行引擎子系統(tǒng)和垃圾收集子系統(tǒng)。 如下圖所示:

虛擬機的運行,必須加載class文件,并且執(zhí)行class文件中的字節(jié)碼指令。它做這么多事情,必須需要自己的空間。就像人吃下去的東西首先要放在胃中。虛擬機也需要空間來存放個中數(shù)據(jù)。首先,加載的字節(jié)碼,需要一個多帶帶的內(nèi)存空間來存放;一個線程的執(zhí)行,也需要內(nèi)存空間來維護方法的調(diào)用關系,存放方法中的數(shù)據(jù)和中間計算結果;在執(zhí)行的過程中,無法避免的要創(chuàng)建對象,創(chuàng)建的對象需要一個專門的內(nèi)存空間來存放。關于虛擬機運行時數(shù)據(jù)區(qū)的內(nèi)容,也會出現(xiàn)在后續(xù)的文章中。虛擬機的運行時內(nèi)存區(qū)大概可以分成下圖所示的幾個部分。(這里只是大概劃分, 并沒有劃分的很精細)

總結

寫到這里,基本上關于我對java虛擬機的理解就寫完了。這篇文章的主題雖然是深入理解Java虛擬機,但是你可能感覺一點也不“深入”,也只是泛泛而談。我也有這樣的感覺。限于自己水平有限,也只能這樣了,要是想深入理解java虛擬機,強烈建議讀一下三本書:

《深入Java虛擬機》

《深入理解Java虛擬機JVM高級特性與最佳實踐》

《Java虛擬機規(guī)范》

其實我也讀過這幾本書,但是它們對虛擬機的解釋也是基于一個外部模型,而沒有深入剖析虛擬機內(nèi)部的實現(xiàn)原理。虛擬機是一個大而復雜的東西,實現(xiàn)虛擬機的人都是大牛級別的,如果不是參與過虛擬機的實現(xiàn),應該很少有人能把它參透。后面的一些文章也參考了這三本書, 雖然講解Java語法的書不計其數(shù), 但是深入講解虛擬機的書, 目前為止我就見過這三本,并且網(wǎng)上的資料也不是很多。

最后做一個總結:

虛擬機并不神秘,在操作系統(tǒng)的角度看來,它只是一個普通進程。

這個叫做虛擬機的進程比較特殊,它能夠加載我們編寫的class文件。如果把JVM比作一個人,那么class文件就是我們吃的食物。

加載class文件的是一個叫做類加載器的子系統(tǒng)。就好比我們的嘴巴,把食物吃到肚子里。

虛擬機中的執(zhí)行引擎用來執(zhí)行class文件中的字節(jié)碼指令。就好比我們的腸胃,對吃進去的食物進行消化。

虛擬機在執(zhí)行過程中,要分配內(nèi)存創(chuàng)建對象。當這些對象過時無用了,必須要自動清理這些無用的對象。清理對象回收內(nèi)存的任務由垃圾收集器負責。就好比人吃進去的食物,在消化之后,必須把廢物排出體外,騰出空間可以在下次餓的時候吃飯并消化食物。

我有一個微信公眾號,經(jīng)常會分享一些Java技術相關的干貨;如果你喜歡我的分享,可以用微信搜索“Java團長”或者“javatuanzhang”關注。

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69204.html

相關文章

  • 從表到里學習JVM實現(xiàn)

    在社會化分工、軟件行業(yè)細分專業(yè)化的趨勢下,會真的參與到底層系統(tǒng)實現(xiàn)的人肯定是越來越少(比例上說)。真的會參與到JVM實現(xiàn)的人肯定是少數(shù)。 但如果您對JVM是如何實現(xiàn)的有興趣、充滿好奇,卻苦于沒有足夠系統(tǒng)的知識去深入,那么可以參考RednaxelaFX整理的這個書單。 showImg(http://segmentfault.com/img/bVbGzn); 本豆列的脈絡是:    1. JV...

    Cristic 評論0 收藏0
  • 深入理解虛擬虛擬性能監(jiān)控和故障處理工具

    摘要:監(jiān)控和故障處理工具顯示指定系統(tǒng)內(nèi)所有的虛擬機進程用于收集虛擬機各方面的運行數(shù)據(jù)。的常用功能選項測試上面輸出了我正在運行程序的包名下的類名虛擬機統(tǒng)計信息監(jiān)視工具使用于監(jiān)視虛擬機各種運行狀態(tài)信息的命令行工具。 《深入理解Java虛擬機:JVM高級特性與最佳實踐(第二版》讀書筆記與常見面試題總結 本節(jié)常見面試題(推薦帶著問題閱讀,問題答案在文中都有提到): JVM調(diào)優(yōu)的常見命令行工具有哪些?...

    jas0n 評論0 收藏0
  • Java虛擬中,字符串常量到底存放在哪

    摘要:的三種常量池此外,有三種常量池,即字符串常量池又叫全局字符串池文件常量池運行時常量池。開始虛擬機把字符串常量池位置從永久代挪到堆,又徹底取消,把諸如之類的元數(shù)據(jù)都挪到堆之外管理。 前言 前陣子和朋友討論一個問題: 字符串常量歸常量池管理,那比如 String str = abc; abc這個對象是放在內(nèi)存中的哪個位置,是字符串常量池中還是堆? 這句代碼的abc當然在常量池中,只有n...

    lewinlee 評論0 收藏0
  • java 基礎 - 收藏集 - 掘金

    摘要:基礎知識復習后端掘金的作用表示靜態(tài)修飾符,使用修飾的變量,在中分配內(nèi)存后一直存在,直到程序退出才釋放空間。將對象編碼為字節(jié)流稱之為序列化,反之將字節(jié)流重建成對象稱之為反序列化。 Java 學習過程|完整思維導圖 - 后端 - 掘金JVM 1. 內(nèi)存模型( 內(nèi)存分為幾部分? 堆溢出、棧溢出原因及實例?線上如何排查?) 2. 類加載機制 3. 垃圾回收 Java基礎 什么是接口?什么是抽象...

    makeFoxPlay 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<