java 中类加载器

jar 运行过程和类加载机制有关,而类加载机制又和我们自定义的类加载器有关,现在我们先来了解一下双亲委派模式。

java 中类加载器分为三个:

  • BootstrapClassLoader 负责加载 ${JAVA_HOME}/jre/lib 部分 jar 包
  • ExtClassLoader 加载 ${JAVA_HOME}/jre/lib/ext 下面的 jar 包
  • AppClassLoader 加载用户自定义 -classpath 或者 Jar 包的 Class-Path 定义的第三方包

类的生命周期为:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using) 和 卸载(Unloading)七个阶段。

当我们执行 java -jar 的时候 jar 文件以二进制流的形式被读取到内存,但不会加载到 jvm 中,类会在一个合适的时机加载到虚拟机中。类加载的时机:

  • 遇到 new、getstatic、putstatic 或 invokestatic 这四条字节码指令时,如果类没有进行过初始化,则需要先对其进行初始化。这四条指令的最常见的 Java 代码场景是使用 new 关键字实例化对象的时候,读取或设置一个类的静态字段调用一个类的静态方法的时候。
  • 使用 java.lang.reflect 包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
  • 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  • 当虚拟机启动时,用户需要指定一个要执行的主类(包含 main() 方法的那个类),虚拟机会先初始化这个主类。

当触发类加载的时候,类加载器也不是直接加载这个类。首先交给 AppClassLoader ,它会查看自己有没有加载过这个类,如果有直接拿出来,无须再次加载,如果没有就将加载任务传递给 ExtClassLoader ,而 ExtClassLoader 也会先检查自己有没有加载过,没有又会将任务传递给 BootstrapClassLoader ,最后 BootstrapClassLoader 会检查自己有没有加载过这个类,如果没有就会去自己要寻找的区域去寻找这个类,如果找不到又将任务传递给 ExtClassLoader ,以此类推最后才是 AppClassLoader 加载我们的类。这样做是确保类只会被加载一次。通常我们的类加载器只识别 classpath (这里的 classpath 指项目根路径,也就是 jar 包内的位置)下 .class 文件。jar 中其他的文件包括 jar 包被当做了资源文件,而不会去读取里面的 .class 文件。但实际上我们可以通过自定义类加载器来实现一些特别的操作

原文地址:https://www.cnblogs.com/zeenzhou/p/11224744.html

时间: 2024-10-19 18:50:23

java 中类加载器的相关文章

Java 之 类加载器

一.类加载器概述 在开发中会遇到 java.lang.ClassNotFoundException 和 java.lang.NoClassDefError,想要更好解决这类问题,或者在一些特殊的应用场景,比如需要支持类的动态加载或需要对编译后的字节码文件进行加密解密操作,那么需要你自定义类加载器,因此了解类加载器及其加载机制成为了Java开发必备技能之一. 二.四种类加载器 1.引导类加载器(Bootstrap Classloader),又称为根类加载器 它负责加载 Java 的核心库(JAVA

java自定义类加载器

前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是eclipse项目中的bin目录里),然后通过java反射机制,获取main方法并执行..class文件名称固定.当 A.class文件更新的时候,问题出现了,main方法的执行结果总和第一次的执行结果相同. 程序流程 代码提交->接收代码->编译成A.class文件->java反射->m

分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码

先回顾一下classpath classpath的作用: classpath的作用是指定查找类的路径:当使用java命令执行一个类(类中的main方法)时,会从classpath中进行查找这个类. 指定classpath的方式一:         设置环境变量CLASSPATH,多个路径之间使用英文的分号隔开,也可以指定为jar包路径.          示例:CLASSPATH=c:/myclasses/;c/mylib/aa.jar;c:/mylib/bb.jar;.          注意

ClassLoader Java中类加载出现在哪个阶段,编译期和运行期? 类加载和类装载是一样的吗

1.ClassLoader Java中类加载出现在哪个阶段,编译期和运行期? 类加载和类装载是一样的吗? :当然是运行期间啊,我自己有个理解误区,改正后如下:编译期间编译器是不去加载类的,只负责编译而已,去rt.jar拿数据干嘛,不依然是class文件,jvm是只要是class文件就能运行. 2.类加载ClassLoader,各个类加载器执行顺序是什么? :永远是自己写的加载器先去加载,记住并不是真正的加载,而是双亲委派机制,每个加载器都不真正去加载,而是去让父加载器去加载,想一下,自然界亦是如

Java的类加载器

1. Java的类加载器的种类都有哪些? 1.根类加载器(Bootstrap) --C++写的 ,看不到源码 2.扩展类加载器(Extension) --加载位置 :jre\lib\ext中 3.系统(应用)类加载器(System\App) --加载位置 :classpath中 4.自定义加载器(必须继承ClassLoader) 2. 类什么时候被初始化?  1)创建类的实例,也就是new一个对象 2)访问某个类或接口的静态变量,或者对该静态变量赋值 3)调用类的静态方法 4)反射(Class.

java 用类加载器的方式管理资源和配置文件

public class ReflectTest {public static void main(String[] args) throws Exception {    //config.properties 与当前类在不同包下:    InputStream is=ReflectTest.class.getResourceAsStream("/com/jhon/copy/config.properties");    //在同一个包下    //InputStream is=Re

Java中类加载机制和反射技术

我们知道一个对象在运行时有两种类型,一个是编译类型,一个是运行时类型.在程序运行时,往往是需要发现类和对象的真实的信息的.那么如何获的这种信息呢? 其一,如果我们在编译和运行时都知道类型的具体信息,这时是可以手动将一个对象转换为运行时的类型. 其二,如果我们在编译时无法预知对象和类到底是属于哪些类,那么程序只有依靠运行时的信息来发现对象和类的真实的信息了,这时就必须要用到反射技术. 在谈具体的发射技术之前,我想先回顾下,有关类的加载的一些基本的性质和原理,以方便我们更好地理解,反射的作用和特点.

java中类加载的全过程及内存图分析

类加载机制: jvm把class文件加载到内存,并对数据进行校验.解析和初始化,最终形成jvm可以直接使用的java类型的过程. (1)加载 将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口. (2)链接 将java类的二进制代码合并到jvm的运行状态之中的过程 2.1 验证 确保加载的类信息符合jvm规范,没有安全方面的问题. 2.2 准备 正式为类变量(static

Java:类加载器(ClassLoader)

听上去很高端,其实一般自定义类加载器不需要用户去实现解析的过程,只要负责实现获取类对应的.class字节流部分就ok了,摘录深入理解Java虚拟机的一段话 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为“类加载器” 实现类加载器需要继承ClassLoader这个抽象类,用户只要实现其中的findClass方法即可.在该类的javadoc中给出了这样一个示