日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1 官網(wǎng)

 

1.1 JDK8

1.2 The relation of JDK/JRE/JVM

Reference -> Developer Guides -> 定位到:https://docs.oracle.com/JAVAse/8/docs/index.html

JDK 8 is a superset of JRE 8, and contains everything that is in JRE 8, plus tools such as the compilers and debuggers necessary for developing Applets and applications. JRE 8 provides the libraries, the Java Virtual machine (JVM), and other components to run applets and applications written in the Java programming language. Note that the JRE includes components not required by the Java SE specification, including both standard and non-standard Java components.

 


 

2 源碼到類文件

2.1 源碼

class Person{
    private String name;
    private int age;
    private static String address;
    private final static String hobby="Programming";
    public void say(){
        System.out.println("person say...");
    }
    public int calc(int op1,int op2){
        return op1+op2;
    }
}

2.2 編譯過程

Person.java -> 詞法分析器 -> tokens流 -> 語法分析器 -> 語法樹/抽象語法樹 -> 語義分析器 -> 注解抽象語法樹 -> 字節(jié)碼生成器 -> Person.class文件

2.3 類文件(Class文件)

官網(wǎng)The class File Format :https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

cafe babe 0000 0034 0027 0a00 0600 1809
0019 001a 0800 1b0a 001c 001d 0700 1e07
001f 0100 046e 616d 6501 0012 4c6a 6176
612f 6c61 6e67 2f53 7472 696e 673b 0100
0361 6765 0100 0149 0100 0761 6464 7265

 

minor_version, major_version

minor_version, major_version

constant_pool_count

0027 對應(yīng)十進(jìn)制27,代表常量池中27個(gè)常量

ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

.class字節(jié)碼文件

魔數(shù)與class文件版本
常量池
訪問標(biāo)志
類索引、父類索引、接口索引
字段表集合
方法表集合
屬性表集合

3 類文件到虛擬機(jī)(類加載機(jī)制)

 

3.1 裝載(Load)

Chapter 5. Loading, Linking, and Initializing (oracle.com)

a.找到類文件所在的位置---:磁盤-->類裝載器ClassLoader --> 尋找類

b.類文件的信息交給JVM --> 類文件字節(jié)碼流靜態(tài)存儲結(jié)構(gòu) --> JVM里賣弄的某一塊區(qū)域

c.類文件所對應(yīng)的對象Class ---> JVM

查找和導(dǎo)入class文件 --> JVM --> 堆

(1)通過一個(gè)類的全限定名獲取定義此類的二進(jìn)制字節(jié)流
(2)將這個(gè)字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)
(3)在Java堆中生成一個(gè)代表這個(gè)類的java.lang.Class對象,作為對方法區(qū)中這些數(shù)據(jù)的訪問入口

3.2 鏈接(Link)

3.2.1 驗(yàn)證(Verify):保證被加載類的正確性

  • 文件格式驗(yàn)證
  • 元數(shù)據(jù)驗(yàn)證
  • 字節(jié)碼驗(yàn)證
  • 符號引用驗(yàn)證

3.2.2 準(zhǔn)備(Prepare)

為類的靜態(tài)變量分配內(nèi)存,并將其初始化為默認(rèn)值

static int num = 10; // 在準(zhǔn)備階段為num分配內(nèi)存空間,并初始化其值為0

3.2.3 解析(Resolve)

把類中的符號引用轉(zhuǎn)換為直接引用

地址:String str =地址是什么,直接對應(yīng)到內(nèi)存中某個(gè)地址指向。

3.3 初始化(Initialize)

對類的靜態(tài)變量,靜態(tài)代碼塊執(zhí)行初始化操作

static int num = 10; // 此時(shí),num才會被真正的賦值為10

3.4 類加載機(jī)制圖解

 

4 類裝載器ClassLoader

在裝載(Load)階段,其中第(1)步:通過類的全限定名獲取其定義的二進(jìn)制字節(jié)流,需要借助類裝載 器完成,顧名思義,就是用來裝載Class文件的。

(1)通過一個(gè)類的全限定名獲取定義此類的二進(jìn)制字節(jié)流。

4.1 分類

1)Bootstrap ClassLoader 負(fù)責(zé)加載$JAVA_HOME中 jre/lib/rt.jar 里所有的class或 Xbootclassoath選項(xiàng)指定的jar包。由C++實(shí)現(xiàn),不是ClassLoader子類。

2)Extension ClassLoader 負(fù)責(zé)加載java平臺中擴(kuò)展功能的一些jar包,包括$JAVA_HOME中 jre/lib/*.jar 或 -Djava.ext.dirs指定目錄下的jar包。

3)App ClassLoader 負(fù)責(zé)加載classpath中指定的jar包及 Djava.class.path 所指定目錄下的類和 jar包。

4)Custom ClassLoader 通過java.lang.ClassLoader的子類自定義加載class,屬于應(yīng)用程序根據(jù) 自身需要自定義的ClassLoader,如Tomcat、jboss都會根據(jù)j2ee規(guī)范自行實(shí)現(xiàn)ClassLoader。

4.2 圖解

 

4.3 加載原則

檢查某個(gè)類是否已經(jīng)加載:順序是自底向上,從Custom ClassLoader到BootStrap ClassLoader逐層檢 查,只要某個(gè)Classloader已加載,就視為已加載此類,保證此類只所有ClassLoader加載一次。

加載的順序:加載的順序是自頂向下,也就是由上層來逐層嘗試加載此類。

雙親委派機(jī)制:

定義:如果一個(gè)類加載器在接到加載類的請求時(shí),它首先不會自己嘗試去加載這個(gè)類,而是把 這個(gè)請求任務(wù)委托給父類加載器去完成,依次遞歸,如果父類加載器可以完成類加載任務(wù),就 成功返回;只有父類加載器無法完成此加載任務(wù)時(shí),才自己去加載。

優(yōu)勢:Java類隨著加載它的類加載器一起具備了一種帶有優(yōu)先級的層次關(guān)系。比如,Java中的 Object類,它存放在rt.jar之中,無論哪一個(gè)類加載器要加載這個(gè)類,最終都是委派給處于模型 最頂端的啟動類加載器進(jìn)行加載,因此Object在各種類加載環(huán)境中都是同一個(gè)類。如果不采用 雙親委派模型,那么由各個(gè)類加載器自己取加載的話,那么系統(tǒng)中會存在多種不同的Object 類。

破壞:可以繼承ClassLoader類,然后重寫其中的loadClass方法,其他方式大家可以自己了解 拓展一下。

5 運(yùn)行時(shí)數(shù)據(jù)區(qū)(Run-Time Data Areas)

在裝載階段的第(2),(3)步可以發(fā)現(xiàn)有運(yùn)行時(shí)數(shù)據(jù),堆,方法區(qū)等名詞

(2)將這個(gè)字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)

(3)在Java堆中生成一個(gè)代表這個(gè)類的java.lang.Class對象,作為對方法區(qū)中這些數(shù)據(jù)的訪問入口

說白了就是類文件被類裝載器裝載進(jìn)來之后,類中的內(nèi)容(比如變量,常量,方法,對象等這些數(shù) 據(jù)得要有個(gè)去處,也就是要存儲起來,存儲的位置肯定是在JVM中有對應(yīng)的空間)

5.1 官網(wǎng)概括

Chapter 2. The Structure of the Java Virtual Machine (oracle.com)

The Java Virtual Machine defines various run-time data areas that are used during execution of a program. Some of these data areas are created on Java Virtual Machine start-up and are destroyed only when the Java Virtual Machine exits. Other data areas are per thread. Per-thread data areas are created when a thread is created and destroyed when the thread exits

>>> Java 虛擬機(jī)定義了在程序執(zhí)行期間使用的各種運(yùn)行時(shí)數(shù)據(jù)區(qū)域。 其中一些數(shù)據(jù)區(qū)是在 Java 虛擬機(jī)啟動時(shí)創(chuàng)建的,只有在 Java 虛擬機(jī)退出時(shí)才會被銷毀。 其他數(shù)據(jù)區(qū)域是每個(gè)線程。 每線程數(shù)據(jù)區(qū)在創(chuàng)建線程時(shí)創(chuàng)建,在線程退出時(shí)銷毀

5.2 圖解

 


 

5.3 常規(guī)理解

5.3.1 Method Area(方法區(qū)):類信息、常量、靜態(tài)變量、即使編譯器編譯之后的代碼

在JDK1.8中,方法區(qū)存放運(yùn)行時(shí)常量池、方法數(shù)據(jù)、方法的代碼和構(gòu)造方法,包括類中的實(shí)例化方法和接口初始化方法。 存放如下數(shù)據(jù):

// 該類型數(shù)據(jù)存放在方法區(qū)
public static final CONSTSANT = "constant";

// 方法區(qū)存放方法以及方法的代碼
public class Test {
   // 該方法存放在方法區(qū)
   public Test() {
   }
   
   // 該方法存放在方法區(qū)
   public void testMethod() {
   }
}

public interface IXXService() {
   // 該方法存放在方法區(qū)
   default void test () {
       
   }
}

The Java Virtual Machine has a method area that is shared among all Java Virtual
Machine threads.
>> 方法區(qū)只有一個(gè),線程共享的內(nèi)存區(qū)域【線程非安全】,生命周期是跟虛擬機(jī)一樣的。

It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.
>> 類信息、常量、靜態(tài)變量、即使編譯器編譯之后的代碼。

The method area is created on virtual machine start-up.

Although the method area is logically part of the heap【邏輯上是屬于堆的一部分】, simple implementations may choose not to either garbage collect or compact it.
垃圾回收不太會討論方法區(qū)的垃圾回收

If memory in the method area cannot be made available to satisfy an allocation request, the Java Virtual Machine throws an OutOfMemoryError.
>> OOM

方法區(qū)是各個(gè)線程共享的內(nèi)存區(qū)域,在虛擬機(jī)啟動時(shí)創(chuàng)建。

用于存儲已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。

雖然Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分,但是它卻又一個(gè)別名叫做Non-Heap(非堆),目 的是與Java堆區(qū)分開來。

當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時(shí),將拋出OutOfMemoryError異常。

此時(shí)回看裝載階段的第2步:(2)將這個(gè)字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù) 結(jié)構(gòu)

如果這時(shí)候把從Class文件到裝載的第(1)和(2)步合并起來理解的話,可以畫個(gè)圖

 

(1)方法區(qū)在JDK 8中就是Metaspace,在JDK6或7中就是Perm Space (2)Run-Time Constant Pool

(2)Run-Time Constant Pool

Class文件中除了有類的版本、字段、方法、接口等描述信息外,

還有一項(xiàng)信息就是常量池,用于存放編譯時(shí)期生成的各種字面量和符號引用,這部分內(nèi)容將在 類加載后進(jìn) 入方法區(qū)的運(yùn)行時(shí)常量池中存放。

Each run-time constant pool is allocated from the Java Virtual Machine's method area (§2.5.4).s

每個(gè)運(yùn)行時(shí)常量池都是從 Java 虛擬機(jī)的方法中分配的區(qū)域 (§2.5.4).s

5.3.2 Heap(堆):對象或者數(shù)組

Java堆是Java虛擬機(jī)所管理內(nèi)存中最大的一塊,在虛擬機(jī)啟動時(shí)創(chuàng)建,被所有線程共享。

Java對象實(shí)例以及數(shù)組都在堆上分配。

The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. 
堆只有一個(gè),線程共享內(nèi)存區(qū)域的【線程非安全】,生命周期跟虛擬機(jī)一樣。

The heap is the run-time data area from which memory for all class instances and arrays is allocated.
存儲數(shù)據(jù)包括:對象或者數(shù)組

The heap is created on virtual machine start-up. 

If a computation requires more heap than can be made available by the automatic storage management system, the Java Virtual Machine throws an OutOfMemoryError.
【如果內(nèi)存不夠,也會發(fā)生OOM】

此時(shí)回看裝載階段的第3步:(3)在Java堆中生成一個(gè)代表這個(gè)類的java.lang.Class對象,作為對方 法區(qū)中這些數(shù)據(jù)的訪問入口

此時(shí)裝載(1)(2)(3)的圖可以改動一下

 

5.3.3 Java Virtual Machine Stacks(虛擬機(jī)棧):局部變量、操作數(shù)、返回?cái)?shù)

Each Java Virtual Machine thread has a private Java Virtual Machine stack,
created at the same time as the thread. A Java Virtual Machine stack stores
frames (§2.6)
【每個(gè)線程獨(dú)有的線程?!?

一個(gè)線程的創(chuàng)建代表一個(gè)棧,每個(gè)方法被當(dāng)前線程調(diào)用了,就代表一個(gè)棧幀。

 

If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.
【StackOverflowError】

If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

經(jīng)過上面的分析,類加載機(jī)制的裝載過程已經(jīng)完成,后續(xù)的鏈接,初始化也會相應(yīng)的生效。

假如目前的階段是初始化完成了,后續(xù)做啥呢?肯定是Use使用咯,不用的話這樣折騰來折騰去 有什么意義?那怎樣才能被使用到?換句話說里面內(nèi)容怎樣才能被執(zhí)行?比如通過主函數(shù)main調(diào) 用其他方法,這種方式實(shí)際上是main線程執(zhí)行之后調(diào)用的方法,即要想使用里面的各種內(nèi)容,得 要以線程為單位,執(zhí)行相應(yīng)的方法才行。

那一個(gè)線程執(zhí)行的狀態(tài)如何維護(hù)?一個(gè)線程可以執(zhí)行多少個(gè)方法?這樣的關(guān)系怎么維護(hù)呢?

虛擬機(jī)棧是一個(gè)線程執(zhí)行的區(qū)域,保存著一個(gè)線程中方法的調(diào)用狀態(tài)。換句話說,一個(gè)Java線程的運(yùn)行 狀態(tài),由一個(gè)虛擬機(jī)棧來保存,所以虛擬機(jī)??隙ㄊ蔷€程私有的,獨(dú)有的,隨著線程的創(chuàng)建而創(chuàng)建。

每一個(gè)被線程執(zhí)行的方法,為該棧中的棧幀,即每個(gè)方法對應(yīng)一個(gè)棧幀。

調(diào)用一個(gè)方法,就會向棧中壓入一個(gè)棧幀;一個(gè)方法調(diào)用完成,就會把該棧幀從棧中彈出。

5.3.4 The pc Register(程序計(jì)數(shù)器)

我們都知道一個(gè)JVM進(jìn)程中有多個(gè)線程在執(zhí)行,而線程中的內(nèi)容是否能夠擁有執(zhí)行權(quán),是根據(jù) CPU調(diào)度來的。

假如線程A正在執(zhí)行到某個(gè)地方,突然失去了CPU的執(zhí)行權(quán),切換到線程B了,然后當(dāng)線程A再獲 得CPU執(zhí)行權(quán)的時(shí)候,怎么能繼續(xù)執(zhí)行呢?這就是需要在線程中維護(hù)一個(gè)變量,記錄線程執(zhí)行到 的位置。

程序計(jì)數(shù)器占用的內(nèi)存空間很小,由于Java虛擬機(jī)的多線程是通過線程輪流切換,并分配處理器執(zhí)行時(shí) 間的方式來實(shí)現(xiàn)的,在任意時(shí)刻,一個(gè)處理器只會執(zhí)行一條線程中的指令。因此,為了線程切換后能夠 恢復(fù)到正確的執(zhí)行位置,每條線程需要有一個(gè)獨(dú)立的程序計(jì)數(shù)器(線程私有)。

如果線程正在執(zhí)行Java方法,則計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址;

如果正在執(zhí)行的是Native方法,則這個(gè)計(jì)數(shù)器為空。

The Java Virtual Machine can support many threads of execution at once (JLS §17). Each Java Virtual Machine thread has its own pc (program counter)register. At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method (§2.6) for that thread. If that method is not native, the pc register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread is native, the value of the Java Virtual Machine's pcregister is undefined. The Java Virtual Machine's pc register is wide enough to hold a returnAddress or a native pointer on the specific platform

5.3.5 Native Method Stacks(本地方法棧)

An implementation of the Java Virtual Machine may use conventional stacks, colloquially called "C stacks," to support native methods (methods written in a language other than the Java programming language).

>> Java 虛擬機(jī)的實(shí)現(xiàn)可以使用傳統(tǒng)的堆棧,通俗地稱為“C 堆棧”,以支持本地方法(以 Java 編程語言以外的語言編寫的方法)

如果當(dāng)前線程執(zhí)行的方法是Native類型的,這些方法就會在本地方法棧中執(zhí)行。

分享到:
標(biāo)簽:JVM
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定