在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Java程序是如何運行的

張康康 ? 2019-12-27 09:31 ? 次閱讀

JVM是Java的運行時虛擬機,所有的Java程序都是在JVM沙箱中運行,每個Java程序就是一個獨立的JVM進程。

談到Java程序是如何運行的,首先需要理解的肯定是JVM是如何運行的,什么是JVM;要理解我們編寫的Java程序,運行起來以后到底是什么樣子,本質上就是弄清楚JVM是什么樣子。

Java程序的代碼是什么樣的

Java誕生之初最大的賣點就是編寫的代碼跨平臺可移植性,實現這種可移植性,是因為Java通過平臺特定的虛擬機,運行中間的字節碼,而不是直接編譯成本地二進制代碼實現,中間字節碼也就是java文件編譯后生成的.class文件,Jar包的話,實際上只是一系列.class文件的集合。

編寫Java程序,首先需要一個入口點,在運行的時候通過指定MainClass來指定入口點,代碼層面主類必須實現一個靜態的main函數,運行時虛擬機會從MainClass.main開始執行指令,其他的邏輯只是import和函數調用了。

SDK自帶的javac命令,負責將我們編程的Java代碼,也就是.java文件,編譯成平臺無關的字節碼;字節碼可以在任何操作系統平臺上,通過平臺對應的JVM執行;JVM執行的時候,運行字節碼,根據自己的平臺特性,將字節碼轉換成平臺相關的二進制碼運行。

javac編譯器運行的過程大致分為:詞法分析(Token流)、語法分析(語法樹)、語義分析(注解語法樹),還有代碼生成器,根據注解語法樹,生成字節碼,

語義分析階段,編譯器會做一些操作,將人類友好的代碼,做一些處理,轉換成更符合機器執行機制的代碼,例如全局變量,魔法變量,依賴注入,注解這些魔法機制。大致分為以下步驟:

  1. 給類添加默認構造函數

  2. 處理注解

  3. 檢查語義的合法性并進行邏輯判斷

  4. 數據流分析

  5. 對語法樹進行語義分析(變量自動轉換并去掉語法糖)

JVM是什么

JVM = 類加載器 classloader + 執行引擎 execution engine + 運行時數據區域 runtime data area

JVM就是運行編譯好字節碼的虛擬機,不同的操作系統和平臺上,虛擬機將平臺無關的字節碼,編譯成特定平臺的指令去執行。我覺得,JVM首先是一個獨立運行在操作系統上的進程。執行java命令運行程序的時候,會啟動一個進程,每個獨立的程序就運行在一個獨立的JVM進程里。JVM負責執行字節碼,從而實現程序要完成的所有功能。

JVM主要由三部分組成:類加載器、運行時數據區和執行引擎。類加載器加載編譯好的.class文件,將所有類結構和方法變量放入運行時數據區,初始化之后,將程序的執行交給執行引擎;JIT編譯器,負責將字節碼編譯成平臺特定的二進制碼,調用本地接口庫。垃圾回收器作為執行引擎的一部分,負責維護運行時數據區中可變的應用程序內存空間。

