美文网首页
Java - 什么时候加载class

Java - 什么时候加载class

作者: 齐晋 | 来源:发表于2018-06-08 07:20 被阅读38次

我们知道,.java文件会被编译成.class文件。JVM虚拟机会把.class文件在必要的时候load到内存中。

那么,class究竟是在什么时候被load的呢?启动的时候就load吗?

不同的虚拟机有不同的策略,但是最根本的策略是:“只有在需要该class的时候,才会把class load到内存”

举个例子:
有两个java文件,TestJava.java和A.java

//TestLoader.java
public class TestLoader {
    public static void main(String[] args) {
        System.out.println("test");
    }
}
//A.java
public class A {
    public void method(){
        System.out.println("inside of A");
    }
}

工程的目录结构如下所示:


image.png

下面,我们通过命令启动程序,看看类是什么时候被加载的。在命令行中,添加-verbose:class参数,可以查看类被加载的情况:

java -verbose:class -classpath /home/ron/workspace/UltimateTest/bin/ compiler.TestLoader

部分输出为:

[Loaded sun.misc.JavaSecurityProtectionDomainAccess from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.ProtectionDomain from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.ProtectionDomain from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.Principal from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded compiler.TestLoader from file:/home/xiwang/workspace/UltimateTest/bin/]
test
[Loaded java.lang.Shutdown from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]

可见,只有TestJava被加载了。

我们将TestJava.java修改一下:

//TestJava.java
public class TestLoader {
    public static void main(String[] args) {
        System.out.println("test");
        A a = new A();
        a.method();
    }
}

执行上面同样的命令,部分输出为:

[Loaded sun.misc.JavaSecurityProtectionDomainAccess from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.ProtectionDomain from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.ProtectionDomain from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.Principal from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded compiler.TestLoader from file:/home/xiwang/workspace/UltimateTest/bin/]
test
[Loaded compiler.A from file:/home/xiwang/workspace/UltimateTest/bin/]
inside of A
[Loaded java.lang.Shutdown from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]

可见,A这时候被load了。

再举个例子:

public class SomethingCaller {
    public static Something something = null; // (1) does not cause class loading
    public static Class<?> somethingClass = Something.class; // (2) causes class loading

    public void doSomething() {
        new Something(); // (3) causes class loading
    }
}

上面的(1)没有触发类加载,因为这个语句不需要知道Something这个类的结构,也就是不需要这个类

(2)和(3)是触发了类加载的。因为,对(2)来讲,Something.class这样的语句是需要知道Something的类结构的。同样,对(3)来讲,调用构造函数,更是需要知道类结构的。也就是在需要这个类的时候,类才被加载。

例子3:

public class SomethingTest {
    public static void main(String[] args) {
        new SomethingCaller();
    }
}

public class SomethingCaller {
    public void doSomething() {
        Class<?> somethingClass = Something.class;
    }
}

public class Something {}

上面的代码不会触发Something的类加载。但是如果doSomething()方法被调用的话,就会触发Something的类加载。

参考

相关文章

网友评论

      本文标题:Java - 什么时候加载class

      本文链接:https://www.haomeiwen.com/subject/htlosftx.html