JVM第四讲:JVM 基础-类加载机制

本文是JVM第四讲:类加载机制,这篇文章将带你深入理解Java 类加载机制。

1、简述java类加载机制?

  • 虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的 java 类型。

2、类加载的机制及过程 阿里

程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载、链接、初始化3个步骤来对该类进行初始化。JVM将会连续完成3个步骤,所以有时也把这个3个步骤统称为类加载或类初始化。

  • JVM 类加载机制分为五个部分: 加载, 验证, 准备, 解析, 初始化。如下图所示
    在这里插入图片描述
  • 1、加载
    • 加载指的是将类的 class 文件读入到内存,并将这些静态数据转换成方法区中的运行时数据结构,并在堆中生成一个代表这个类的 java.lang.Class 对象,作为方法区类数据的访问入口,这个过程需要类加载器参与。
    • Java类加载器由JVM提供,是所有程序运行的基础,JVM提供的这些类加载器通常被称为系统类加载器。除此之外,开发者可以通过继承 ClassLoader 基类来创建自己的类加载器。
    • 类加载器,可以从不同来源加载类的二进制数据,比如:本地Class文件、Jar包Class文件、网络 Class 文件等等等。
    • 类加载的最终产物就是位于堆中的 Class 对象(注意不是目标类对象),该对象封装了类在方法区中的数据结构,并且向用户提供了访问方法区数据结构的接口,即 Java 反射的接口
  • 2、链接
    • 当类被加载之后,系统为之生成一个对应的Class对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中(意思就是将java类的二进制代码合并到JVM的运行状态之中)。类连接又可分为如下3个阶段。
      • 验证:确保加载的类信息符合JVM规范,没有安全方面的问题。主要验证是否符合 Class文件格式规范,并且是否能被当前的虚拟机加载处理;
      • 准备:正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配;
      • 解析:虚拟机常量池的符号引用替换为字节引用过程。
  • 3、初始化(初始化是为类的静态变量赋予正确的初始值)
    • 初始化阶段是执行类构造器< clinit>() 方法的过程。类构造器< clinit>()方法是由编译器自动收藏类中的所有类变量的赋值动作和静态语句块( static块 )中的语句合并产生,代码从上往下执行;
    • 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化;
    • 虚拟机会保证一个< clinit>() 方法在多线程环境中被正确加锁和同步
    • 类的初始化仅会被执行一次,这个特性被用来实现单例的延迟初始化
    • 类的初始化何时会被触发呢?
      • 1、当虚拟机启动时,初始化用户指定的主类;
      • 2、当遇到用以新建目标类实例的 new 指令时,初始化 new 指令的目标类;
      • 3、当遇到调用静态方法的指令时,初始化该静态方法所在的类;
      • 4、当遇到访问静态字段的指令时,初始化该静态字段所在的类;
      • 5、子类的初始化会触发父类的初始化;
      • 6、如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化;
      • 7、使用反射 API 对某个类进行反射调用时,初始化这个类;
      • 8、当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类

Demo,饿汉式单例,只有当调用 Singleton.getInstance 时,程序才会访问 LazyHolder.INSTANCE,才会触发对LazyHolder 的初始化(对应第四种情况)

public class Singleton {
	private Singleton() {}
	private static class LazyHolder {
		static final Singleton INSTANCE = new Singleton();
	}
	public static Singleton getInstance() {
		return LazyHolder.INSTANCE;
	}
}

3、描述一下JVM加载Class文件的原理机制

Java中的所有类,都需要由类加载器装载到JVM中才能运行。类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中。在写程序的时候,我们几乎不需要关心类的加载,因为这些都是隐式装载的,除非我们有特殊的用法,像是反射,就需要显式的加载所需要的类。

类装载方式,有两种 :

  • 1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中,
  • 2.显式装载, 通过class.forName()等方法,显式加载需要的类

Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到 jvm 中,至于其他类,则在需要的时候才加载。这当然就是为了节省内存开销。

4、什么是 tomcat 类加载机制?

当 tomcat启动时,会创建几种类加载器: Bootstrap 引导类加载器 加载 JVM启动所需的类,以及标准扩展类(位于 jre/lib/ext 下) System 系统类加载器 加载 tomcat 启动的类,比如
bootstrap.jar,通常在 catalina.bat 或者 catalina.sh 中指定。位于 CATALINA_HOME/bin 下

Common 通用类加载器

5、什么是类加载器,类加载器有哪些?

在这里插入图片描述
实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。

主要有一下四种类加载器:

  • 启动类加载器(Bootstrap ClassLoader) 用来加载java核心类库,无法被 java 程序直接引用。
  • 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
  • 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过ClassLoader. getSystemClassLoader() 来获取它。
  • 用户自定义类加载器,通过继承 java.lang.ClassLoader 类的方式实现。

6、 自己写过 String 类能加载吗, 之前的 String 是什么时候加载进去的? 阿里

  • 不能加载, 因为双亲委派机制, JVM 出于安全性的考虑, 全限定类名相同的 String 是不能被加载的。
  • java.lang.String 会被顶级类加载器 Bootstrap Classloader 加载。 当 class 文件被加载到内存中时, 类文件常量池中的其他常量会加载到运行时常量池, 但是字符串常量不会。 它会首先在堆区中创建一个字符串对象, 然后再把这个对象的引用保存到全局字符串常量池中。

7、什么是双亲委派模型?

  • 如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有的加载请求都会被传送到顶层的启动类加载器中,只有当父加载无法完成加载请求(它的搜索范围中没找到所需的类)时,子加载器才会尝试去加载类。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
《深入理解JVM第四版》是一本关于Java虚拟机(JVM)原理和实现的经典著作。它由周志明所著,共计300页。这本书的主要目的是教读者如何深入理解并掌握JVM的工作原理和内部机制。 本书首先介绍了JVM的基本概念和结构。它详细解释了JVM如何加载、验证、解析和初始化Java。此外,书中还涉及了运行时数据区域的结构和功能,包括堆、栈、方法区等。 接下来,本书讨论了JVM的垃圾回收机制。它介绍了不同型的垃圾回收算法和相关的性能调优技术。读者可以通过阅读这一部分,了解如何优化程序的内存使用和垃圾回收效率。 此外,本书还涵盖了JVM的即时编译器和优化技术。它详细介绍了JIT编译器的工作原理,并解释了常用的优化技术,如内联、逃逸分析和锁消除等。这对于那些希望通过编写高效的Java代码来提高程序性能的开发人员来说非常有用。 最后,本书还提供了一些高级主题,如加载器、字节码增强和调试技术。通过阅读这些章节,读者可以加深对JVM内部机制的理解,并学习如何调优和调试JVM相关的问题。 总体而言,《深入理解JVM第四版》是一本全面而深入的JVM学习资料。它适合那些希望更深入了解JVM内部工作原理的Java开发人员。无论是学生、工程师还是研究人员,都可以从这本书中获得宝贵的知识和技巧。读者可以通过仔细阅读和实践书中的示例代码,提升自己的Java编程能力和理解JVM的水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员 jet_qi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值