美文网首页
由一道面试题理解类加载机制

由一道面试题理解类加载机制

作者: marsjhe | 来源:发表于2019-03-17 17:55 被阅读0次

前言

不了解JVM的类加载机制你也可以coding,但是当你了解之后,可以让你在coding的时候避免很多坑,本文将以一道常见的面试题去剖析一下。本文参考深入理解Java虚拟机(第2版)

public class ClassLoadTest {
    private static ClassLoadTest test = new ClassLoadTest();

    static int x;
    static int y = 0;

    public ClassLoadTest() {
        x++;
        y++;
    }

    public static void main(String[] args) {
        System.out.println(test.x);
        System.out.println(test.y);
    }
}

这里大家可以先猜测一下答案,可能结果会出乎你的意料~

类加载过程

先用一个图简单的描述一下类加载的这个过程


加载

这个过程相当于从本地或者网络端去读取一个字节流,然后将一些静态储存结构转换成方法区中运行时期的数据,最后生成一个代表这个类的Class对象,作为方法区访问这个类的入口。
例如:

  • 咱们可以通过一个类的全限定名去加载类
  • 通过jar、war包去加载类
  • 通过http请求去第三方平台上拉取指定的类来加载
  • 运行时计算生成,例如Cglib动态代理等等

针对上述例子,这里是加载一个ClassLoadTest.class对象。

验证

要理解这个环节并不是很难,一个东西要放到JVM上去运行,咱们肯定得对其进行一些过滤,不能啥都往上丢,这里的验证简单的举几个例子:

  • 文件格式的验证:
    ①是否以魔数0xCAFEBABE开头;
    ②主次版本号是否在当前虚拟机处理范围内;
    ③常量池中的常量是否有不被支持的常量类型等等。
  • 元数据的验证:
    ①这个类是否有父类;
    ②这个类的父类是否继承了不被允许继承的类(final修饰的类);
    ③这个类不是抽象类,是否实现了所有接口中要实现的方法等等。
  • 字节码的验证:
    ①保证跳转指令不会跳转到方法体以外的字节码指令上;
    ②保证方法体中的类型转换是有效的等等。
  • 符号引用的验证:
    ①能否通过类的全限定名去找到对应的类;
    ②符号引用中的类、字段、方法是否可以被当前类访问等等。
准备过程

这个过程相当于给类变量分配内存并设置变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。

针对上述例子:

test = null;
x = 0;
y = 0;

注意:这里有个特殊情况,如果该字段被final修饰,那么在准备阶段改字段就会被设置成咱们自定义的值。public static final int value = 11,在准备阶段就会直接赋值11,并不是该变量的初始值。

解析过程

将符号引用转换成直接引用的过程。这里有两个名词符号引用直接引用

  • 符号引用:符号引用与虚拟机的布局无关,甚至引用的目标不一定加载到了内存中。符号可以是任何形式的字面量,只要使用时能够准确的定位到目标即可。
  • 直接引用:直接引用可以直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用与虚拟机布局有关,如果有了直接引用,那么引用的目标必定已经在内存中存在。

而解析过程又会针对类、字段、方法进行解析,解析失败则会抛出相应的异常。例如在解析时发现没有访问权限会抛出java.lang.IllegalAccessException异常,查询不到引用字段会抛出java.lang.NoSuchFieldException异常,查询不到方法会抛出java.lang.NoSuchMethodException异常等等。

初始化

在准备阶段,变量已经赋值过系统要求的默认值,在初始化阶段,则会根据程序制定的主观计划去初始化类变量和其他资源。这句话听起来有些绕口,根据上述例子,实际上就是:

test = new ClassLoadTest();// x = 1;y =1
y = 0;

这个过程,由于x咱们自己并没有去设定一个值,所以初始化阶段它不会发生任何改变,但是y咱们有设定一个值0,所以最后造成最终结果为x = 1;y = 0

ps:在同一个类加载器下,一个类只会初始化一次。多个线程同时初始化一个类,只有一个线程能正常初始化,其他线程都会进行阻塞等待,直到活动线程执行初始化方法完毕。

总结

对于上面这个面试题,咱们用流程图简单的描述一下:


End

相关文章

  • 由一道面试题理解类加载机制

    前言 不了解JVM的类加载机制你也可以coding,但是当你了解之后,可以让你在coding的时候避免很多坑,本文...

  • 由一道面试题理解类加载机制

    前言 不了解JVM的类加载机制你也可以coding,但是当你了解之后,可以让你在coding的时候避免很多坑,本文...

  • 深入理解Java类加载

    本文目的: 深入理解Java类加载机制; 理解各个类加载器特别是线程上下文加载器; Java虚拟机类加载机制 虚拟...

  • 深入理解 Java 类加载

    本文目的: 深入理解Java类加载机制; 理解各个类加载器特别是线程上下文加载器; Java虚拟机类加载机制 虚拟...

  • ClassLoader双亲委派机制源码分析

    前言:为了更好的分析Tomcat的类加载机制,首先要对JDK的类加载机制有较为深入的理解,JDK类加载机制的前期理...

  • java类加载机制

    java类加载机制的七个阶段 两道面试题,带你解析Java类加载机制 - 陈树义 - 博客园 当我们的Java代码...

  • 类加载机制(一)

    加载机制系列类加载机制(一)类加载机制(二)类加载机制(三) 类加载机制 1.JVM把class文件加载到内存,对...

  • 类加载机制

    类加载机制 类加载由7个步骤完成,类的生命周期是由7个阶段组成,但是类的加载说的是前5个阶段 类加载器 加载 1、...

  • 理解类加载机制

    类加载器 1. 类加载器作用类加载器本身作用就是用于加载类的,将类转换成java.lang.Class的实例;类加...

  • 谈谈JVM类加载机制与内存模型

    1、类加载机制 1.1、什么是类加载机制 我的理解是Java编译器将java文件编译成字节码文件,然后类加载器将字...

网友评论

      本文标题:由一道面试题理解类加载机制

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