JVM 类加载器(1)

i263315.jpg

在 java 代码中,类的加载连接初始化过程都是在程序运行期间完成的。
提供了更大的灵活性,增加了更多的可能性,在一阵烟雾弥漫后,大力神 JVM 将 class 加载到内存来完成强大的功能。

devastator-574x499.jpg

loader-illustration.png

而且在 JVM 中对有些规范并没有给出严格要求,只是进行一些描述,厂商可以根据自己需要,来实现适合自己的 JVM,阿里巴巴就自己的 jvm

Java虚拟机与程序的生命周期
在如下几种情况下,Java虚拟机将结束生命周期

  • 执行了 System.exit() 方法
  • 程序正常执行结束
  • 程序在执行过程中遇到了异常或错误而异常终止
  • 由于操作系统出现错误导致 java 虚拟机进程终止
8207483-5482742d6c86e3a8.jpeg

load-states.png

详解 JVM 的机制(1)

1. 加载

查找并加载类的二进制数据

2. 连接

验证

确保被加载的类的正确性

准备

为类的静态变量分配内存,并将其初始化为默认值

解析

把类中的符号引用转换为直接引用

3. 解析

把类的静态变量赋予正确的初始值

java 程序对类的使用方式分为两种

  • 主动使用
    1. 创建类的实例
    2. 访问或对类或接口的静态变量赋值,访问以及赋值的助记符getstaticsetstatic
    3. 调用静态方法,对应的助记符invokestatic
    4. 反射
    5. 初始化一个类的子类
    6. JVM 启动时表明为启动类的类
    7. JDK 1.7 开始提供的动态语言支持
  • 被动使用
    所有的 Java 虚拟机实现必须在每一个类或接口被 Java 程序首次主动使用时才初始化他们

类的加载

类的加载将类的.class 文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在内存中创建一个 java.lang.class 对象来封装类在方法区的数据结构。
加载.class 文件的方式

  • 从本地系统中直接加载
  • 网络下载 class 文件
  • 从 zip, jar 等归档文件中加载 .class 文件
  • 从专有数据库提取.class文件
  • 将java 源文件动态编译为.class文件

-XX: +

class Parent {
    public static String parentStr = "parent static";
    static {
        System.out.println("parent static block");
    }
}

class Child extends Parent{
    public static String childStr = "child static";
    static {
        System.out.println("child static block");
    }
}

public class ZiClient {
     public static void main(String[] args) {
         System.out.println("hello jvm");
         System.out.println(Child.parentStr);
    }
}
hello jvm
parent static block
parent static

从输出上来看这里并没有初始化 Child ,只是初始化 Parent 因为打印了 Parent static 代码块内容


屏幕快照 2019-04-06 下午4.56.35.png

可以通过开启 TraceClassLoading 选项来查看 JVM 加载类的过程。

hello jvm
[0.556s][info   ][class,load] sun.net.spi.DefaultProxySelector$NonProxyInfo source: jrt:/java.base
[0.556s][info   ][class,load] sun.net.spi.DefaultProxySelector$4 source: jrt:/java.base
[0.556s][info   ][class,load] sun.net.NetHooks source: jrt:/java.base
[0.557s][info   ][class,load] sun.net.NetHooks$Provider source: jrt:/java.base
[0.557s][info   ][class,load] sun.net.sdp.SdpProvider source: jrt:/java.base
[0.557s][info   ][class,load] com.zidea.jvm.demo.Parent source: file:/Users/jangwoo/IdeaProjects/learnjvm3/target/classes/
[0.557s][info   ][class,load] com.zidea.jvm.demo.Child source: file:/Users/jangwoo/IdeaProjects/learnjvm3/target/classes/
parent static block
parent static

然后我们就可以查看到了虽然没有初始化 Child 类,但是已经将这个 Child 进行了加载。

class Parent {
    public static String final parentStr = "parent static";
    static {
        System.out.println("parent static block");
    }
}

我们将 parentStr 变为 final 类型后再次运行应用得到下面结果,具体原因请看下次分解...

hello jvm
parent static

你可能感兴趣的:(JVM 类加载器(1))