JVM学习笔记——类的加载机制

类加载的过程:加载、验证、准备、解析、初始化 加载 通过类的全类名获取定义此类的二进制字节流 通过字节流获取静态存储结构并转化为方法区的运行时数据结构 生成一个代表该类的java.lang.Class对象,作为访问方法区数据的入口。 验证 文件格式验证,验证字节流是否Class文件格式的规范,文件能否被当前版本的虚拟机处理。 元数据验证,对字节码信息进行语义分析,保证其符合Java语法。 字节码验证,针对方法内指令级别的验证,保证字节码指令不会危害虚拟机安全。 符号引用验证,由符号引用转为直接引用时的验证,即发生在“解析”阶段。验证符号引用的内容是否能找到匹配的信息,例如:符号引用中通过全类名能找到对应的类,符号引用中的信息,可见性(private、public..)是否能被当前类访问等等。 准备 为类分配内存,设置类变量默认初始值。 解析 将类内部的“符号引用”替换为“直接引用”。替换的范围包括,类或接口名,字段名,类方法名,接口方法名。 符号引用 以一组符号来描述所引用的目标,比如 String s = "a" ,使用s时就会被解析成符号引用。 直接引用 可以直接指向目标的指针、偏移量或是一个能间接定位到目标的句柄。比如 System.out.print("abc") ,其中“abc”就会被解析为直接引用。 初始化 生成并运行()方法。 生成 ()方法会收集类变量初始赋值操作以及静态代码块的内容,按照源文件中出现的顺序进行收集。 在没有类变量初始化操作以及静态代码块时,()可以不生成。 运行 JVM会保证父类的()先于子类的()执行。 接口与类不同,子接口的()执行时,如果没有引用父接口的变量,则父接口的()不会执行。 ()执行时JVM会对其进行加锁,也就是说多个线程执行()时,只有一个线程会执行,其他线程将会阻塞等待执行完毕。 类加载器 类加载器就是实现“加载”这个动作的组件。在Java中,两个类是否“相等”,必须在这两个类是由同一个类加载器加载的前提下。这里的“相等”,包括:Class的equals()、Class的isInstance()、instanceof关键字等等。 启动类加载器(Bootstrap ClassLoader) 负责加载<JAVA_HOME>\lib目录中的类库。 扩展类加载器(Extension ClassLoader) 负责加载<JAVA_HOME>\lib\ext目录中的类库。 应用程序类加载器(Application ClassLoader) 这个加载器是ClassLoader中getSystemClassLoader的返回值,默认情况下这个就是程序中默认的类加载器,它负责加载应用程序的类路径的上的类库(ClassPath)。 双亲委派模型 所有类加载器遵循“父子”的层级关系(这里的“父子关系一般使用复合而非继承”),当一个类加载时优先委托给父级的加载器进行加载,若所有父级加载器都无法加载该类时,才会到本加载器加载。 OSGi的类加载模型 OSGi将每个模块称为Bundle,与普通的Java类库差别不大,都是Package与Class。Bundle将所依赖的Package通过Import-Packge进行声明,将允许导出的Package通过Export-Packge声明。如果某个Bundle依赖了某个Package,那么所有对这个Package内的类加载,全部会交给Export该Package的Bundle的类加载器进行处理。详细的类加载规则如下: 以java.*开头的类,委派给父类加载器 否则,委派列表内的类委派给父类加载器 否则,Import列表中的类,委派给Export这个类的Bundle的类加载器。 否则,查找当前Bundle的ClassPath,使用自己的类加载器。 否则,查找是否存在自己的Fragement Bundle中,如果是则委派给Fragement Bundle的类加载器。 否则,查找Dynamic Import列表的Bundle,委派给对应的Bundle的类加载器。 否则,类加载失败。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值