JVM類的載入步驟,自己理解整理
du -h /home/appadmin/upload/ 查詢指定目錄下面記憶體使用的情況
一、序列化:
序列化的特點:
1:所有儲存到磁碟上的物件都有序列化編號
2:當程式試圖序列化一個物件時,程式檢查該物件是否已經序列化過,
只有該物件從未(在本次虛擬機器中)被序列化過,系統才會將該物件轉換為位元組序列並輸出
3:如果物件已經被序列化過,程式將只是直接輸出一個序列化編號,而不是再次進行重新序列化該物件
二、類的載入和jvm:
jvm啟動載入所有的執行緒和類,當出現以下情況是將終止:
1:程式執行到最後正常結束
2:程式執行時使用了System.exit()或Runtime.getRuntime().exit()程式碼處程式結束
3:程式過程中遇到了未捕獲到的異常或者錯誤而結束
4:程式所在的平臺強制將誒輸了JVM程序
開發者可以通過整合ClassLoader的基類來建立自己的類載入器
載入類的二進位制資料的來源:
1:本地檔案載入class檔案,這是前面絕大部分實力程式的載入方式
2:從jar載入class檔案,這種方式也是很常見的,前面介紹的JDBC程式設計時
用到的資料驅動類就放在JAR檔案中,JVM可以從jar檔案中直接載入class檔案
3:通過網路載入class檔案
4:把一個java原始檔動態編譯,並執行載入
三、類的載入過程:
類的連線的準備的目的主要是類的驗證目的是確定java類二進位制資料的正確性,
也因為java虛擬機器不知道.class檔案是如何被建立的,有可能是正常建立,也有可能是黑客特質破壞虛擬機器的所以要有驗證環節,提高程式的健壯性
對於Java程式中每個正在執行的執行緒,都有一個PC暫存器儲存著當前執行的指令地址
java虛擬器可以一次編譯在不同的平臺作業系統上執行,執行時把位元組碼轉換為不同的機器指令執行,一次編譯到處執行
1、類的宣告週期分為五個步驟:
1.1:載入
1.1.1:建立class檔案,放到記憶體中
1.1.2:(1)類的載入器分為系統自帶的載入器:1、包括啟動類載入器,2、擴充套件類載入器,和3、系統類載入器
(2) 使用者自定義載入器:ClassLoader類的子類,使用者可以通過實現該類來定製類的載入方式
1.2.3:
1.2:連線
1.2.1:驗證
1.2.1.1:檢查檔案的格式,確保遵循java的固定格式
1.2.1.2:確定java的語意是否正確,驗證final是否有子類,final修飾的方法是否被重寫,
注:final修改變數不能修改,修飾方法不能重寫,修飾類不能被繼承
1.2.1.3:確保位元組碼流可以被java虛擬機器正確的執行,它是由操作碼的單位元組指令組成的序列,
每一個操作碼都跟著一個或多個運算元,java虛擬機器會驗證該運算元是否合法
1.2.1.4:二進位制相容驗證:確保類與類之間引用的協調性;如A類中a方法引用B類中b方法,虛擬機器會驗證A類時會檢查方法區內是否有B類的b方法,
如果不存在或不相容時,會丟擲NoSuchMethodError異常
1.2.2:準備
1.2.2.1:為類的靜態變數分配記憶體空間,並將其賦予預設值,注意是初始值 如static int型別初始值為0
1.2.3:解析
1.2.3.1:將類中的符號引用轉換為直接引用,主要針對類或介面、欄位、類方法、介面方法、方法型別、方法控制代碼和呼叫點限定符類符號引用進行。
如在A類中a方法中引用了B類中的b方法,將b方法放入A類中
1.3:初始化
1.3.1:類的初始化步驟:步驟2中父類含有父類則進行123的順序依次再次執行
1.3.1.1:假如這個類沒有被載入或者連線,則程式先載入並且連線該類
1.3.1.2:假如該類的直接父類還沒有初始化,則先初始化其直接父類
1.3.1.3:假如類中有初始化語句,則系統依次執行這些初始化語句
1.3.2:類初始化的方式:類的例項化主要對變數、靜態程式碼塊和私有構造的初始化,使用final修飾,呼叫時不會進行初始直接賦值引用
1.3.2.1:Student stu = new Student();new物件的方式
1.3.2.2:反射的方式:Class.forName("XXX").newInstance
1.3.2.3:使用java.lang.relect.Constructor的方式,Constructor<Student> constructor = Student.class.getConstructor(Integer.class);
Student stu3 = constructor.newInstance(123);使用該方式可以獲取引數的私有構造
1.3.2.4:克隆的方式,使用java.lang.relect.Constructor的方式獲取再進行呼叫。clone方法
1.3.3.5:通過反序列化本地實體類的檔案
1.4:使用
1.4.1:類的載入器:
1.4.1.1:Bootstrap ClassLoader:根載入器,載入java執行的核心類,在jvm啟動時進行載入,存放於<JAVA_HOME>\lib下面的核心類都由它載入
1.4.1.2:Extendsion ClassLoader:擴充套件類載入器載入<JAVA_HOME>\lib\ext下面核心的類檔案,對外擴充套件使用可以在裡面新增自己常使用的jar檔案
1.4.1.3:Application ClassLoader:應用程式類載入器,載入CLASSPATH下面的jar,一般我們編寫的java類都是由這個類載入器載入,這個類載入器是CLassLoader中的getSystemClassLoader()方法的返回值,所以也稱為系統類載入器.一般情況下這就是系統預設的類載入器.
除此之外,我們還可以加入自己定義的類載入器,以滿足特殊的需求,需要繼承java.lang.ClassLoader類.沒有指定使用者自己編寫的類載入器作為父類載入器
1.4.2:雙親委派原型:所有的類載入器請求載入類的時候,類不會直接被載入,而是去請求父類進行載入,只有父類無法載入時才會讓子類進行載入,比如java.langObject,
它存放在\jre\lib\rt.jar中,它是所有java類的父類,因此無論哪個類載入都要載入這個類,把所有的類彙總到頂層,進行統一的載入
1.5:解除安裝
四:jvm的內部分配
1:類載入子系統負責從檔案系統或者網路中載入Class資訊,存放於方法區,主要存放類的資訊,方法區中可能還會存放執行時常量池資訊---方法區的使用
2:jvm啟動時建立堆區,java例項存放於堆區,堆空間是所有執行緒共享的,這是一塊與java應用密切相關的記憶體空間--堆區
2.1:java堆是和應用程式關係最為密切的記憶體空間,幾乎所有的物件都存放在堆上
2.2:根據java回收機制的不同,java堆有可能擁有不同的結構。最為常見的一種構成是將整個java堆分為新生代和老年代。其中新生代存放新生物件或者年齡不大的物件,
老年代則存放老年物件。新生代有可能分為eden區、s0區、s1區,s0區和s1區也被稱為from和to區
2.3:
3:java的NIO庫允許java程式使用直接記憶體。直接記憶體是在java堆外的、直接向系統申請的記憶體空間,訪問速度快,記憶體受限於Xmx和機器的執行記憶體--直接記憶體區
4:垃圾回收系統是java虛擬機器的重要組成部分,垃圾回收器可以對方法區、java堆和直接記憶體進行回收。其中,java堆是垃圾收集器的工作重點
5:每一個java虛擬機器執行緒都有一個私有的java棧,一個執行緒的java棧線上程建立的時候被建立,java棧中儲存著幀資訊,
java棧中儲存著區域性變數、方法引數,同時和java方法的呼叫、返回密切相關。--棧區
5.1:棧執行壓棧執行,先進後出的原則,它儲存著當前函式的區域性變數、中間計算結果等資料。
5.2:遞迴函式的呼叫使用引數的數量和函式的呼叫次數影響棧記憶體的使用的大小,相同的函式呼叫的次數引數較多的方法呼叫會更快消耗
棧的記憶體,系統會丟擲StackOverflowError棧溢位錯誤
5.3:棧幀中區域性變量表中的槽位是可以重用的,如果一個區域性變數過了其作用域,那麼在其作用域之後申明的新的區域性變數就很有可能會
複用過期區域性變數的槽位,從而達到節省資源的目的。如public class TestReuse {
public static void localvar1(){
int a=0;
System.out.println(a);
int b=0;
}
public static void localvar2(){
{
int a=0;
System.out.println(a);
}
int b=0;
}
}localvar2中的b變數複用了a的槽位
五、垃圾的回收機制
1、對新生代的物件的收集稱為minor GC;
2、對舊生代的物件的收集稱為Full GC;
3、程式中主動呼叫System.gc()強制執行的GC為Full GC。
4、不同的物件引用型別, GC會採用不同的方法進行回收,JVM物件的引用分為了四種類型:
(1)強引用:預設情況下,物件採用的均為強引用(這個物件的例項沒有其他物件引用,GC時才會被回收)
(2)軟引用:軟引用是Java中提供的一種比較適合於快取場景的應用(只有在記憶體不夠用的情況下才會被GC)
(3)弱引用:在GC時一定會被GC回收
(4)虛引用:由於虛引用只是用來得知物件是否被GC
六、this方法的使用
1、構造器中引用該構造器正在初始化的物件
2、在方法中引用呼叫該方法的物件
七、面向物件:注(rt.grow().grow(),連續呼叫同一個方法直接.方法名)
1:面向物件的三大特徵:
1.1:封裝:java提供了private、protect和public等訪問修飾符來進行良好的封裝,修飾符可以完全省
1.1.1:封裝的意義:(把該隱藏的隱藏,把該暴露的暴露)
1.1.1.1:隱藏類的實現細節
1.1.1.2:限制對成員變數不合理的訪問
1.1.1.3:檢查資料的完整性和準確性
1.1.1.4:便於修改,不用全域性檢索修改
1.2:繼承:extend關鍵字進行繼承父類,使用父類的成員變數和方法(類中一般包括構造器、成員變數和方法)
1.2.1:繼承的規則:
1.2.1.1:當子類的方法名和父類額方法名相同時現象為重寫或者覆蓋
1.2.1.2方法重寫遵循“兩同兩小一大的原則”的原則,兩同指的是方法名相同和形參列表相同,兩小指的是子類返回值型別應比父類方法返回值型別更小或者相同
子類方法宣告丟擲的異常類應比父類方法宣告丟擲的異常類更小或者相等,一大指的是子類方法的訪問許可權比父類的訪問許可權更大或者相等
1.3:多型:構造器用於對例項進行初始化操作,構造器支援過載(類被載入,提供預設的構造器,否則類無法被例項化,構造器返回值和隱式的)
2: