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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

JVM入门到放弃之基本概念

發布時間:2023/12/10 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM入门到放弃之基本概念 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 基本概念

jvm 是可運行Java代碼的假想計算機,包括一套字節碼指令集、一組寄存器、一個棧、一個垃圾回收堆和一個存儲方法域。

jvm 是運行在操作系統之上的,屏蔽了與具體操作系統平臺相關的信息,使得Java程序只需生成在 jvm 上運行的字節碼,就可以在多種平臺上不加修改地運行。

Java 語言的一個非常重要的特點就是與平臺的無關性(跨平臺),其得益于 jvm,不是 Java 實現的跨平臺,而是 jvm 的跨平臺性,進而描述 Java 是跨平臺的。

我們知道,每個平臺的 api 肯定是不同的,就好比,android 實現動畫繪制肯定跟 ios 實現動畫繪制不同。jvm 通過 jit 即時編譯器解釋執行 Java 代碼,最終得到相同的字節碼,所以才有了經典的 "writ once,run anywhere"

通俗理解:jvm 運行在操作系統之上,其通過編譯器解釋執行 Java 代碼得到相同的字節碼,實現跨平臺性,進而描述 Java 語言跨平臺。

2. 運行過程

.java 源文件通過編譯器(假裝javac),能夠產生相應的 .class 文件(字節碼文件),
而字節碼文件又通過 jvm 中的解釋器,編譯成計算機真正識別的機器碼(二進制01)。

  • java源文件 > 編譯器 > 字節碼文件
  • 字節碼文件 > 解釋器 > 機器碼

每一種平臺的解釋器是不同的,但是實現的虛擬機是相同的,這也就是為什么 Java 能夠實現跨平臺的原因,當一個程序從開始運行時,虛擬機就開始實例化了,多個程序啟動,則存在多個虛擬機實例。程序退出或者關閉,則虛擬機實例消亡,多個虛擬機實例之間的數據不能共享。

通俗理解:java源文件通過編譯器得到字節碼文件,字節碼再通過解釋器獲得計算機真正可識別的機器碼。

3. 內存管理

對于 Java 程序員來說,在 jvm 自動內存管理機制幫助下,不需要在為每一個 new 操作去寫配對的 delete/free 代碼,正常情況下是不容易出現內存泄漏和內存溢出的問題。

jvm 在執行 Java 程序的過程中會把它所管理的內存劃分為若干個不同的數據區域,如圖所示。

針對上圖對運行時數據區域組成部分做簡單描述。

1.程序計數器

用于記錄當前線程所執行到的字節碼的行號。
怎么理解?舉個簡單的例子:


每一個線程都是順序執行單元,就如同上圖標記的行號一樣,是向下順序指定的,而程序計數器,就是用于標記行號的,遇到 if/else 則跳過不執行的行號,比如第 16 行是跳過的。

2.java虛擬機棧

虛擬機棧是為虛擬機執行 java 方法服務的,在了解虛擬機棧之前我們先了解一下 棧幀與局部變量表:

棧幀:每個方法執行都會創建一個棧幀,伴隨著方法從創建到執行完成。用于存儲局部變量表,操作數棧,動態鏈接,方法出口等。下圖為方法執行過程:

方法不停地調用,不停地進棧,如果棧內存滿了,就會 Stack Overflow Error 或者 Out of Memory

