啓動
:當啓動一個java程序時,一個jvm實例就誕生了,任何一個擁有main
方法的class均可以做爲jvm實例運行的起點。java
運行
:main()函數做爲程序初始線程起點,其它線程由該線程啓動,包括守護線程(daemon)和non-daemon(普通線程)。守護線程是JVM本身使用的線程好比GC線程就是個守護線程,只要這個jvm實例還有普通線程執行,就不會中止,可是能夠用exit()強制終止程序。安全
消亡
:全部非守護線程退出時,JVM實例結束生命,若安全管理器容許,程序也可使用java.lang.Runtime類或者System.exit(0)來退出。實際上exit也是用到Runtime類來退出,Runtime是個神奇的類,它還能夠用於啓動和關閉非java進程。網絡
咱們一直說java虛擬機實現的與語言是無關的
,java虛擬機不和包含java在內的任何語言綁定,它只和與class文件
這種特殊的二進制文件格式所關聯,class文件中包含了java虛擬機指令集
和符號表
以及若干其餘輔助信息。基於安全方面的考慮, Java 慮擬機規範要求在 Class 文件中使用許多強制性的語法和結構化約束
,但任一門功能性語言均可以表示爲一個能被 Java 虛擬機所接受的有效的 Class 文件。做爲一個通用的、機器無關的執行平臺,任何其餘語言的實現者均可以將 Java 虛擬機做爲語言的產品交付媒介。例如,使用 Java 編譯器能夠把 Java 代碼編譯爲存儲字節碼的 Class 文件,使用 JRuby 等其餘語言的編譯器一樣能夠把程序代碼編譯成 Class 文件,虛擬機並不關心Class 的來源是何種語言,如圖。dom
Java字節碼類文件(.class)是Java編譯器編譯Java源文件(.java)產生的「目標文件」。它是一種8位字節的二進制流文件, 各個數據項按順序緊密的從前向後排列, 相鄰的項之間沒有間隙, 這樣可使得class文件很是緊湊, 體積輕巧, 能夠被JVM快速的加載至內存, 而且佔據較少的內存空間(方便於網絡的傳輸)。jvm
class文件是一組以8位字節爲基礎單位的二進制流。
class文件中的信息是一項一項排列的, 每項數據都有它的固定長度, 有的佔一個字節, 有的佔兩個字節, 還有的佔四個字節或8個字節, 數據項的不一樣長度分別用u1, u2, u4, u8表示, 分別表示一種數據項在class文件中佔據一個字節, 兩個字節, 4個字節和8個字節。編輯器
當咱們把class文件轉成16進制,咱們能夠看到文件的頭四個字節是cafe babe
,這個就稱爲魔數
。,它惟一做用就告訴虛擬機當前的文件就是class文件。 使用魔數而不是用擴展名來進行識別主要是基於安全考慮,由於擴展名咱們能夠隨意經過重命名等方式改動。而經過魔數就算你把結尾改爲.clss。但它一樣還能在JVM運行,由於它的頭部仍是cafe babe
沒變。 不少文件存儲標準中都用魔數進行身份標識,如圖片gif,jpeg都在文件頭部中存儲着魔數。函數
我先講下概念,接下來我會將class文件轉爲16進制流後,在舉例說明。工具
常量池中每一項常量都是一個表,jdk1.8有14種結構不一樣的表結構,這14個表有個共同特色,就是表開始的第一位都是一個u1類型的標誌位,JVM根據這個標誌位[tag]來肯定某個常量池項表示什麼類型的字面量,好比tag爲1就是指CONSTANT_utf8_info編碼
再看常量池類型表:spa
這14種常量項結構還有一個特色是,其中13表佔用得字節固定,只有CONSTANT_Utf8_info佔用字節不固定
,其大小由length決定。爲何呢?由於從常量池存放的內容可知,其存放的是字面量和符號引用,最終這些內容都會是一個字符串, 這些字符串的大小是在編寫程序時才肯定,好比你定義一個類,類名能夠取長取短,因此在沒編譯前,沒法肯定大小不固定,編譯後,經過utf-8編碼,就能夠知道其長度。
在看每一項常量表對應的說明:
<br>
先看java代碼
package com.jincou.demo.domain; public class XiaoXiao { private String father; public String fatherName() { return "小小她爹"; } }
經過命令自動生成class文件(會在同一目錄生成)
javac XiaoXiao.java
在將class文件拖入文本編輯器裏,顯示天然就是16進制流了,以下:
<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190402230800719-150205933.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="500">
上面的表其實能夠劃分爲如下七個部分,.class 字節碼文件包括:
這篇博客只講到常量池,其它的下篇講,接下來咱們一行一行解釋,首先是:
cafe babe
:上面說過了這個是魔數,告訴JVM虛擬機我就是class文件。
0000 0034
:次版本號組成u2+主版本號u2。共佔4個字節。0034轉10進製爲52,表明當前JDK版本爲1.8。
0013
:說明有19-1即18個常量。
上面這些位置是固定的。接下來就是說明每個常量:
0a
:這就是tag表明一個標誌,0a表明10,去找常量池列表。
得知它是一個接口中方法的符號引用,而後去找CONSTANT_Methodref_info
對應常量列表描述:
從常量列表咱們能夠知道該類型一共佔了5u,即0a00 0400 0f
,那麼下一個tag就是08
表明字符串類型常量,以此類推就能夠知道一共18個常量的信息。 <br>
經過上面看16進制的卻太麻煩了,如今咱們能夠經過JDK自帶反編譯工具查看會更加清晰。
javap -verbose 文件名
經過反編譯看去就很直觀,好比第一個字符常量很明顯告訴你是CONSTANT_Methodref_info
,並且對於的就是4和15和上面完美對應。
最後思考,到底哪些會放到常量池?
1.常量池能夠理解爲class文件中的資源倉庫,有不少種類型,主要存放兩大常量 ①.字面量 字面量就是通俗理解的java常量,如文本字符串,8大基本數據類型,final修飾的常量值等 ②.符號引用 符號引用屬於編譯原理的概念,主要包含如下三種 1)類和接口的全限定名 2)字段的名稱和描述符 3)方法的名稱和描述符
<br>
一、深刻了解java虛擬機第2版第六章
<br>
<br>
只要本身變優秀了,其餘的事情纔會跟着好起來(少將3)