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、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...