【java】JVM-类加载机制

加班使我快乐!

点赞再看,养成习惯!

开始之前,先来两张图冷静一下。

类加载机制流程图

java程序的执行流程图

一、类加载机制的概念

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

二、类加载的生命周期

类从被加载到JVM内存开始,到卸载出内存位置,它的生命周期如下所示:

在类加载的过程中,加载、验证、准备和初始化这四个阶段发生的顺序是确定的,而解析阶段则不一定,他在某些情况下可以在初始化阶段之后开始,这是为了支持java语言的运行时绑定。

类初始化的时机:

  • 创建类的实例
  • 调用某个类的类方法(静态方法)
  • 访问某个类或接口的类变量,或为该类变量赋值
  • 使用反射方式来强制创建某个类或接口对应的java.lang.class对象
  • 初始化某个类的子类
  • 直接使用java.exe命令来运行某个主类

三、类加载器的层次关系

站在Java虚拟机的角度来讲,只存在两种不同的类加载器:
  • 启动类加载器:它使用C++实现(这里仅限于Hotspot,也就是JDK1.5之后默认的虚拟机,有很多其他的虚拟机是用Java语言实现的),是虚拟机自身的一部分。
  • 所有其他的类加载器:这些类加载器都由Java语言实现,独立于虚拟机之外,并且全部继承自抽象类java.lang.ClassLoader,这些类加载器需要由启动类加载器加载到内存中之后才能去加载其他的类。
站在Java开发人员的角度来看,类加载器可以大致划分为以下三类:
  • 启动类加载器:Bootstrap ClassLoader,跟上面相同。它负责加载存放在JDK\jre\lib(JDK代表JDK的安装目录,下同)下,或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库(如rt.jar,所有的java.*开头的类均被Bootstrap ClassLoader加载)。启动类加载器是无法被Java程序直接引用的。
  • 扩展类加载器:Extension ClassLoader,该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载JDK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如javax.*开头的类),开发者可以直接使用扩展类加载器。
  • 应用程序类加载器:Application ClassLoader,该类加载器由sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

这种层次关系叫做类加载器的双亲委派模型。每一层上面的类加载器叫做当前层类加载器的父加载器,但是他们之间的父子关系不是由继承来实现的,而是通过组合关系来复用父加载器中的代码。

工作流程:一个类加载器收到了类加载的请求后,他会把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递的顶层的启动类加载器中(从底向上检查类是否被加载),如果在父加载器中没有找到所需的类,子加载器才会尝试自己去加载类(从顶向下加载类)。

四、一道面试题

能不能写一个类叫java.lang.System?

答案:不可以。我们不能写以“java.”开头的类,因为它要么不能加载进内存,要么即使你是用自定义的类去强行加载,也会收到一个SecurityException.

原文链接:https://blog.csdn.net/tang9140/article/details/42738433

发布了150 篇原创文章 · 获赞 94 · 访问量 6万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章