本文目錄一覽:
- 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-tw/n/131368.html