一個“Hello World”理解JVM運行時數據區

来源:https://www.cnblogs.com/JunFengChan/archive/2018/07/12/9250585.html
-Advertisement-
Play Games

先上一張JVM體繫結構圖: 1)運行時數據區:經過編譯生成的位元組碼文件(class文件),由class loader(類載入子系統)載入後交給執行引擎執行。在執行引擎執行的過程中產生的數據會存儲在一塊記憶體區域。這塊記憶體區域就是運行時區域 2)程式計數器:用於記錄當前線程的正在執行的位元組碼指令位置。由 ...


先上一張JVM體繫結構圖:

 

1)運行時數據區:經過編譯生成的位元組碼文件(class文件),由class loader(類載入子系統)載入後交給執行引擎執行。在執行引擎執行的過程中產生的數據會存儲在一塊記憶體區域。這塊記憶體區域就是運行時區域

2)程式計數器:用於記錄當前線程的正在執行的位元組碼指令位置。由於虛擬機的多線程是切換線程並分配cpu執行時間的方式實現的,不同線程的執行位置都需要記錄下來,因此程式計數器是線程私有的

3)虛擬機棧:虛擬機棧是java方法執行的記憶體結構,虛擬機會在每個java方法執行時創建一個“棧楨”,用於存儲局部變數表,操作數棧,動態鏈接,方法出口等信息。當方法執行完畢時,該棧楨會從虛擬機棧中出棧。其中局部變數表包含基本數據類型和對象引用;

   在java虛擬機規範中,對這個區域規定了兩種異常狀態:如果線程請求的棧的深度大於虛擬機允許的深度,將拋出StackOverFlowError異常(棧溢出),如果虛擬機棧可以動態擴展(現在大部分java虛擬機都可以動態擴展,只不過java虛擬機規範中也允許固定長度的java虛擬機棧),如果擴展時無法申請到足夠的記憶體空間,就會拋出OutOfmMemoryError異常(沒有足夠的記憶體)

4)本地方法棧:類似java方法的執行有虛擬機棧,本地方法的執行則對應有本地方法棧

5)方法區:用於存儲已被虛擬機載入的類信息,常量,靜態變數,即時編譯器編譯後的代碼等數據。線程共用(看存儲的數據就知道了)

     java虛擬機規範對方法區的限制非常寬鬆,除了和java堆一樣不需要連續的記憶體和可以選擇固定大小或者可擴展外,還可以選擇不實現垃圾收集。相對而言,垃圾收集在這個區域是比較少出現的,但並非數據進入了方法區就如永久代的名字一樣永久存在了。這區域的記憶體回收目標重要是針對常量池的回收和類型的卸載,一般來說這個記憶體區域的回收‘成績’比較難以令人滿意。尤其是類型的卸載條件非常苛刻,但是這部分的回收確實是必要的。在sun公司的bug列表中,曾出現過的若幹個嚴重的bug就是由於低版本的HotSpot虛擬機對此區域未完成回收導致的記憶體溢出。

6)java堆(java Heap):堆的主要作用是存放程式運行過程中創建的對象實例,因為要存放的對象實例有可能會極多,因此也是虛擬機記憶體管理中最大的一塊。並且由於硬體條件有限,所以需要不斷回收已“無用”的實例對象來騰出空間給新生成的實例對象;因此java的垃圾回收主要是針對堆進行回收的(還有方法區的常量池),java堆很多時候也被稱為GC堆(Garbage Collected Heap)。

7)類載入機制(Class Loader):類載入子系統是根據一個類的全限定名來載入該類的二進位流到記憶體中,在JVM中將形成一份描述Class結構的元信息對象(方法區),通過該元信息對象可以獲知Class的結構信息:如構造函數,屬性和方法等,Java允許用戶藉由這個Class相關的元信息對象間接調用Class對象的功能。

 

好!說了這麼多關鍵字,再拿例子來講解一下這些關鍵字:

A.圖1是我們寫的HelloWorld.java,通過IDE或命令:javac HelloWorld 編譯生成16進位的HelloWorld.class(位元組碼文件,見圖3),想讀懂16進位位元組可參考:一文讓你明白java位元組碼 ;但一般IDE會自動轉譯成圖2的指令;或者通過命令:javap -verbose HelloWorld 進行轉譯。

(圖1)HelloWorld.java

(圖2)HelloWorld.class

(圖3)16進位的位元組碼:

