Java反射-类动态加载

  • Post author:
  • Post category:java


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。