JVM虛擬機我來了~~~

来源:https://www.cnblogs.com/jiagooushi/archive/2022/11/21/16911290.html
-Advertisement-
Play Games

虛擬機 1.1 發展歷程 1.1.1 java往事 ​ Java誕生在一群懶惰、急躁而傲慢的程式天才之中。 ​ 1990年12月,Sun的工程師Patrick Naughton被當時糟糕的Sun C++工具折磨的快瘋了。他大聲抱怨,並威脅要離開Sun轉投當時在Steve Jobs領導之下的NeXT公 ...


虛擬機

1.1 發展歷程

1.1.1 java往事

​ Java誕生在一群懶惰、急躁而傲慢的程式天才之中。

​ 1990年12月,Sun的工程師Patrick Naughton被當時糟糕的Sun C++工具折磨的快瘋了。他大聲抱怨,並威脅要離開Sun轉投當時在Steve Jobs領導之下的NeXT公司。領導層為了留住他,給他一個機會,啟動了一個叫做Stealth(秘密行動)的項目。

​ 隨著James Gosling等人的加入,這個項目更名為Green。其目標是使用C++為嵌入式設備開發一種新的基礎平臺技術,James Gosling本人負責開發一個編輯器。正如人們事後分析的那樣,這位天才的程式員太懶惰,所以沒有把C++學好,開發中碰了一頭包。於是他決定開發一種新的編程語言。他把這種語言命名為C++++--,意思是C++ “加上一些好東西,減去一些壞東西”。顯然這個糟糕的名字不可能長久,於是很快這種頗受同伴喜愛的小語言被命名為Oak。

​ 到了1992年9月,Oak語言連同Green OS和一些應用程式一起發佈在稱做Start 7的小設備上,有了第一次精彩的亮相。隨後,Sun開了一家名為FirstPerson的公司,整個團隊被轉移到這家公司里研發機頂盒,以投標時代華納公司的一個項目。這幫天才被技術狂熱所鼓舞,開發出了一個高交互性的設備,結果沒想到時代華納公司和有線電視服務商並不願意用戶擁有那麼大的控制權,從而在競標之戰中敗給了SGI。

​ Sun無奈地關閉了FirstPerson,召回了整個團隊,java的出路卻沒有因此而斷送,隨著互聯網發展的涌動,java開始離開嵌入式小設備,往互聯網傾斜。1994年,Oak被命名為Java,回到了激情澎湃的IT產業,抓住互聯網的大潮,從此一發不可收拾。

​ 剩下的事情,大家都知道了……

1.1.2 版本迭代

  • 1991 年,James Gosling 博士發佈產品 Oak( 橡樹),這是 Java 語言的前身。

  • 1995 年,Oak 語言改名為 Java。

  • 1996 年,JDK(Java開發所使用的工具包)1.0 發佈,提供了純解釋執行的 Java 虛擬機實現:Sun Classic VM。

  • 1997 年,JDK1.1 發佈,代表技術有:JDBC、JavaBeans、內部類、反射。

  • 1998 年,JDK1.2 發佈,Java 技術體系被拆分為 J2SE、J2EE、J2ME 三大體系。

    • 2000 年,JDK1.3 發佈,預設的 Java 虛擬機由 Sun Classic VM 改為 HotSopt。
  • 2002 年,JDK1.4 發佈,Java 真正走向成熟,代表技術有:正則表達式、NIO等。

  • 2004 年,JDK5.0 發佈,對語法易用性做了很大改進,新增了泛型、枚舉等,代表技術有:併發包等。

  • 2006 年,JDK6.0 發佈,將 J2EE/J2SE/J2ME 的命名方式改為 Java SE 6、Java EE 6、Java ME 6。

  • 2009 年,Sun 公司因為經營不善被 Oracle 公司收購。

  • 2011 年,JDK7 發佈。

  • 2013 年,JDK8(LTS) 發佈,函數式編程,lamda表達式。

  • 2017年,JDK9

  • 2018年,JDK 10,11(LTS)正式發佈

  • 2019年,JDK 12,13

  • 2020年,JDK 14,15

  • 2021年,JDK 16,17(LTS)