類加載器(ClassLoader

類加載器將類加載到內存,并管理類的生命周期,知道將類從內存中卸載結束生命周期。

系統提供了三種類加載器,分別用于不同類的加載:

  1. 啟動類加載器(Bootstrap ClassLoader),該加載器會將lib目錄下能被虛擬機識別的類加載到內存中,也就是系統類

  2. 擴展類加載器(Extension ClassLoader),該加載器會將libext目錄下的類庫加載到內存

  3. 應用程序類加載器(Application ClassLoader),該加載器負責加載用戶路徑上所指定的類庫。

運行時數據區(Runtime Data Area

運行時數據區,是JVM運行時,在內存中分配的空間。

運行時數據區,被分為五個不同的結構:

  1. Java虛擬機棧(Java Stacks): 也叫棧內存,主管Java程序的運行,是在線程創建時創建,它的生命期是跟隨線程的生命期,線程結束棧內存也就釋放,對于棧來說不存在垃圾回收問題,只要線程一結束該棧就Over,生命周期和線程一致,是線程私有的。

  2. 本地方法棧(Native Method Memory): 登記的native方法,執行引擎執行時加載

  3. 程序寄存器(PC Registers): 當前線程所執行字節碼的指針,存儲每個線程下一步要執行的字節碼JVM指令。

  4. Java堆(Heap Memory): 應用的對象和數據都是存在這個區域,這塊區域也是線程共享的,也是gc 主要的回收區,一個 JVM 實例只存在一個堆類存,堆內存的大小是可以調節的。類加載器讀取了類文件后,需要把類、方法、常變量放到堆內存中,以方便執行器執行。

  5. 方法區(Method Area): 所有定義的方法的信息都保存在該區域,此區域屬于共享區間。靜態變量+常量+類信息+運行時常量池存在方法區中,實例變量存在堆內存中。

其中的程序寄存器、Java虛擬機棧是按照線程分配的,每個線程都有自己私有的獨立空間。

運行的方法和運行期數據,以棧幀的形式存儲在運行時JVM虛擬機棧中,棧幀中保存了本地變量,包括輸入輸出參數和本地變量;保存類文件和方法等幀數據,還記錄了出棧入棧操作。每一個方法被調用直至執行完成的過程就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。

堆在JVM是所有線程共享的,因此在其上進行對象內存的分配均需要進行加鎖。

執行引擎(Execution Engine

執行引擎由三個模塊組成,分別是執行引擎,JIT CompilerGarbage Collector,執行引擎的核心是Jit Compiler,執行字節碼或者本地方法;垃圾回收器,則是一系列線程,負責管理分代堆內存。

三個模塊分別是運行時計算和運行時內存的管理,負責執行運行時指令的是執行引擎,通過程序寄存器和虛擬機棧中的棧幀出入棧實現方法和指令的執行。GC則負責堆內存的管理,因為GC的時候需要停止指令的執行,消耗資源,所以采用分代方式管理對象收集。JIT則是把字節碼編譯成本地二進制代碼,并調用本地庫執行。

GC垃圾回收機制

Java的內存管理,主要是針對的堆內存,因為堆內存是運行時程序和數據分配的空間;不同于內存的其他區域,加載完程序之后,基本上可以確定需要占用的空間大小;heap memory 空間會在運行時動態的分配,無法預測,可大可小,而且快速變化,管理不慎就容易產生內存溢出,所以由JVM提供了強大的分代內存管理機制。

JVM 使用分代內存管理,來分配運行時的堆內存結構,針對不同的世代,采用不同的垃圾回收算法

常用垃圾回收算法

  • 引用計數器法(Reference Counting)

  • 標記清除法(Mark-Sweep)

  • 復制算法(Coping)

  • 標記壓縮法(Mark-Compact)

  • 分代算法(Generational Collecting)

  • 分區算法(Region)

堆內存的組成

heap 的組成有三區域/世代:分別是新生代(Young Generation)、老生代(Old Generation/tenured)和永久區(Perm)。

新生代堆內存又分成Eden區和兩個生存區,其中Eden區和生存區的占比為8:1:1,在清理新生代內存的時候,使用的是復制清除算法,優點是清除以后不會產生碎片;簡單的復制算法,將內存分成大小相同的兩個區域,每次周期只分配其中的一半,這樣空間利用率比較低,只使用了一半的內存。

考慮到新生代內存區的對象都是周期很短的,所以JVM實現了一種優化的復制算法,設置一個較大的Eden區來分配對象內存,Eden區空間不夠了觸發垃圾回收,將上一個生存區和Eden區中還存活的對象,復制到空閑的生存區。然后清空上述兩個區域,這樣就不會產生內存碎片。

將清理一定次數(15次)還生存的對象,定期晉升到老生代內存區,如果生存區空間不夠了,則馬上就會觸發晉升機制。將部分對象直接晉升到老生代。

如果晉升之后,發現老生代內存不夠,就會觸發完整的全局GC,清理老生代和新生代內存,老生代內存清理需要使用標記清除和標記整理兩種算法。

GC工作原理

分配內存的時候,首先分配到新生代的Eden區,如果Eden區滿了,就會發起一次Minor GC,將Eden和From Survivor生存的對象,拷貝到To Survivor Space,如果清理過程中,to Space的空間占用達到一定閾值,或者有對象經歷Minor GC的次數達標,就會將對象移動到老生代內存。如果移動過程中發現,老生代內存的空間已經不夠了。這時就需要發起Full GC,先進行一次Minor GC,然后通過CMS進行標記清除算法,清理老生代內存,老生代內存經歷標記清除之后,因為會產生內存碎片,還需要采用標記整理算法,將所有內存塊往前移動,形成連續的內存空間。

老生代標記清除的優點是不需要額外空間。不同于老生代清除算法,會產生碎片,而且標記算法的成本開銷也很大;在新生代清除中,因為考慮到大多數新生代對象生存期都是很短暫的,可以使用一種空間換時間的思路,拿出一部分內存空間不分配,而是作為中轉,將每次檢查時還生存的對象拷貝到Survivor Space,然后直接清除所有原區域的對象,因為大量對象都是生存周期極短的,所以Survivor Space的空間可以遠小于正常分配的空間。

不同于引用計數方法,Java使用一種 GC Roots 的對象作為起點開始檢查對象,當一個對象到 GC Roots 沒有任何引用鏈相連時, 即該對象不可達, 也就說明此對象是不可用的。就會在GC的時候收回。

GC清理類型的時候,為了防止程序地址出現異常,需要stop the world,清理線程會停止所有運行線程,直到清理完,這個時候是影響性能的。

垃圾回收器的本質

垃圾回收器在JVM層面,是由一系列不同的組件組成的,每種組件是一個獨立線程,分別執行自己的邏輯。

新生代垃圾收集器:

  1. Serial(串行)收集器是最基本、發展歷史最悠久的收集器,它是采用復制算法的新生代收集器,。它是一個單線程收集器,只會使用一個CPU或一條收集線程去完成垃圾收集工作,更重要的是它在進行垃圾收集時,必須暫停其他所有的工作線程,直至Serial收集器收集結束為止(“Stop The World”)。

  2. ParNew收集器就是Serial收集器的多線程版本,它也是一個新生代收集器。除了使用多線程進行垃圾收集外,其余行為包括Serial收集器可用的所有控制參數、收集算法(復制算法)、Stop The World、對象分配規則、回收策略等與Serial收集器完全相同,兩者共用了相當多的代碼。

  3. Parallel Scavenge收集器也是一個并行的多線程新生代收集器,它也使用復制算法。Parallel Scavenge收集器的特點是它的關注點與其他收集器不同,CMS等收集器的關注點是盡可能縮短垃圾收集時用戶線程的停頓時間,而Parallel Scavenge收集器的目標是達到一個可控制的吞吐量(Throughput)。

老生代垃圾收集器:

  1. Serial Old 是Serial收集器的老年代版本,它同樣是一個單線程收集器,使用“標記-整理”(Mark-Compact)算法

  2. Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法

  3. CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器,優點是:并發收集、低停頓,因此CMS收集器也被稱為并發低停頓收集器(Concurrent Low Pause Collector)

面向服務端的G1收集器。

G1收集器是一款面向服務端應用的垃圾收集器。

在使用G1收集器時,Java堆的內存布局和其他收集器有很大的差別,它將這個Java堆分為多個大小相等的獨立區域,雖然還保留新生代和老年代的概念,但是新生代和老年代不再是物理隔離的了,它們都是一部分Region(不需要連續)的集合。

GC回收的觸發條件

Minor GC觸發條件:當Eden區滿時,觸發Minor GC

Full GC觸發條件:

  1. gc()方法的調用

  2. 老年代代空間不足

  3. 方法區空間不足

  4. CMS GC時出現promotion failed和concurrent mode failure

  5. 統計得到的Minor GC晉升到舊生代的平均大小大于老年代的剩余空間

  6. 堆中分配很大的對象

  7. 通過Minor GC后進入老年代的平均大小大于老年代的可用內存

  8. 由Eden區、From Space區向To Space區復制時,對象大小大于To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小于該對象大小

GC Roots

在Java語言中,可以作為GC Roots的對象包括下面幾種:

  • 虛擬機棧(棧幀中的本地變量表)中引用的對象;

  • 方法區中類靜態屬性引用的對象;

  • 方法區中常量引用的對象;

  • 本地方法棧中JNI(即一般說的Native方法)引用的對象;

總結就是,方法運行時,方法中引用的對象;類的靜態變量引用的對象;類中常量引用的對象;Native方法中引用的對象。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    Java開發者必備的效率工具——Perforce JRebel是什么?為什么很多Java開發者在用?

    Perforce JRebel是一款Java開發效率工具,旨在幫助java開發人員更快地編寫更好的應用程序。JRebel可即時重新加載對代碼的修改,無需重啟或重新部署應用程序,就能讓開
    的頭像 發表于 04-27 13:44 ?164次閱讀
    <b class='flag-5'>Java</b>開發者必備的效率工具——Perforce JRebel是什么?為什么很多<b class='flag-5'>Java</b>開發者在用?

    如何在 樹莓派 上編寫和運行 C 語言程序

    在本教程中,我將討論C編程語言是什么,C編程的用途,以及如何在RaspberryPi上編寫和運行C程序。本文的目的是為您介紹在RaspberryPi上進行C編程的基礎知識。如果您想深入了解C編程
    的頭像 發表于 03-25 09:28 ?430次閱讀
    如何在 樹莓派 上編寫和<b class='flag-5'>運行</b> C 語言<b class='flag-5'>程序</b>?

    零基礎入門:如何在樹莓派上編寫和運行Python程序

    在這篇文章中,我將為你簡要介紹Python程序是什么、Python程序可以用來做什么,以及如何在RaspberryPi上編寫和運行一個簡單的Python程序。什么是Python
    的頭像 發表于 03-25 09:27 ?508次閱讀
    零基礎入門:如何在樹莓派上編寫和<b class='flag-5'>運行</b>Python<b class='flag-5'>程序</b>?

    Spire.XLS for Android via Java組件說明

    Spire.XLS for Android via Java 是一款專業的 Android Excel 組件,用于在 Android 手機應用程序中創建、操作和轉換 Excel 工作表,并且運行環境
    的頭像 發表于 01-24 12:16 ?422次閱讀
    Spire.XLS for Android via <b class='flag-5'>Java</b>組件說明

    華為云 Flexus X 實例下的場景體驗——小企業必備——JAVA 環境搭建——保姆級教學

    前言 上次我們使用的是 Ubuntu 來操作的,這里跑的服務器多的還是 Huawei Cloud EulerOS,所以我們還原到基礎鏡像上做環境架設,此次我們來架設 java 的基礎運行環境,是能
    的頭像 發表于 01-07 17:05 ?431次閱讀
    華為云 Flexus X 實例下的場景體驗——小企業必備——<b class='flag-5'>JAVA</b> 環境搭建——保姆級教學

    SSM框架在Java開發中的應用 如何使用SSM進行web開發

    SSM框架,即Spring、SpringMVC和MyBatis的整合,是Java Web開發中常用的技術棧。它通過分層架構,實現了視圖、控制、業務邏輯和數據訪問的分離,提高了代碼的可維護性和可擴展性
    的頭像 發表于 12-16 17:28 ?1458次閱讀

    Java 23功能介紹

    Java 23 包含全新和更新的 Java 語言功能、核心 API 以及 JVM,同時適合新的 Java 開發者和高級開發者。從?IntelliJ IDEA 2024.2?開始已支持 Java
    的頭像 發表于 12-04 10:02 ?854次閱讀
    <b class='flag-5'>Java</b> 23功能介紹

    Java代碼之美,從遵循樣式規范開始

    作者:京東零售 劉仲偉 在軟件開發的世界里,代碼不僅是程序的基石,更是程序員交流的通用語言。而Java,作為一門廣泛應用于企業級應用的編程語言,其代碼的可讀性和一致性對于項目的長期維護和團隊協作
    的頭像 發表于 11-27 11:42 ?515次閱讀
    <b class='flag-5'>Java</b>代碼之美,從遵循樣式規范開始

    Java集合API的改進介紹

    解答這些問題。 我們將逐步學習 Java 集合類的優化過程,并按版本逐一對比分析。主要討論的焦點將包括 JDK 1.0、1.2、1.4、1.5、1.6、1.8、9、10、11 和 21 版本的 Java 集合功能 Java 集合
    的頭像 發表于 11-22 11:12 ?511次閱讀
    <b class='flag-5'>Java</b>集合API的改進介紹

    對比Python與Java編程語言

    使得編寫代碼更加靈活,但也可能導致運行時錯誤。 Java 語法相對冗長,需要顯式聲明變量類型,增加了代碼的可讀性和安全性。 靜態類型系統在編譯時進行類型檢查,減少了運行時錯誤。 二、性能 Python 解釋型語言,
    的頭像 發表于 11-15 09:31 ?922次閱讀

    Java中時間戳的使用

    Java中時間戳的使用
    的頭像 發表于 11-06 16:04 ?465次閱讀
    <b class='flag-5'>Java</b>中時間戳的使用

    java反編譯能拿到源碼嗎

    在語法和風格上有所不同的代碼,因為它們主要關注于恢復代碼的邏輯結構,而不是精確復制原始代碼的每個細節。 1. 反編譯的基本原理 Java程序在編譯時,源代碼(.java文件)會被編譯成字節碼(.class文件),這些字節碼可以在
    的頭像 發表于 09-02 11:03 ?1668次閱讀

    keil軟件怎么運行寫好的程序

    Keil軟件是一款功能強大的嵌入式開發工具,廣泛應用于單片機、ARM、DSP等嵌入式系統的開發。本文將介紹如何使用Keil軟件運行寫好的程序。 安裝Keil軟件 首先,需要從Keil官網下載Keil
    的頭像 發表于 09-02 10:29 ?4187次閱讀

    linux驅動程序運行在什么空間

    Linux 驅動程序是操作系統的一部分,負責管理硬件設備與操作系統之間的交互。驅動程序運行在內核空間(Kernel Space),這是操作系統的核心部分,與用戶空間(User Space)相對。內核
    的頭像 發表于 08-30 14:37 ?808次閱讀

    華納云:java web和java有什么區別java web和java有什么區別

    的平臺,Java可以用于開發桌面應用程序、移動應用程序、企業級應用程序等。 – Java Web是Jav
    的頭像 發表于 07-16 13:35 ?1371次閱讀
    華納云:<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別
    主站蜘蛛池模板: 国产欧美日韩综合精品无毒 | 国产小视频在线免费 | 天堂在线www网亚洲 天堂在线观看 | 欧美黄色免费看 | 成人国产精品高清在线观看 | 国产午夜视频在永久在线观看 | 综合精品视频 | 国产激情视频一区二区三区 | 亚洲国产高清精品线久久 | 最新色网站 | 视频一二三区 | 97av在线播放 | 欧美伊人久久大香线蕉综合69 | 性夜影院爽黄e爽在线观看 羞羞色院91精品网站 | 成年人看的黄色 | 三级精品 | 3p高h文| 成人a在线| 亚洲欧美天堂网 | 一本久草 | 色妞网| 人人玩人人干 | 免费观看一级成人毛片 | 一区二区影视 | 国产成人毛片毛片久久网 | 国产在线精彩视频二区 | 天天搞一搞 | 日本一道dvd在线中文字幕 | 你懂的在线观看网址 | 亚洲成人网在线播放 | 日本最黄| 亚洲电影一区二区 | 在线黄色.com| 卡1卡2卡3精品推荐老狼 | 精品国产成人系列 | 亚洲伊人久久大香线蕉综合图片 | 女人张腿让男桶免费视频网站 | 婷婷色人阁 | 久久性| 欧美男人的天堂 | 免费精品美女久久久久久久久 |