局部變量表:

  • 存放編譯器可知的各種基本數據類型、引用類型。
  • 局部變量表的內存空間在編譯器完成分配,當進入一個方法時,這個方法需要幀分配多少內存是固定的,在方法運行期間是不會改變局部表量表的大小,局部變量表存放的是對象的引用。
  • 在網上我們經常看到有人把 java 內存分為 堆內存 和 棧內存,這種分法是比較廣義的,內存的實際劃分是比較復雜的。這種劃分方式的流行只能說大多數人關注的是:與對象內存分配關系最親密的兩塊內存區域(棧堆)。其中 棧內存 就是上方的虛擬機棧,或者說是虛擬機棧中局部變量表部分。

    3.本地方法棧

    本地方法棧是為 native 方法服務的。

    native方法:

    • 簡單地講,一個 native 方法就是一個 Java 調用非 Java 代碼的接口。
    • 一個 native 方法是這樣一個 Java 的方法:該方法的實現由非 Java 語言實現,比如 C。
      這個特征并非 Java 所特有,很多其它的編程語言都有這一機制,比如在 C++ 中,你可以用extern "C"告知C++編譯器去調用一個 C 的函數。
    4.java堆

    Java 堆是 jvm 所管理的內存中最大的一塊,所有的對象實例以及數組都要在堆上分配。

    因為分的蛋糕比較大,固然成為 gc(垃圾回收器)經常光顧的主要區域。

    由于現在的收集器基本都采用分代收集算法,所以 Java 堆可以細分為:新生代、老年代、永久代(java8中移除了永久代),這一塊后面會單獨寫一篇關于垃圾回收器的文章,暫時有個印象即可。

    5.方法區

    方法區與 java 堆一樣,是各個線程共享的內存區域,用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。

    盡管 jvm 規范把方法區描述為堆的一個邏輯部分,但是它卻有一個別名叫非堆,目的區分堆。

    4. 對象的創建

    對象的創建過程:

  • 給對象分配內存
  • 線程安全性問題
  • 初始化對象
  • 執行構造方法
  • 1.給對象分配內存[位于棧中]

    對象的創建一般從 new 指令開始的,jvm 首先對符號引用進行解析,如果找不到對應的符號引用,那么這個類還沒有被加載,因此jvm便會進行類加載過程(關于類加載后面單獨文章講解),符號引用解析完畢之后,jvm 會為對象在堆中分配內存。

    2.線程安全性問題

    描述一種場景:正在給 A 對象分配內存,指針還沒來得及修改,對象 B 又同時使用了原來的指針來分配內存的情況。

    兩種解決方案:

  • 對內存分配內存空間的動作進行同步處理。
  • 把內存分配動作按照線程劃分在不同的空間之中進行。
  • 3.初始化對象

    對象創建后通常有個默認值。
    jvm 為對象分配完堆內存之后,jvm 會將該內存進行零值初始化,這也就解釋了為什么 Java 的屬性字段無需顯示初始化就可以被使用,而方法的局部變量卻必須要顯示初始化后才可以訪問。

    4.執行構造方法

    執行完上方三步,jvm 會調用對象的構造函數。

    至此,一個對象就被創建完畢。

    5. 最后總結

    jvm 的學習是比較枯燥乏味的,基本都是一些概念性問題,上文對 jvm 的基本概念以及內存區域做了簡單的介紹。
    工欲善其事,必先利其器。盡管 jvm 的學習非常無聊,但是卻非常重要,下面我用白話文根據自己的理解針對本文做一個總結。

    上邊有提到 "jvm 的跨平臺性,實現了java語言的跨平臺" ,何為跨平臺?通俗理解就是: 一個操作系統下開發的應用,放到另一個操作系統下依然可以運行。舉一個生動一點的例子,用 eclipse/idea 開發的 Java 程序,可以同時運行在 Linux、Windows 等操作系統上,即所謂的 "Write once, run anywhere(一次編寫,到處運行)" 。

    從廣義的層次理解了 jvm 的跨平臺性,接著是上文提到的 jvm 內存管理,jvm 有一套 自動內存管理機制,在該機制的幫助下,通常我們是不需要去關注對象的 內存分配以及釋放的,然后這套內存管理機制,會把他所管理的內存劃分為不同的運行時數據區域,而運行時數據區域由線程獨立以及線程共享兩部分組成。

    說到線程,何為線程呢?說到線程又不得不提進程….(果然坑越描越大)
    這里所說的線程是指程序執行過程中的一個線程實體,在講程序計數器時有提到,每一個線程都是順序執行單元,就好比一個簡單的main方法,是按照從上到下的順序執行的。線程之間又是有所區分的,比如虛擬機線程、gc線程、編譯器線程等,jvm 允許一個應用并發執行多個線程,就是所謂的多線程。

    關于線程、進程、多線程的關系。
    我們將王小工作的車間理解為進程,而線程則理解為車間里的工人,一個車間里肯定有很多工人 ,他們協同完成一個任務,也就是多線程完成一個進程。
    我們結合車間與工人,再來看看上邊提到的 "線程獨立" 與 "線程共享"。
    線程共享:車間的空間是工人們共享的,比如許多房間是每個工人都可以進出的。這表示一個進程的內存空間是共享的,每個線程都可以使用這些共享內存。
    線程獨立:王小所在的車間,只有一個廁所,而廁所的空間最多只能容納一個人,進入廁所后,是需要上鎖的,這樣別人才不能進來。里面有人的時候,其他人就不能進去,這代表一個線程使用某些共享內存時,其他線程必須等它結束,才能使用這一塊內存。

    了解了運行時數據區域劃分的線程概念,接著就是內存的各個組成區域,主要了解到 java堆,堆是用來存放對象實例以及數組的。每當你 new 一個對象,都是要在堆上拉取一塊內存區域的,通常一個程序要 new(實例化)很多對象,無形中帶來了內存負擔,所以就引出了 gc 垃圾回收的概念,我們可以將堆中的對象理解為 gc 的獵物,很顯然,對于富的流油的堆來說,自然成了 gc 主要的光顧對象。在這個地方我們提到了 新生代、老年代、永久代的概念,下一篇單獨講解。

    如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:niceyoo

    總結

    以上是生活随笔為你收集整理的JVM入门到放弃之基本概念的全部內容,希望文章能夠幫你解決所遇到的問題。

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