java類載入-ag真人国际官网
a. java中關於類載入。
首先要有該類的class文件所在的文件夾
然後,用classloader載入這個文件夾中的所有以class結尾的文件,然後調用這個class對象的isannotationpresent({註解}.class).判斷是不是有加註解
class類也可以通過反射查找到這個類或者這個方法上有沒有加這個註解。但這是通過類找到註解
主要是想通過註解找到加了這個註解的所有類,
b. java的類載入後什麼時候會被釋放
java的類載入後且當使用階段完成之後,java類就進入了卸載階段,也就是所謂的釋放。
使用階段包括主動引用和被動引用,主動飲用會引起類的初始化,而被動引用不會引起類的初始化。
一個java類的完整的生命周期會經歷載入、連接、初始化、使用、和卸載五個階段,當然也有在載入或者連接之後沒有被初始化就直接被使用的情況,如圖所示:
ps:關於類的卸載,在類使用完之後,如果滿足下面的情況,類就會被卸載:
該類所有的實例都已經被回收,也就是java堆中不存在該類的任何實例。
載入該類的classloader已經被回收。
該類對應的java.lang.class對象沒有任何地方被引用,無法在任何地方通過反射訪問該類的方法。
如果以上三個條件全部滿足,jvm就會在方法區垃圾回收的時候對類進行卸載,類的卸載過程其實就是在方法區中清空類信息,java類的整個生命周期就結束了。
c. java程序什麼是類載入
你可以了解一下 深入理解java虛擬機,
java類載入 是因為在運行時當它需要引用某個類的時候,會先去載入這個類,就是去讀這個class文件到內存裡面來,現在還沒有創建這個類的實例,
你可以理解為 你寫的java代碼在編譯成class文件後,並沒有去執行,或者去引用他,只有程序運行時它將要使用這個類的時候才會去讀取這個class文件,這時候叫做類載入,當緩存了這個類文件之後,後面的創建類的時候都會去引用它,因為類載入是運行是載入,所以java代碼在運行時是有辦法修改的,同樣java類載入也允許載入一個遠程的class文件,也代表它是支持程序不停止時更新程序代碼的。
d. java如何載入一個外部的類或class文件
首先import 類,之後object來裝class.forname()。inner.現在這object有了import類的所有方法
這forname里的路徑該寫你的類的名字,如果在包里要加包名
e. java類載入順序
記住 3 條原則:
1、父類優先於子類
2、屬性優先於代碼塊優先於構造方法
3、靜態優先於非靜態
因此,類載入順序為:
父類靜態變數->父類靜態語句塊->子類靜態變數->子類靜態語句塊->父類普通成員變數->父類動態語句塊->父類構造器->子類普通成員變數->子類動態語句塊->子類構造器
f. java 類載入機制有什麼用
ava類載入機制詳解
「代碼編譯的結果從本地機器碼轉變為位元組碼,是存儲格式發展的一小步,卻是變成語言發展的一大步」,這句話出自《深入理解java虛擬機》一書,後面關於jvm的系列文章主要都是參考這本書。
java源碼編譯由三個過程組成:
1、源碼編譯機制。
2、類載入機制
3、類執行機制
我們這里主要介紹編譯和類載入這兩種機制。
一、源碼編譯
代碼編譯由java源碼編譯器來完成。主要是將源碼編譯成位元組碼文件(class文件)。位元組碼文件格式主要分為兩部分:常量池和方法位元組碼。
二、類載入
類的生命周期是從被載入到虛擬機內存中開始,到卸載出內存結束。過程共有七個階段,其中到初始化之前的都是屬於類載入的部分
載入----驗證----准備----解析-----初始化----使用-----卸載
系統可能在第一次使用某個類時載入該類,也可能採用預載入機制來載入某個類,當運行某個java程序時,會啟動一個java虛擬機進程,兩次運行的java程序處於兩個不同的jvm進程中,兩個jvm之間並不會共享數據。
1、載入階段
這個流程中的載入是類載入機制中的一個階段,這兩個概念不要混淆,這個階段需要完成的事情有:
1)通過一個類的全限定名來獲取定義此類的二進制位元組流。
2)將這個位元組流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
3)在java堆中生成一個代表這個類的class對象,作為訪問方法區中這些數據的入口。
由於第一點沒有指明從哪裡獲取以及怎樣獲取類的二進制位元組流,所以這一塊區域留給我開發者很大的發揮空間。這個我在後面的類載入器中在進行介紹。
2、准備階段
這個階段正式為類變數(被static修飾的變數)分配內存並設置類變數初始值,這個內存分配是發生在方法區中。
1、注意這里並沒有對實例變數進行內存分配,實例變數將會在對象實例化時隨著對象一起分配在java堆中。
2、這里設置的初始值,通常是指數據類型的零值。
private static int a = 3;
這個類變數a在准備階段後的值是0,將3賦值給變數a是發生在初始化階段。
3、初始化階段
初始化是類載入機制的最後一步,這個時候才正真開始執行類中定義的java程序代碼。在前面准備階段,類變數已經賦過一次系統要求的初始值,在初始化階段最重要的事情就是對類變數進行初始化,關注的重點是父子類之間各類資源初始化的順序。
java類中對類變數指定初始值有兩種方式:1、聲明類變數時指定初始值;2、使用靜態初始化塊為類變數指定初始值。
初始化的時機
1)創建類實例的時候,分別有:1、使用new關鍵字創建實例;2、通過反射創建實例;3、通過反序列化方式創建實例。
new test();
class.forname(「com.mengdd.test」);
2)調用某個類的類方法(靜態方法)
test.dosomething();
3)訪問某個類或介面的類變數,或為該類變數賦值。
int b=test.a;
test.a=b;
4)初始化某個類的子類。當初始化子類的時候,該子類的所有父類都會被初始化。
5)直接使用java.exe命令來運行某個主類。
除了上面幾種方式會自動初始化一個類,其他訪問類的方式都稱不會觸發類的初始化,稱為被動引用。
1、子類引用父類的靜態變數,不會導致子類初始化。
執行結果:
migu
用final修飾某個類變數時,它的值在編譯時就已經確定好放入常量池了,所以在訪問該類變數時,等於直接從常量池中獲取,並沒有初始化該類。
初始化的步驟
1、如果該類還沒有載入和連接,則程序先載入該類並連接。
2、如果該類的直接父類沒有載入,則先初始化其直接父類。
3、如果類中有初始化語句,則系統依次執行這些初始化語句。
在第二個步驟中,如果直接父類又有直接父類,則系統會再次重復這三個步驟來初始化這個父類,依次類推,jvm最先初始化的總是java.lang.object類。當程序主動使用任何一個類時,系統會保證該類以及所有的父類都會被初始化。
g. java中類載入的兩種方法是什麼
java類有兩種方法一種是類方法就是用static修飾的,一種是實例方法,就是沒有static修飾的方法
h. java 類載入先後順序
父類態代碼塊
父類靜態屬性
//以上根據代碼順序
子類靜態屬性
子類靜態代碼塊
//以上根據代碼順序
父類屬性
父類代碼塊
//以上根據代碼順序
父類構造器
子類屬性
子類代碼塊
//以上根據代碼順序
子類構造方法
子類方法
父類方法
父類靜態方法
子類靜態方法
package com.zz;
/**
* created by @摩西摩西 2020/3/21 22:29
**/
public class father {
public string name=son.getmetod("父類屬性");
public father(){
system.out.println("父類構造器");
}
{
system.out.println("父類代碼塊");
}
public void fathermethod(){
system.out.println("父類方法");
}
static {
system.out.println("父類態代碼塊");
}
static string name1=son.getmetod("父類靜態屬性");
public static void fatherstaticmethod(){
system.out.println("父類靜態方法");
}
}
package com.zz;
/**
* created by @摩西摩西 2020/3/21 22:32
**/
public class son extends father {
public string name = getmetod("子類屬性");
public son() {
system.out.println("子類構造方法");
}
{
system.out.println("子類代碼塊");
}
public void sonmethod(){
system.out.println("子類方法");
}
public static string name1 = getmetod("子類靜態屬性");
static {
system.out.println("子類靜態代碼塊");
}
public static void sonstaticmethod() {
system.out.println("子類靜態方法");
}
public static string getmetod(string s) {
system.out.println(s);
return s;
}
public static void main(string[] args) {
son son= new son();
son.sonmethod();
son.fathermethod();
fatherstaticmethod();
sonstaticmethod();
}
}
i. java類載入器有幾種
java中載入器的種類大致可以分為四種:bootstrap classloader(由c 語言寫成),系統載入器(也就是內部類appclassloader),extclassloader,以及java.net.urlclassloader.
當我們運行一個程序時,首先是找到jdk安裝目下的jvm.dll來啟動java虛擬機,而後bootstrap classloader產生,接下來就是bootstrap classloader來載入extclassloader,並且指定extclassloader的父載入器為bootstrap classloader,但是因為bootstrap classloader用c 語言寫的,所以用java的觀點來看,這個載入器的實例是不存在的,所以extclassloader的父載入器被設置為了null,然後就是bootstrap classloader將appclassloader裝載,並指定其父載入器為extclassloader。
java是按照載入器的委派模型來實現的。這種模型是java安全性機制的保證。並且值得我們注意的就是這幾個載入器的默認載入類的路徑。對於appclassloder來說,它的路徑也就是我們的classpath裡面的路徑。而對於extclassloader來說,它的路徑是jre\lib\ext\classes.對於urlclassloader來說,它的載入路徑是我們指定的url。