一.JVM的概述
java語言有跨平臺特點, 寫一次java程序,可以在不同的平臺上運行.(JVM虛擬機的作用)
? ? ? ?前提條件: 在不同的平臺上安裝不同的虛擬機(虛擬機就是一個翻譯)
.java--->.class--->不同的虛擬機--->機器碼
1.jvm作用:
? ? ? ?負責將字節碼翻譯為機器碼, 管理運行時內存
2.jvm的整體組成部分
? 類加載系統: 負責將硬盤上的字節碼文件加載到內存中(重點)
? 運行時數據區: 負責存儲運行時各種數據(重點)
? 執行引擎: 負責將字節碼 轉為機器碼
? 本地方法接口: 負責調用本地方法(非java的方法)
? 垃圾回收(重點)
二.類加載系統
1.作用
? ? ? 負責將硬盤上的字節碼文件加載到內存中(運行時數據區中)
2.類什么時候會被加載
(1).在一個類寫一個main方法,運行main方法
(2).new 某個類對象時
(3).使用類中的靜態成員
(4).使用反射機制時
public class Hello {final static int num = 10;static int num1= 10;/*靜態代碼塊在類被加載時自動執行,目前可以看做一個類只被加載一次*/static {System.out.println("類被加載了");}public static void main(String[] args) {System.out.println("111111111");}
}public class TestHello {public static void main(String[] args) throws ClassNotFoundException {//new Hello();//System.out.println(Hello.num);// Class.forName("com.ffyc.javapro.jvm.classloader.Hello");/*創建的是數組對象,數組是Hello類型*/Hello [] hellos = new Hello[10];//只是訪問類中的靜態常量,類是不加載的,直接返回靜態常量值即可System.out.println(Hello.num);//System.out.println(Hello.num1);}
}
3.類加載的過程? (了解)
? ?加載: 以字節流形式讀取文件
? ?鏈接: 驗證 準備 解析
? ?初始化: 主要為靜態成員變量初始化賦值
4.類加載器
? ? ?類加載器就是負責加載類的實踐者
? ? ?不同的類,是否不同的類加載器加載的
? 類加載器分類:
? ? 啟動類加載器(引導類加載器),不是用java語言寫的,是c/c++寫的, 負責加載虛擬機核心的類庫
? ??擴展類加載器 ,是用java語言寫的,負則加載jre/lib/ext目錄下的類
? ? 應用程序類加載器,是用java語言寫的,負責加載程序員寫的項目中的類(target/class)
public static void main(String[] args) {//獲得類的類加載器
System.out.println(String.class.getClassLoader());//類加載器為null,說明是由啟動類加載器加載的String類System.out.println(Hello.class.getClassLoader());//sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(Hello.class.getClassLoader().getClass().getClassLoader());//應用程序類加載器的加載器為null}
5.什么是雙親委派機制(重點)
? ?工作原理:
? ? ? 當收到類加載任務時,首先委派給上級的類加載器加載,如果上級類加載器還有父級,依次遞歸,直到最頂級的啟動類加載器, 當父級類加載器找到類時,成功返回,
? ? ? 如果找不到,就委派給子類加載器,如果子類加載器找到后,成功返回,
? ? ? 如果均未找到,那么就拋出ClassNotFoundException.
7.為什么設計雙親委派機制
? ? ? 為了安全, 避免了自己定義的類,替換了系統中的核心類
? ? ? ?例如: 自己創建java.lang.String, 結果還是加載的系統中的String類
8.如何打破雙親委派機制
? ? ? ?自定義類加載重寫方法打破雙親委派機制
? ? ? ? ? ?①可以自定義類加載器
? ? ? ? ? ?②寫一個類 繼承 ClassLoader類,
? ? ? ? ? ?③重寫findClass();
自己用流將字節碼讀入,
Class<?> clazz = defineClass(null, bytes, 0, bytes.length);
Object o = clazz.newInstance();//反射機制創建對象//com.ffyc.javapro.jvm.classloader.MyClassLoader@1b6d3586
System.out.println(clazz.getClassLoader());
三.運行時數據區
? ? ?當類加載系統把類信息加載到內存后,存儲到運行時數據區.
? ? ?運行時數據區,根據不同的功能可以分為5個部分:
1.程序計數器
? ? ?作用:
? ? ? ? ? ? ? 程序計數器用來記錄線程執行的指令集的位置, 因為線程在執行時cpu要進行切換執行,需? ? ? ? ? 要記錄線程執行的位置.
特點:
? (1).是運行時數據區中空間最小的,運行速度最快的區域
? (2).每個線程都有一個屬于自己的程序計數器,是線程私有的,程序計數器生命周期與線程生命? ? ? ? ? ? ? ? ?周期相同.
? (3).程序計數器是運行時數據區中唯一一個不會有內存異常情況的區域,
2.虛擬機棧
? ? ? 虛擬棧是運行單位,管理程序如何執行,調用一個方法,方法入棧執行,運行結束后,出棧.
? ? ? 虛擬機棧主要用來運行java語言寫的方法.
特點:
? ? ?①線程私有的,每個線程中調用的方法都在線程對應的虛擬機棧中執行.
? ? ?②棧中存儲局部變量
? ? ?③虛擬棧中不存在垃圾回收
? ? ? ? ?虛擬機棧中會存在內存溢出問題(遞歸調用太深)
? ? ? ? ?Exception in thread "main" java.lang.StackOverflowError 棧溢出錯誤
? ? ?④不同線程中所包含的棧幀(方法)是不允許存在相互引用的
? ? ? ? ? ? ? (eg:A線程中的方法不能調用B線程中的方法)
? ? ?⑤先進后出
public void test(){ int a = 10;//局部變量int b= 20;String s = new String(); //s是引用類型,保存的是對象地址
}
棧幀:
? ? ? ? 當一個方法被調用后,被壓入到虛擬機棧中稱為一個棧幀,
棧幀內部結構:
? ? ? ? ①局部變量表(存儲局部變量的區域)
? ? ? ? ②操作數棧? ? ——? ? 操作數棧就是用來計算的區域,
? ? ? ? ? ? 例如? :
int a= 10,int b=20; //a和b存儲在局部變量表中
int c = a+b ;//計算時,把a和b從局部變量表加載到操作數棧運算,把 運算結果賦給c,把c寫回到局部變量表
? ? ? ? ③方法返回地址: 記錄方法調用的位置,方法執行完成后要回到自己開的位置
3.本地方法棧
? ? ? ?本地方法: 在java程序中,不是用java語言實現的方法, 由底層操作系統提供
? ? ? ? ? ? ? ? ? ? ? ? 使用 native關鍵修飾的方法,沒有方法體
? ?? ?因為java語言屬于上層語言(開發上層應用程序),沒有權限與底層硬件進行交互(如讀取內存數據,讀取硬盤數據)
? ? ? 本地方法棧用來執行本地方法的,當程序中調用了本地方法,那么被加載到本地方法棧中運行.
特點:
? ? ? ? ?①線程私有的,每個線程都有屬于自己的本地方法棧
? ? ? ? ?②本地方法棧也會出現內存溢出情況
? ? ? ? ?③本地方法棧中不會出現垃圾回收
4.堆
(1).概述
? ? ? ?作用:
? ? ? ? ? ? ? ? 堆空間是用來存儲java中創建的對象的
? ? ? ?特點:
? ? ? ? ? ?堆空間是運行時數據區中最大的一塊內存空間,
? ? ? ? ? ? ?還可以根據需要通過參數設置大小: -Xms:10m(堆起始大小) -Xmx:30m(堆最大內大小
? ? ? ? ? ? ?堆空間是所有線程共享的.
? ? ? ? ? ? ?堆空間會出現內存溢出情況的.
? ? ? ? ? ? ?堆空間是垃圾回收的重點區域.
(2).堆內存區域劃分
新生代(區): 伊甸園區? ? 幸存者0(from)? ?幸存者1(to)
老年代(區):
(3).為什么要分區(代)
? ? 根據對象的存活周期,對象的大小放在不同的區域,不同的區域可以采用不同的垃圾回收算法.會頻繁的回收新生代, 相對較少回收老年代.可以對回收算法揚長避短.
(4).對象創建內存分配過程
? ? ? ①.新創建的對象都存儲在伊甸園區(比較大的對象,可以直接分配到老年代)
? ? ? ②.當下次垃圾回收到來時,把伊甸園區存活的對象移動到幸存者0區,清空伊甸園區
? ? ? ③.當下次垃圾回收時,把伊甸園區中存活的對象和幸存者0區的存活對象移動到幸存者1區,清空伊甸園區和幸存者0區.
? ? ? ④.當一個對象經歷過最大上限15次垃圾回收后,依然存活,那么將此對象移動到老年代
5.方法區
(1).概述
? ? ? ? ?方法區主要存放類信息(屬性,方法,靜態常量...)和編譯器編譯后的代碼
? ? ? ? ?是一個被線程共享的內存區域
? ? ? ? ?方法的大小也是可以設置的,方法區的大小決定可以加載多少了類
? ? ? ? ? 方法區也是有可能出現內存溢出的.
(2).方法區大小設置
? ? ? ? ? ? ? 可以使用參數-XX:MetaspaceSize指定
(3).方法區的垃圾回收
? ? ? 方法區也是有垃圾回收的, 方法區的垃圾回收主要回收的是類信息.
? ? ? 類信息回收條件(比較苛刻的):
? ? ? ? ? ? ? ①.該類所創建的對象都已經不再使用,并且被回收了
? ? ? ? ? ? ? ②.該類的Class對象也不在被使用了
? ? ? ? ? ? ? ③.加載該類的類加載器也被回收了
線程共享: 堆,方法
線程私有的: 程序計數器,虛擬機棧,本地方法棧
會出現內存溢出: 堆,方法, 虛擬機棧,本地方法棧
會出現垃圾回收: 堆,方法區
四.本地方法接口 (了解)
? ? ? ?虛擬機中負責調用本地方法的入口, 本地方法運行在本地方法棧中.
什么是本地方法:
? ? ? ?被native修飾的方法, 沒有方法體, 是操作系統提供的方法
為什么java中要調用本地方法:
? ? ? ? java屬于上層應用開發語言,沒有權限直接訪問計算機硬件(硬盤,內存,外設(喇叭)),需要調用本地操作系統提供的方法.
五.執行引擎(黑盒)? (了解)
執行引擎在虛擬機中主要負責將加載到虛擬機中的字節碼 解釋/編譯 為機器碼
.java-----jdk編譯--->.class 在開發階段 (前端編譯)
.class---執行引擎編譯---->機器碼 在運行階段(后端編譯)
什么是解釋器?什么是 JIT 編譯器?
? ?解釋器/解釋執行--->sql,html,css,js ,python 解釋執行 不需要整體編譯,由解釋器一行一行執行
? ?JIT編譯器-->編譯執行,先把代碼整體進行編譯,生成另一種文件格式,但并不是馬上執行
解釋執行特點:
? ? ? ? ? ?速度慢, 不需要花費時間編譯?
編譯執行特點:
? ? ? ? ? ? 編譯后執行快, 但是編譯需要花費一定的時間
jvm中的執行引擎在將字節碼 翻譯為機器碼時,采取半解釋,半編譯機制.
開始時,可以先采用解釋執行,立即投入到翻譯工作中,
等到編譯器編譯完成后,采用編譯執行