附:sun與微軟的軼事
java誕生的1995年,正是微軟在軟體產業地位達到巔峰的時代。但是這個初出茅廬的毛頭小子硬是引起了微軟帝國的關註。所以96年微軟就向sun申請了java認證。
微軟的加持確實推動了人們對java的信心和興趣。
但是好景不長,從1997年發佈Visual J++的第一個版本開始,微軟就開始在Java中摻入自己的私有擴展。這毫無疑問引起Sun的高度重視。
1997年10月,Sun向美國加州地方法院起訴微軟公司違反兩公司就微軟使用Java技術所簽定的合同,指控微軟公司在自己的Java產品中做了“不恰當的修改”,違反了合同中承諾向用戶提供Java相容產品的條款。
這一官司一直打到了2001年1月雙方達成和解。
到了2001年7月,微軟公佈新版的Windows XP將不再支持Sun的JVM,並且推出了.NET平臺與Java分庭抗禮。
當然目前.net用的人少了,這是後話。

file

1.1.3 兩種jdk

openjdk vs oraclejdk:

  1. Oracle JDK將更多地關註穩定性,它重視更多的企業級用戶,而OpenJDK經常發佈以支持其他特性,不太穩定。
  2. Oracle JDK支持長期發佈的更改(LTS),而Open JDK僅支持計劃和完成下一個發行版。
  3. Oracle JDK根據二進位代碼許可協議獲得許可,而OpenJDK根據GPL v2許可獲得許可。
  4. 2019年1月之後發佈的Oracle Java SE 8的公開更新將無法用於商業,但是,OpenJDK是完全開源的,可以自由使用。
  5. Oracle JDK的構建過程基於OpenJDK,因此OpenJDK與Oracle JDK之間沒有技術差異。
  6. 頂級公司正在使用Oracle JDK,Open JDK不太受歡迎。
  7. Oracle JDK具有良好的GC選項和更好的渲染器,而OpenJDK具有更少的GC選項
  8. 在響應性和JVM性能方面,Oracle JDK提供了更好的性能。
  9. Oracle JDK在運行JDK時不會產生任何問題,而OpenJDK有時會產生一些問題。
  10. Oracle JDK將從其10.0.X版本將收費,用戶必須付費或必須依賴OpenJDK才能使用其免費版本。
  11. Oracle JDK完全由Oracle公司開發,而Open JDK項目由IBM,Apple,SAP AG,Redhat等頂級公司加入和合作。

1.2 JVM體系

file

  • JDK(Java Development Kit)是 Java語言的軟體開發工具包,也是整個java開發的核心,它包含了JRE和開發工具包

  • JRE(Java Runtime Environment),Java運行環境,包含了JVM和Java的核心類庫(Java API)

  • JVM(Java Virtual Machine),Java虛擬機,它是運行在操作系統之上的,它與硬體沒有直接的交互

所謂“一次編碼,隨處運行“正是基於不同系統下的jvm幫你掩蓋了系統之間介面的差異:

file

總結

jdk是開發人員的工具包,它包含了java的運行環境和虛擬機,而一次編寫到處運行就是基於jvm

1.3 各種虛擬機

1.3.1 清單

1、Sun Classic VM

​ 世界上第一款商用 Java 虛擬機。

1996年隨著Java1.0的發佈而發佈,JDK1.4時完全被淘汰

2、BEA JRockit

專註於服務端應用,號稱是世界上最快的JVM

​ 後來被 Oracle收購;Oracle JRockit (原來的 Bea JRockit)

3、IBM公司的 J9VM

全稱:IBM Technology for Java Virtual Machine,簡稱IT4J,內部代號:J9

是 IBM 自己開發的一款 JVM

市場定位於HotSpot接近,伺服器端、桌面應用、嵌入式等多用途VM

4、HotSpot VM(現在最常用)

​ 它是Sun JDK和OpenJDK中所帶的虛擬機,也是目前使用範圍最廣的Java虛擬機。

5、其他

(TaobaoJVM 、Graal VM、Azul VM、Liquid VM、Apache Harmony、)虛擬機

1.3.2 查看

shawn@macpro:~ > java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
  • hotspot虛擬機

  • Client VM是專門為快速啟動和小記憶體(small footprints)而優化的,像GUI就很適合

  • Server VM是專門為高性能應用而優化的,如伺服器應用

  • 版本是基於tag為1.8.0_181

1.4 jvm整體架構

1.4.1 java運行過程

file

1.源碼編譯:通過Java源碼編譯器將Java代碼編譯成JVM位元組碼(.class文件)

