首页 > 其他分享 >JVM类加载机制

JVM类加载机制

时间:2024-06-15 14:33:17浏览次数:23  
标签:Java 虚拟机 双亲 JVM 机制 方法 ClassLoader 加载

类加载机制
概述
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7 个阶段。其中验证、准备、解析 3 个部分统称为连接(Link)。

初始化的单例模式(线程安全)
虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕。如果在一个类的<clinit>()方法中有耗时很长的操作,就可能造成多个进程阻塞。所以类的初始化是线程安全的,项目中可以利用这点。

类加载器
对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在 Java 虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。这句话可以表达得更通俗一些:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个 Class 文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。这里所指的“相等”,包括代表类的 Class 对象的 equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果,也包括使用 instanceof 关键字做对象所属关系判定等情况。

双亲委派模型
对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在 Java

从 Java 虚拟机的角度来讲,只存在两种不同的类加载器:
一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用 C++语言实现,是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由 Java 语言实现,独立于虚拟机外部,并且全都继承自抽象类 java.lang.ClassLoader。
启动类加载器(Bootstrap ClassLoader):这个类加器负责将存放在<JAVA_HOME>\lib 目录中的,或者被-Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar,名字不符合的类库即使放在 lib 目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被 Java程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用 null 代替即可。
扩展类加载器(Extension ClassLoader):这个加载器由 sun.misc.Launcher$ExtClassLoader 实现,它负责加载
<JAVA_HOME>\lib\ext
目录中的,或者被java.ext.dirs 系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。

应用程序类加载器(Application ClassLoader):这个类加载器由 sun.misc.Launcher $App-ClassLoader 实现。由于这个类加载器是 ClassLoader 中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
我们的应用程序都是由这 3 种类加载器互相配合进行加载的,如果有必要,还可以加入自己定义的类加载器。双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里类加载器之间的父子关系一般不会以继承(Inheritance)的关系来实现,而是都使用组合(Composition)关系来复用父加载器的代码

使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是 Java 类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在 rt.jar 之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此 Object 类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中将会出现多个不同的 Object 类,Java 类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。

应用程序类加载器
ClassLoader 中的 loadClass 方法中的代码逻辑就是双亲委派模型:
在自定义 ClassLoader 的子类时候,我们常见的会有两种做法,一种是重写 loadClass 方法,另一种是重写 findClass 方法。其实这两种方法本质上差不多,毕竟 loadClass 也会调用 findClass,但是从逻辑上讲我们最好不要直接修改 loadClass 的内部逻辑。我建议的做法是只在 findClass 里重写自定义类的加载方法。
loadClass 这个方法是实现双亲委托模型逻辑的地方,擅自修改这个方法会导致模型被破坏,容易造成问题。因此我们最好是在双亲委托模型框架内进行小范围的改动,不破坏原有的稳定结构。同时,也避免了自己重写 loadClass 方法的过程中必须写双亲委托的重复代码,从代码的复用性来看,不直接修改这个方法始终是比较好的选择。

标签:Java,虚拟机,双亲,JVM,机制,方法,ClassLoader,加载
From: https://www.cnblogs.com/velloLei/p/18249268

相关文章

  • jvm调优工具和调优策略
    JDK为我们提供的jvm工具命令行工具jps、jstat、jinfo、jmap、jhat、jstack可视化工具JMX、Jconsole、visualvm生产服务器推荐开启-XX:-HeapDumpOnOutOfMemoryError默认关闭,建议开启,在java.lang.OutOfMemoryError异常出现时,输出一个dump.core文件,记录当时的堆内存快......
  • JVM垃圾回收算法和垃圾回收器
    垃圾回收算法复制算法(Copying)将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情......
  • JVM中的对象
    虚拟机中的对象对象的分配虚拟机遇到一条new指令时:根据new的参数是否能在常量池中定位到一个类的符号引用,如果没有,说明还未定义该类,抛出ClassNotFoundException1)检查加载先执行相应的类加载过程。如果没有,则进行类加载2)分配内存根据方法区的信息确定为该类分配的内存空......
  • JVM垃圾回收策略机制和算法
    判断对象的存活引用计数法给对象添加一个引用计数器,当对象增加一个引用时计数器加1,引用失效时计数器减1。引用计数为0的对象可被回收。(Python在用,但主流虚拟机没有使用)优点:快,方便,实现简单。缺陷:对象相互引用时(A.instance=B同时B.instance=A),很难判断对象是否该回收。......
  • 【SPARK-CORE】checkpoint机制
    本文主要介绍SPARKRDD的checkpoinnt机制 checkpoint机制介绍checkpoint是讲RDD保存到可靠的存储中的机制,主要目的是提高应用的容错能力和持久性。Checkpointing将数据从内存中转移到磁盘存储,使得在出现节点故障时,Spark可以从存储中恢复数据,而不需要重新计算所有的数据。这......
  • JVM运行时数据区(线程相关)
    一、JVM运行时数据区JVM运行时数据区是一个抽象概念,主要依赖于寄存器、高速缓存、主内存几个部分组成。计算机运行=指令+数据,指令用于执行方法,数据用于指向存放的数据和对象。虚拟机栈---用于执行java方法本地方法栈---执行本地方法(通常时c语言实现的)程序计数......
  • 6、Git之团队协作机制
    6.1、团队内协作6.1.1、创建本地库如上图所示,一个名叫刘备的人,在本地电脑中创建了一个项目,并使用git来维护。6.1.2、推送本地库到代码托管中心如上图所示,刘备想让别人也能看到自己本地库中的内容,就通过push命令,将本地库复制上传到代码托管中心,形成远程库。关于代码托......
  • 核心(Hutool-core)工具类(SPI加载工具-ServiceLoaderUtil)
    介绍SPI(ServiceProviderInterface),是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。更多介绍见:https://www.jianshu.com/p/3a3edbcd8f24使用定义一个接口:packagecn.hutool.test.spi;publicinterfaceSPIService......
  • 核心(Hutool-core)工具类(类加载工具-ClassLoaderUtil)
    介绍提供ClassLoader相关的工具类,例如类加载(Class.forName包装)等方法获取ClassLoadergetContextClassLoader获取当前线程的ClassLoader,本质上调用Thread.currentThread().getContextClassLoader()getClassLoader按照以下顺序规则查找获取ClassLoader:获取当前线程的Context......
  • 【Java】 反射机制及其应用
    >>【痕迹】QQ+微信朋友圈和聊天记录分析工具>>(1)纯Python语言实现,使用Flask后端,本地分析,不上传个人数据。>>(2)内含QQ、微信聊天记录保存到本地的方法,真正实现自己数据自己管理。>>(3)数据可视化分析QQ、微信聊天记录,提取某一天的聊天记录与大模型对话。>>下载地......