通过实例解析Java class文件编译加载过程

一、Java从编码到执行

首先我们来看一下Java是如何从编码到执行的呢? 我们有一个x.java文件通过执行javac命令可以变成x.class文件,当我们调用Java命令的时候class文件会被装载到内存中,这个过程叫做classloader。一般情况下我们自己写代码的时候会用到Java的类库,所以在加载的时候也会把Java类库相关的类也加载到内存中。装载完成之后会调用字节码解释器和JIT即时编译器来进行解释和编译,编译完之后由执行引擎开始执行,执行引擎下面对应的就是操作系统硬件了。下图是大体的流程:

Java叫做跨平台的语言,JVM可以称之为跨语言的平台;

有个问题:java是解释执行还是编译执行?答:解释和编译是可以混合的,特别常用的代码或则是代码用到的次数特别多的时候,会把一个即时编译做成本地编译,这样会很大程度上的提高效率。

Java虚拟机是如何做到这么多语言都可以在上面运行,关键在于class文件,任何语言只要能编译成class文件,并且符合class文件的规范你就可以放在Java虚拟机上去运行。

二、详解class文件的加载过程

接下来主要讲的是一个class文件是怎么从硬盘上到内存中,并开始执行的。

类加载主要有三个过程:loading 、linking 、initializing;其中linking又分为三个步骤:verification 、preparation 、resolution;

1、首先Loading是什么意思呢?是把一个class问价load到内存中去;

2、接下来是Linking分为了三小步:

verification 是用来校验加载进来的class文件是否符合class文件标准,如果不符合直接就会被拒绝了;
preparation 是将class文件静态变量赋默认值而不是初始值,例如static int i =8;这个步骤并不是将i赋值为8,而是赋值为默认值0;
resolution 是把class文件常量池中用到的符号引用转换成直接内存地址,可以访问到的内容;
3、initializing 成为初始化,静态变量在这个时候才会被赋值为初始值;

下面为类加载过程的简化图:

类加载器的加载过程是分成不同的层次来加载的,不同的类加载器来加载不同的class文件, Bootstrap >Extension>Application>Custom(自定义类加载器)

1、第一个类加载器的层次为:Bootstrap 称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库。

2、第二个类加载器的层次为:Extension 是用来加载扩展类的,主要负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目录下的所有jar包。

3、第三个类加载器的层次为:Application又称为系统类加载器,负责在JVM启动时,加载来自在命令java中的classpath或者java.class.path系统属性或者CLASSPATH操作系统属性所指定的JAR类包和类路径。

4、第三个类加载器的层次为:CustomClassLoader(自定义加载器)

package com.example.demo.classloader;

public class ClassLoaderScope {
  public static void main(String[] args) {
    System.out.println("-------------------Bootstrap加载类-------------------");
    String property = System.getProperty("sun.boot.class.path");
    String s = property.replaceAll(";", System.lineSeparator());
    System.out.println(s);

    System.out.println("-------------------Ext加载类-------------------");

    String property1 = System.getProperty("java.ext.dirs");
    String s1 = property1.replaceAll(";", System.lineSeparator());
    System.out.println(s1);

    System.out.println("-------------------App加载类-------------------");

    String property2 = System.getProperty("java.class.path");
    String s2 = property2.replaceAll(";", System.lineSeparator());
    System.out.println(s2);
  }
}
    /**输出结果只截取了部分*/
    //E:\JDK\jdk1.8\jre\lib\resources.jar
    //E:\JDK\jdk1.8\jre\lib\rt.jar
    //E:\JDK\jdk1.8\jre\lib\sunrsasign.jar
    //E:\JDK\jdk1.8\jre\lib\jsse.jar
    //E:\JDK\jdk1.8\jre\lib\jce.jar
    //E:\JDK\jdk1.8\jre\lib\charsets.jar
    //E:\JDK\jdk1.8\jre\lib\jfr.jar
    //E:\JDK\jdk1.8\jre\classes
    //----------------------------------------------
    //E:\JDK\jdk1.8\jre\lib\ext
    //C:\Windows\Sun\Java\lib\ext
    //----------------------------------------------
    //E:\JDK\jdk1.8\jre\lib\charsets.jar
    //E:\JDK\jdk1.8\jre\lib\deploy.jar
    //E:\JDK\jdk1.8\jre\lib\ext\access-bridge-64.jar
    //E:\JDK\jdk1.8\jre\lib\ext\cldrdata.jar
    //E:\JDK\jdk1.8\jre\lib\ext\dnsns.jar
    //E:\JDK\jdk1.8\jre\lib\ext\jaccess.jar
    //E:\JDK\jdk1.8\jre\lib\ext\jfxrt.jar

你可能感兴趣的:(通过实例解析Java class文件编译加载过程)