2.類載入:通過ClassLoader及其子類來完成JVM的類載入

3.類執行:位元組碼被裝入記憶體,進入JVM虛擬機,被解釋器解釋執行

1.4.2 jvm模型

file

由上面的圖可以看出,JVM虛擬機中主要是由三部分構成,分別是類載入子系統、運行時數據區、執行引擎。

類載入子系統

Java虛擬機把描述類的數據從Class文件載入到記憶體,並對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型。

運行時數據區

Java虛擬機在執行Java程式的過程中會把它所管理的記憶體劃分為若幹個不同的數據區域。

這些區域有各自的用途,以及創建和銷毀的時間,有的區域隨著虛擬機進程的啟動而一直存在,有些區域則是依賴用戶線程的啟動和結束而建立和銷毀。

執行引擎

執行引擎用於執行JVM位元組碼指令,主要有兩種方式,分別是解釋執行和編譯執行,區別在於,解釋執行是在執行時翻譯成虛擬機指令執行,而編譯執行是在執行之前先進行編譯再執行。

解釋執行啟動快,執行效率低。編譯執行,啟動慢,執行效率高。

垃圾回收器就是自動管理運行數據區的記憶體,將無用的記憶體占用進行清除,釋放記憶體資源。

本地方法庫、本地庫介面

在jdk的底層中,有一些實現是需要調用本地方法完成的(使用c或c++寫的方法),就是通過本地庫介面調用完成的。比如:System.currentTimeMillis()方法。

2、類文件結構

瞭解jvm後續的一切動作,先從位元組碼開始。它是一切發生的源頭。

2.1 測試案例

2.1.1 源代碼

package com.itheima.jvm.demo;

public class ClassStruct {

    private static String name = "JVM";

    public static void main(String[] args) {
        System.out.println("Hello " + name);
    }

}

2.1.2 編譯

1)maven定義編譯的版本

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

2)編譯

mvn clean compile

2.2 位元組碼結構

2.2.1 二進位概覽

1)vscode打開

file

2)class文件是一個二進位文件,轉化後是16進位展示,實際上class文件就是一張表,它由以下數據項構成,這些數據項從頭到尾嚴格按照以下順序排列:

類型 名稱 數量 描述
u4 magic 1 魔數
u2 minor_version 1 次版本號
u2 major_version 1 主版本號
u2 constant_pool_count 1 常量個數
cp_info constant_pool constant_pool_count - 1 具體常量
u2 access_flags 1 訪問標誌
u2 this_class 1 類索引
u2 super_class 1 父類索引
u2 interfaces_count 1 介面索引
u2 interfaces interfaces_count 具體介面
u2 fields_count 1 欄位個數
field_info fields fields_count 具體欄位
u2 methods_count 1 方法個數
method_info methods methods_count 具體方法
u2 attributes_count 1 屬性個數
attribute_info attributes attributes_count 具體屬性

3)圖示如下:

file

2.2.2 魔數與版本

1)魔數:

CAFEBABE,咖啡寶寶,固定的。

file

2)版本號:

34,換成10進位就是52

file

jdk的版本標記映射關係:

file

說明編譯用的是jdk8,我們改成1.6,重新執行 mvn clean compile ,再來查看class文件試試:

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

擴展

在開發中,經常會遇到類似Unsupported major.minor version 51.0的錯誤,一般情況下都是JDK版本不匹配造成的。
雖然jdk代碼在執行時基本上向下相容,但是!開發環境和伺服器環境jdk最好一致,不要嘗試這個坑。

區分和理解兩個環境:編譯環境,運行環境

2.2.3 常量池

再往下遵從相同的規律: 計數器(標註後面有多少個) + 對應個數的結構體

我們以常量池為例:

1)位置

file

2)結構說明

常量池記錄了jvm內的一堆常量信息,這部分由 【2個位元組計數】 + 【n個cp_info結構】組成

file

其中cp_info有多種類型:

  • 直接類型,存的就是當前值,這種像Integer,Long等長度都是確定的
  • 引用類型,存的是指向其他位置的指針

file
附:綠色代表指針,橙色代表直接類型

3)案例

下麵以String為例,String是一種引用類,它會指向一個utf8類型來存儲真實的信息

jdk提供了一個工具,javap,可以查看常量列表的詳細內容:

javap -v ClassStruct.class