B.接著,當我們通過IDE或者命令:java HelloWorld 運行這個class文件時,位元組碼文件(class文件)通過類載入機制載入完畢交付給執行引擎執行;類載入機制把HelloWrold類的信息、靜態變數(例子中沒加)、常量(例子中沒加,常量會載入到方法區的常量池,這和靜態變數不一樣)等載入到方法區中,接下來如果需要創建該類的對象,需要通過new後面帶的參數到方法區進行查找類相關信息。

C.類載入完後,虛擬機會檢查程式的入口,虛擬機中程式的執行入口為main函數,如HelloWorld.class中,,執行引擎找到main函數開始執行指令,並生成一個“楨棧”入棧至虛擬機棧的棧頂;我們可以看到(圖2)在main方法下麵的命令:0  new java.lang.StringBuilder [16]  表示創建一個String對象,創建的String對象實例會在java堆(Heap)中分配記憶體存儲,並把該指令位置“0”記錄到當前線程的程式計數器中;3  dup 然後把該對象的引用壓入虛擬機棧中,並把該指令位置“3”記錄到當前線程的程式計數器中;4  ldc <String "Hello"> [18]字元串常量池(從jdk1.7開始,字元串常量池被移動到java堆)載入字元串常量Hello,並更新指令位置到程式計數器;...如果執行過程中有本地方法的指令,則會在本地方法棧中進行出入棧;這裡有個點註意一下,請看main函數指令16的位置: 16  new java.lang.StringBuilder [31] 這裡創建了一個StringBuilder對象,自jdk5開始已對這種類型的字元串拼接進行了優化,具體自行谷歌補充。

D.執行引擎執行指令過程中,按需調用本地庫介面以執行本地庫方法,如new指令、輸出屏幕等操作

 

以上就是一個HelloWorld執行過程在JVM中發生的事情。

 

 參考:

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

  https://www.cnblogs.com/IUbanana/p/7067362.html 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 下麵是在變數開始的時候定義初始值 ...
  • Description 聰聰和可可是兄弟倆,他們倆經常為了一些瑣事打起來,例如家中只剩下最後一根冰棍而兩人都想吃、兩個人都想玩兒電腦(可是他們家只有一臺電腦)……遇到這種問題,一般情況下石頭剪刀布就好了,可是他們已經玩兒膩了這種低智商的游戲。他們的爸爸快被他們的爭吵煩死了,所以他發明瞭一個新游戲:由 ...
  • 我們在上一篇搭建了一個簡單的springboot應用,這一篇將介紹使用spring-data-jpa操作資料庫。 新建一個MySQL資料庫,這裡資料庫名為springboot,建立user_info數據表,作為我們示例操作的表對象。 user_info信息如下: 資料庫及表創建成功後,回到我們的工程 ...
  • 好久不發文章了,難道是因為忙,其實是因為懶。這是一篇關於線程池使用和基本原理的科普水文,如果你經常用到線程池,不知道你的用法標準不標準,是否有隱藏的 OOM 風險。不經常用線程池的同學,還有對幾種線程的使用不甚瞭解的同學可以讀一下此文。 為什麼要使用線程池 雖然大家應該都已經很清楚了,但還是說一下。 ...
  • 集合 初次學習集合過程中的學習筆記,學習頂層,使用底層.包括常用的API Collection介面 概述 集合 : 集合是Java中提供的一種容器,可以用來存儲多個數據. 與數組的區別: 數組的長度是固定的,集合的長度是可變的. 數組只能存儲同一種數據類型,集合可以存儲任意數據類型. 數組可以存儲基 ...
  • 原文地址:https://medium.com/karachain/why-i-am-building-a-blockchain-in-go-6395a60b24dd Go語言現在常常被用來做去中心化系統(decentralised system)。其他類型的公司也都把Go用在產品的核心模塊中,並且 ...
  • https://blog.csdn.net/shengmingqijiquan/article/details/52634640 一.ArrayList概述 ArrayList 是一個數組隊列,相當於動態數組。與Java中的數組相比,它的容量能動態增長。它繼承於AbstractList,實現了Lis ...
  • 集合List下有2個子類,分別為ArrayList和LinkedList。 ArrayList:裡面實際為數組,動態大小。即創建ArrayList時自動創建數組大小,在後續添加數據時,數組長度不夠,會自動進行擴容。連續記憶體,增修查快、刪除慢。下方分別是圖形展示和部分實現代碼。 1 public cl ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...