VM在執行Java程序的時候,並不是一次性把所有用到的class全部加載到內存,而是第一次需要用到class時才加載。例如:
// Main.java
public class Main {
public static void main(String[] args) {
if (args.length > 0) {
create(args[0]);
}
}
static void create(String name) {
Person p = new Person(name);
}
}
當執行Main.java
時,由於用到了Main
,因此,JVM首先會把Main.class
加載到內存。然而,並不會加載Person.class
,除非程序執行到create()
方法,JVM發現需要加載Person
類時,纔會首次加載Person.class
。如果沒有執行create()
方法,那麼Person.class
根本就不會被加載。
這就是JVM動態加載class
的特性。
動態加載class
的特性對於Java程序非常重要。利用JVM動態加載class
的特性,我們才能在運行期根據條件加載不同的實現類。例如,Commons Logging總是優先使用Log4j,只有當Log4j不存在時,才使用JDK的logging。利用JVM動態加載特性,大致的實現代碼如下:
// Commons Logging優先使用Log4j:
LogFactory factory = null;
if (isClassPresent("org.apache.logging.log4j.Logger")) {
factory = createLog4j();
} else {
factory = createJdkLog();
}
boolean isClassPresent(String name) {
try {
Class.forName(name);
return true;
} catch (Exception e) {
return false;
}
}
這就是爲什麼我們只需要把Log4j的jar包放到classpath中,Commons Logging就會自動使用Log4j的原因。
小結
- JVM爲每個加載的
class
及interface
創建了對應的Class
實例來保存class
及interface
的所有信息; - 獲取一個
class
對應的Class
實例後,就可以獲取該class
的所有信息; - 通過Class實例獲取
class
信息的方法稱爲反射(Reflection); - JVM總是動態加載
class
,可以在運行期根據條件來控制加載class。