file

2.2.4 其他信息

1)說明

常量池之後,是緊挨的一系列信息,這些信息大同小異,無非就是值、或者引用

(參考上面2.3.3里的表格和圖例)

  • 訪問標記:public abstract 等信息
  • 類索引,class類型,最終指向一個utf8,標記當前類的名字
  • 父類,同上
  • 介面,2位元組記錄數量,後面記錄多個介面類型
  • 接下來是欄位、方法、屬性,都是2位元組記錄後面多少個,後面緊跟對應的結構體類型

2)註意事項

要看懂javap後的格式,明白這些格式,可以輕鬆看懂class結構

file

類型 標識符 案例 說明
數組 [ [Ljava.lang.String String數組
對象 L Lcom.test.Demo
基本類型 大寫字母開頭 B=byte,I=int……

組合類型

類型 案例 說明
類里的屬性、欄位、方法等 com.test.Demo.name:Ljava.lang.String 英文點號隔開
標識什麼類型 com.test.Demo.getName:()Ljava.lang.String 英文冒號隔開
方法 (參數類型)返回值類型 英文括弧,後面是返回值類型

3)實例分析

file

本文由傳智教育博學谷教研團隊發佈。

如果本文對您有幫助,歡迎關註點贊;如果您有任何建議也可留言評論私信,您的支持是我堅持創作的動力。

轉載請註明出處!


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

-Advertisement-
Play Games
更多相關文章
  • 一.小結 1.標識符是程式中事務的名稱 2.標誌符是由字母 數字 下劃線 和美元符號$構成的字元序列 3.標識符必須以字母或下劃線開頭,不能以數字開頭 4.標識符不能是保留字 5.標識符可以是任意長度 6.選擇描述性的標識符可提高程式的可讀性 7.使用變數存儲在程式中使用的數據 8.聲明變數就是告訴 ...
  • 大家好,歡迎來到 Crossin的編程教室 ! 前幾天,後臺老有小伙伴留言“愛心代碼”。這不是Crossin很早之前發過的內容嘛,怎麼最近突然又被人翻出來了?後來才知道,原來是一部有關程式員的青春偶像劇《點燃我,溫暖你》在熱播,而劇中有一段關於期中考試要用程式畫一個愛心的橋段。 於是出於好奇,Cro ...
  • 列表和字典的區別是列表可以通過索引來訪問值,而字典可以通過名稱來訪問各個值。 字典這種數據結構稱為映射(mapping),字典是Python中唯一內置映射類型,值不按照順序排列,而是存儲再鍵下麵。 其中鍵可以是數字、字元串或元組等不可變數據類型。 字典的用途 字典的名稱指出了這種數據結構的用途。日常 ...
  • 來源:blog.csdn.net/u014454538/article/details/98515807 1. Java中的線程安全 Java線程安全:狹義地認為是多線程之間共用數據的訪問。 Java語言中各種操作共用的數據有5種類型:不可變、絕對線程安全、相對線程安全、線程相容、線程獨立 ① 不可 ...
  • 1、快速開始 1.1、現有一張 User 表,其表結構如下 | id | name | age | emali | | | | | | | 1 | Jone | 18 | [email protected] | | 2 | Jack | 20 | [email protected] | | 3 ...
  • 在JSP頁面實現驗證碼校驗文章中當時是使用的Servlet類來進行的驗證碼校驗,但是這種方式並不能即時校驗,在正常情況下都是直接在用戶輸入之後就進行校驗,這樣對用戶來說很方便的。 AJAX 即“Asynchronous Javascript And XML”(非同步 JavaScript 和 XML) ...
  • 抽象類:可以作為頂層基類,從高層次規範編程介面 1、在abc模塊中,最常見的抽象類有Iterable,我們可以用他判斷一個對象是不是可迭代對象 1 from collections.abc import Iterable 2 3 4 class Valley: 5 6 def __iter__(se ...
  • 流程式控制制主要作用於:用來判斷某個程式在不同條件下,執行不同邏輯。 按結構分類,流程式控制制可分為:順序結構、選擇結構、迴圈結構 順序結構:程式從上往下執行 選擇結構:根據程式在不同條件下,選擇執行不同的邏輯代碼 迴圈結構:在一定的條件下,重覆執行某段代碼 選擇結構 java選擇結構的語句有:if語句 i ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...