本文目錄一覽:
- 1、java重新加載class文件
- 2、如何在Java運行的時候動態加載一個jar包到classpath裡面
- 3、描述一下JVM加載class文件的原理?
- 4、北大青鳥設計培訓:Java類加載機制?
- 5、Java如何實現反射靜態加載和動態加載實例代碼詳解
- 6、java動態加載類和靜態加載類的區別有哪些
java重新加載class文件
Java類的加載是動態的,它並不會一次性將所有類全部加載後再運行,而是保證程序運行的基礎類(像是基類)完全加載到jvm中,至於其他類,則在需要的時候才加載。這當然就是為了節省內存開銷。
Java的類加載器有三個,對應Java的三種類:
Bootstrap Loader // 負責加載系統類 (指的是內置類,像是String,對應於C#中的System類和C/C++標準庫中的類)
|
– – ExtClassLoader // 負責加載擴展類(就是繼承類和實現類)
|
– – AppClassLoader // 負責加載應用類(程序員自定義的類)
三個加載器各自完成自己的工作,但它們是如何協調工作呢?哪一個類該由哪個類加載器完成呢?為了解決這個問題,Java採用了委託模型機制。
委託模型機制的工作原理很簡單:當類加載器需要加載類的時候,先請示其Parent(即上一層加載器)在其搜索路徑載入,如果找不到,才在自己的搜索路徑搜索該類。這樣的順序其實就是加載器層次上自頂而下的搜索,因為加載器必須保證基礎類的加載。之所以是這種機制,還有一個安全上的考慮:如果某人將一個惡意的基礎類加載到jvm,委託模型機制會搜索其父類加載器,顯然是不可能找到的,自然就不會將該類加載進來。
我們可以通過這樣的代碼來獲取類加載器:
ClassLoader loader = ClassName.class.getClassLoader();
ClassLoader ParentLoader = loader.getParent();
注意一個很重要的問題,就是Java在邏輯上並不存在BootstrapKLoader的實體!因為它是用C++編寫的,所以打印其內容將會得到null。
前面是對類加載器的簡單介紹,它的原理機制非常簡單,就是下面幾個步驟:
1.裝載:查找和導入class文件;
2.連接:
(1)檢查:檢查載入的class文件數據的正確性;
(2)準備:為類的靜態變量分配存儲空間;
(3)解析:將符號引用轉換成直接引用(這一步是可選的)
3.初始化:初始化靜態變量,靜態代碼塊。
這樣的過程在程序調用類的靜態成員的時候開始執行,所以靜態方法main()才會成為一般程序的入口方法。類的構造器也會引發該動作。
如何在Java運行的時候動態加載一個jar包到classpath裡面
給你個例子自己看一下吧不會了再追問,注釋基本都有了
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
public final class ExtClasspathLoader {
private static Method addURL = initAddMethod();
private static URLClassLoader classloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
/**
* 初始化addUrl 方法.
* @return 可訪問addUrl方法的Method對象
*/
private static Method initAddMethod() {
try {
Method add = URLClassLoader.class.getDeclaredMethod(“addURL”, new Class[] { URL.class });
add.setAccessible(true);
return add;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 加載jar classpath。
*/
public static void loadClasspath() {
ListString files = getJarFiles();
for (String f : files) {
loadClasspath(f);
}
ListString resFiles = getResFiles();
for (String r : resFiles) {
loadResourceDir(r);
}
}
private static void loadClasspath(String filepath) {
File file = new File(filepath);
loopFiles(file);
}
private static void loadResourceDir(String filepath) {
File file = new File(filepath);
loopDirs(file);
}
/** *//**
* 循環遍歷目錄,找出所有的資源路徑。
* @param file 當前遍歷文件
*/
private static void loopDirs(File file) {
// 資源文件只加載路徑
if (file.isDirectory()) {
addURL(file);
File[] tmps = file.listFiles();
for (File tmp : tmps) {
loopDirs(tmp);
}
}
}
/**
* 循環遍歷目錄,找出所有的jar包。
* @param file 當前遍歷文件
*/
private static void loopFiles(File file) {
if (file.isDirectory()) {
File[] tmps = file.listFiles();
for (File tmp : tmps) {
loopFiles(tmp);
}
}
else {
if (file.getAbsolutePath().endsWith(“.jar”) || file.getAbsolutePath().endsWith(“.zip”)) {
addURL(file);
}
}
}
/**
* 通過filepath加載文件到classpath。
* @param filePath 文件路徑
* @return URL
* @throws Exception 異常
*/
private static void addURL(File file) {
try {
addURL.invoke(classloader, new Object[] { file.toURI().toURL() });
}
catch (Exception e) {
}
}
/***
* 從配置文件中得到配置的需要加載到classpath里的路徑集合。
* @return
*/
private static ListString getJarFiles() {
// TODO 從properties文件中讀取配置信息 如果不想配置 可以自己new 一個ListString 然後把 jar的路徑加進去 然後返回
return null;
}
/**
* 從配置文件中得到配置的需要加載classpath里的資源路徑集合
* @return
*/
private static ListString getResFiles() {
//TODO 從properties文件中讀取配置信息略 如果不想配置 可以自己new 一個ListString 然後把 jar的路徑加進去 然後返回 額 如果沒有資源路徑為空就可以了
return null;
}
public static void main(String[] args) {
ExtClasspathLoader.loadClasspath();
}
}
描述一下JVM加載class文件的原理?
Java語言是一種具有動態性的解釋型語言,類(class)只有被加載到JVM中後才能運行。當運行指定程序時,JVM會將編譯生成的.class文件按照需求和一定的規則加載到內存中,並組織成為一個完整的Java應用程序。這個加載過程是由類加載器來完成的,具體來說,就是由ClassLoader和它的子類來實現的。類加載器本身也是一個類,其實質是把類文件從硬盤讀取到內存中。
類的加載方式分為隱式加載與顯式加載兩種。隱式加載指的是程序在使用new等方法創建對象時,會隱式地調用類的加載器把對應的類加載到JVM中。顯式加載指的是通過直接調用class.forName()方法來把所需要的類加載到JVM中。
任何一個工程項目都是由許多個類組成的,當程序啟動時,只把需要加載的類加載到JVM中,其他類只有被使用到的時候才會被加載,採用這種方法,一方面可以加快加載速度,另外一方面可以節約程序運行過程中對內存的開銷。此外,在Java語言中,每個類或接口都對應一個.class文件,這些文件可以被看成一個個可以被動態加載的單元,因此當只有部分類被修改時,只需要重新編譯變化的類即可,而不需要重新編譯所有文件,因此加快了編譯速度。
北大青鳥設計培訓:Java類加載機制?
1,類的加載每個開發人員對java.lang.ClassNotFoundExcetpion這個異常肯定都不陌生,這背後就涉及到了java技術體系中的類加載。
Java的類加載機制是技術體系中比較核心的部分,雖然和大部分開發人員直接打交道不多,但是對其背後的機理有一定理解有助於排查程序中出現的類加載失敗等技術問題,對理解java虛擬機的連接模型和java語言的動態性都有很大幫助。
那麼什麼是類的加載?類的加載指的是將類的.class文件中的二進制數據讀入到內存中,將其放在運行時數據區的方法區內,然後在堆區創建一個java.lang.Class對象,用來封裝類在方法區內的數據結構。
類的加載的最終產品是位於堆區中的Class對象,Class對象封裝了類在方法區內的數據結構,並且向Java程序員提供了訪問方法區內的數據結構的接口。
類加載器是Java語言的一個創新,也是Java語言流行的重要原因之一。
它使得Java類可以被動態加載到Java虛擬機中並執行。
類加載器從JDK1.0就出現了,最初是為了滿足JavaApplet的需要而開發出來的。
JavaApplet需要從遠程下載Java類文件到瀏覽器中並執行。
現在類加載器在Web容器和OSGi中得到了廣泛的使用,而類加載器並不需要等到某個類被“首次主動使用”時再加載它,JVM規範允許類加載器在預料某個類將要被使用時就預先加載它,如果在預先加載的過程中遇到了.class文件缺失或存在錯誤,類加載器必須在程序首次主動使用該類時才報告錯誤(LinkageError錯誤)如果這個類一直沒有被程序主動使用,那麼類加載器就不會報告錯誤。
2,類的生命周期類加載的過程中包括有加載,驗證,準備,解析,初始化五個階段。
而需要注意的是在這五個階段中,加載、驗證、準備和初始化這四個階段發生的順序是確定的,而解析階段則不一定,它在某些情況下可以在初始化階段之後開始,這是為了支持Java語言的運行時綁定(也成為動態綁定或晚期綁定)。
另外注意這裡的幾個階段是按順序開始,而不是按順序進行或完成,因為這些階段通常都是互相交叉地混合進行的,通常在一個階段執行的過程中調用或激活另一個階段。
加載:查找並加載類的二進制數據加載時類加載過程的第一個階段,在加載階段,虛擬機需要完成以下三件事情:1、通過一個類的全限定名來獲取其定義的二進制字節流。
(並沒有指明要從一個Class文件中獲取,可以從其他渠道,譬如:網絡、動態生成、數據庫等)2、將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
3、在Java堆中生成一個代表這個類的java.lang.Class對象,作為對方法區中這些數據的訪問入口。
相對於類加載的其他階段而言,加載階段(準確地說,是加載階段獲取類的二進制字節流的動作)是可控性最強的階段,電腦培訓發現因為開發人員既可以使用系統提供的類加載器來完成加載,也可以自定義自己的類加載器來完成加載。
Java如何實現反射靜態加載和動態加載實例代碼詳解
1.Java動態加載類和靜態加載類的區別
new創建對象的方式稱作為靜態加載,而使用Class.forName(“XXX”)稱作為動態加載,它們倆本質的區別在於靜態加載的類的源程序在編譯時期加載(必須存在),而動態加載的類在編譯時期可以缺席(源程序不必存在)。
2.為什麼需要動態加載類
對於我自己的理解,動態加載類增加了程序的靈活性。比如一個程序中有50個功能,但你可能只會使用其中的一個,如果你用的是靜態加載的方式,你必須在編譯前提供100個功能的所有定義,否則無法編譯通過,若你使用的是動態加載機制,則不需要如此大費周章,用哪一個就定義哪一個即可。
靜態加載:
public class Office_Static {
public static void main(String[] args) {
//new 創建對象,是靜態加載類,在編譯時刻就需要加載所有的可能使用到的類
if(“Word”.equals(args[0])){
Word w = new Word();
w.start();
}
if(“Excel”.equals(args[0])){
Excel e = new Excel();
e.start();
}
}
}
這個程序編譯時必須有Word和Excel這兩個類存在才行,即使判斷後用不到Excel也要加載
動態加載:
接口OfficeAble :
public interface OfficeAble {
public void start();}
java動態加載類和靜態加載類的區別有哪些
Class.forName 不僅表示類的類類型,還代表了動態加載類。編譯時加載是靜態加載類,
運行時加載是動態加載類。
原創文章,作者:AZVZ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/131368.html