首页 > 编程知识 正文

java的三大体系,api网关和nginx区别

时间:2023-05-03 05:11:41 阅读:32601 作者:881

什么是班级加载机制? java虚拟机将编译的class文件加载到内存中,进行验证、转换、分析和初始化,最终使用。 这就是java类的加载机制;

1、类加载生命周期类加载生命周期主要有加载(Loading )、验证(Verification )、准备(Preparation )、分析(Resolution )、初始化(initial )

2、类加载的定时类加载的生命周期中,决定了加载、验证、准备、初始化、卸载五个阶段的顺序,加载过程一定按照这个顺序执行。 分析阶段有点特殊,在特定情况下在初始化后开始。

那么,在什么情况下需要开始类加载的第一阶段? 相反,Java虚拟机规范没有强制约束,而是交给虚拟机的具体实现自由掌握。 但是,在初始化阶段,虚拟机规范中只有五种情况需要立即“初始化”类,加载、验证和准备当然需要在此之前开始。 1 )有严格的规定,遇到4字节代码指令:新建、获取静态、putstatic或invoke静态。

2 )使用java.lang.reflect包中的方法反射调用类时。

3 )初始化类时,如果发现父类尚未初始化,必须首先触发该父类的初始化。

4 )虚拟机启动时,用户必须指定要运行的主类。 虚拟机首先初始化此主类。

5 )、使用JDK1.7动态语言支持时一个

是java.lang.invoke.MethodHandle实例的最后一个分析结果REF_getStatic、REF_putStatic和REF_invokeStatic的方法句柄,并且与此句柄相对

3、类加载过程接下来详细介绍类加载的几个重要阶段:加载、验证、准备、分析和初始化

3.1、加载

在加载阶段,虚拟机主要执行以下三项操作

1 )通过类的完全限定名获取定义该类的二进制字节流。

2 )将该字节流所代表的静态存储结构转换为方法区域的运行时数据结构。

3 )作为访问方法区域这一类的各种数据的入口,在存储器中生成表示该类的Class对象。

这个阶段与其他阶段相比,是开发者可控性最强的阶段。 因为在这个阶段,您可以使用系统提供的加载程序(下面将对此加载程序进行介绍)进行加载,也可以使用开发人员定制的加载程序进行加载。

在加载的这个阶段还有一点需要注意。 执行第一个操作时,需要知道可以从何处获取以下class文件:

1 )从压缩文件读取(JAR、WAR等) ) ) ) ) ) )。

2 )从本地磁盘获取

3 )、从网上获取(小程序) ) )。

4 )运行时动态生成) )动态代理) ) ) ) ) )。

5 )、其他文件生成(与jsp生成对应的class文件) )。

6 )、从数据库读取

3.2、验证

验证阶段主要有四个阶段的验证。 文件格式验证、元数据验证、字节码验证和元件验证

3.2.1、文件格式验证

在此阶段,请确保字节流符合Class文件格式规范,并且可以在当前版本的虚拟机(如魔数、版本号和常量池)中进行处理。

3.2.2、元数据验证

在此阶段,您将对字节码中的信息进行语义分析,以确保所编写的信息满足java语言规范的要求。 主要包括是否有父类、类中的字段、方法是否与父类冲突、如果不是抽象类,是否在该父类或接口中实现了请求实现的所有方法等。

3.2.3、字节码验证

该阶段在元数据验证后,对类的方法主体进行验证分析,以避免验证类的方法在运行时引发危害虚拟机的安全事件,主要目的是通过数据流和控制流分析,实现程序语义也是验证过程最复杂的阶段。

3.2.4、符号引用验证

此阶段的验证在虚拟机将符号引用直接转换为引用时发生。 就是对类本身以外的信息进行一致性检查。 主要目的是确保分析动作正常执行。

3.3、准备

准备阶段是为类变量分配内存并设置类变量初始值的阶段,这些内存的分配在方法区域内进行。 在这一阶段,需要重点说明两点。

1 )、只有类变量(用static限定的变量)分配内存,不包含实例变量。 实例变量在对象实例化时为堆分配内存。

2 )设置类变量的初始值不是代码中设置的默认值,而是与数量类型相对应的默认值。 例如,自变量number准备阶段以来的初始值(如公共静态int number=111 )为0,而不是111。 为number分配111是在初始化阶段。

基本数据类型的默认值如下:

3.4、分析

分析阶段是虚拟机将常量池中的符号引用直接转换为引用。 请注意两个概念:

1 )、参考符号)用一组符号描述所有参考对象。 符号可以是任何形式的字面量,只要使用时能正确定义到目标即可。

2 )直

接引用:可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符等7类符号引用进行的。

3.5、初始化

这个阶段是类加载过程的最后一步,是代码真正开始执行的时候,在这个阶段,开发人员可以根据自己的需求去给类变量初始化赋值。简单来说就是执行类构造器()方法的过程。

4、类加载器

接下来看看是什么是类加载器:

虚拟机设计团队将加载动作放到了Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称之为“类加载器”。

4.1、系统提供的3种类加载器

1)、启动类加载器(Bootstrap ClassLoader):负责将存放在<JAVA_HOME>lib目录中,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。(注:仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)

2)、扩展类加载器(Extension ClassLoader):负责加载<JAVA_HOME>libext目录中的,或被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。

3)、应用程序类加载器(Application ClassLoader):负责加载用户路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,一般情况下该类加载是程序中默认的类加载器。

这三种加载器的加载顺序如下:

4.2、双亲委派模型

如上图展示的类加载器之间的这种层次关系就是双亲委派模型。双亲委派模型要求除了顶层的启动类加载器外,其他的类加载器都应有自己的父类加载器。

双亲委派原则的好处:

1)、避免重复加载同一个类;

2)、防止用户任意修改java中的类;

双亲委派:如果一个类加载器收到类加载的请求,他首先不会自己去尝试加载这个类,而是把请求委派给父类加载器去完成,每一层次的类加载器都是这样,因此所有的加载请求最终都应该传送到底层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试去加载。

如下图所示:

4.3、自定义类加载器

上面讲述的是系统提供的类加载器以及它们之间的关系,还有很多情况需要我们自定义类加载器。那该如何定义呢?有以下两种方式

1、如果我们自定义的加载器不想破坏双亲委派,继承 java.lang.ClassLoader 类并重写 findClass 方法。

2、如果使用我们自定义的加载器破坏双亲委派,继承 ava.lang.ClassLoader 类并重写loadClass(java.lang.String) 方法。

该文章转载自微信公众号:程序猿分享编程

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。