黑马程序员--05.类加载器--02【抽象类ClassLoader】【JVM加载类的过程】

来源:互联网 发布:crm软件的使用方法 编辑:程序博客网 时间:2024/04/27 04:34

类加载器--2

抽象类ClassLoader           JVM加载类的过程

----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------

说明:这篇日志涉及到的东西我开始也有很多不同的知识。但是幸运的是,我查阅了相关的资料,将难点基本弄清楚了。在这里通过对自己学到的知识和理解,整理出下面这篇日志。不足的地方请大家多多指教!

引用文献1篇:

(1). 《深入理解Java虚拟机:JVM高级特性和最佳实践》 作者:周志明

1.    java.lang.ClassLoader抽象类

1). 抽象类ClassLoader基本知识

(1). ClassLoader抽象类的含义

[1]. ClassLoader是负责加载类的类

{1}. 给定一个类名,一个ClassLoader总是尝试确定这个类的位置或者生成可以构成这个类的定义的数据

{2}. {1}的典型实现方法

{2}1. ClassLoader实例给定的类名转换为字节码文件名

{2}2. ClassLoader实例本地文件系统读取相应转换字节码文件

(2). ClassLoader的源码声明

public abstract class ClassLoader {…}

ClassLoader类抽象类

(3). ClassLoader类的位置

ClassLoader类位于java.lang包

(4). 抽象类ClassLoader的抽象方法

ClassLoader的源码可知,ClassLoader类中没有任何抽象方法是一个不含有抽象方法的抽象类

(2). ClassLoader的常用方法

(1). 将byte[]数组中的数据转化为Class类的实例 -----定义字节码对象

[1]. 源码声明

protected final Class<?> defineClass(Stringname, byte[] b,int off, int len)

注意】Java代码中的一个类被使用之前,一定要被正确解析

[2]. 返回值类型Class类型实例 Class<?>

【分析】由于返回的任意类型的Class对象,所以加上了通配符?作为类型变量的真实类型。

[3]. 参数类型

{1}. String name:以字符串形式指定的要加载的类名

{2}. byte[] b + int off +int len:字节数组b中从位置offoff +len -1数据用来构建内存类的数据

注意字节数组b中的通过offlen这两个参数指定的数据段的格式必须符合JVMclass文件的规范

Class文件广义理解Class文件未必指的是硬盘的某个文件广义Class文件指的是一串二进制的字节 (byte)流。

所以这里defineClass方法参数byte[] b中数据构成了内存中类数据的来源

注意】这个方法java.lang.ClassLoader除了被重载的形式调用之外,没有其他的方法对defineClass进行过调用

(2). 对String形式指定的类名进行加载 -----loadClass(String name)

[1]. 源码声明

public Class<?> loadClass(String name);

注意】这个loadClass方法是public的。这个方法实际上是对重载形式loadClass(String, boolean)的封装。

[2]. 返回值类型Class类型实例 Class<?>

[3]. loadClass()调用者(API)

这个方法是JVM进行调用的,不是被Java中的代码进行调用

(3). 对String形式指定的类名进行加载 ----- loadClass重载形式

[1]. 源码声明

protected Class<?> loadClass(String name,boolean resolve);

注意】这个loadClass方法是protected的。这个方法实际是被重载形式loadClass(String)进行调用的。

注意】这个方法实际上就是JVM内部对“类加载器双亲委托机制的代码表现”****

[2]. 返回值类型Class类型实例 Class<?>

[3]. 后面详细阐述这个方法的源码。

(4). 寻找指定以String形式出现的类名对应的Class类对象

[1]. 源码声明

protected Class<?> findClass(String name);

注意】findClass()方法是protected的。

[2]. 回值类型Class类型实例 Class<?>

[3]. API重要说明

{1}. API已经着重强调:这个findClass()方法应该遵循“类加载器双亲委派模型”的抽象类ClassLoader的实现子类进行覆盖/重写

{2}. findClass()方法调用者就是访问权限是protectedloadClass()方法

2.    JVM加载类的过程

【主要参考】

{1}. 周志明老师的《深入理解Java虚拟机:JVM高级特性和最佳实践》

并进行了整理和组合

1). JVM进行类加载的基本知识

(1). JVM的类加载机制

[1]. 广义Class文件Class文件未必指的是硬盘的某个文件广义Class文件指的是一串二进制的字节 (byte)

[2]. JVM描述类的数据Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被JVM直接使用的Java。这就是JVM的类加载机制

(2). Java中的类的生命周期 (简介)

[1]. Java其他语言的一个不同点

{1}. 以C、C++为例,这些语言在编译的时候就要进行连接工作的。

{2}. 在Java类型的加载连接都是在程序运行期间完成的。

[2]. 运行时进行类型的加载和连接优缺点:

{1}. 缺点增加类加载的开销

{2}. 优点Java语言动态语言的特性依赖于这个运行期间的动态加载和动态链接

举例】一个使用接口的应用程序可以等到运行时再获取对应的实际实现

[3]. Java中的生命周期


【简单通过图了解一下即可 为类加载做铺垫

2). JVM进行类加载 (Class Loading) 全过程

类加载全过程

就是类在内存中的生命周期前五步:加载、验证、准备、解析初始化

(1). 加载 (Loading) 阶段*** -----对理解自定义类加载器很重要

[1]. JVM在加载阶段要做三件事(属于JVM的规范)

{1}. 通过全类名获取定义此类的二进制字节 (byte)

{2}. 将这个字节流代表的静态存储结构转化方法区的运行时数据结构

(知道就好 不用深入)

{3}. 在Java中生成一个表达这个类的java.lang.Class类对象,作为{2}中在方法区的数据的访问入口

[2]. 加载阶段的灵活性

注意】第一条JVM规范“通过全类名获取定义此类的二进制字节 (byte) 并不具体。也就是没有指明从哪里怎样获取二进制字节 (byte) ,这样就导致许多新技术的出现

[3]. 由于加载阶段灵活性出现的新技术举例

{1}. zip包中读取,最终成为日后JAR、EAR和WAR格式的基础。【从哪里获取

{2}. 从网络中获取,此场景的典型应用是Applet。【从哪里获取

{3}. 运行时通过计算进行获取,此场景的典型应用动态代理技术。【怎样获取

java.lang.reflect.Proxy中,就是使用ProxyGenerator.generateProxyClass来为特定接口生成*$Proxy的代理类二进制字节流

{4}. 由其他文件生成,典型应用场景是JSP。【从哪里获取

[4]. 类加载 (class loading) 的加载阶段(loading)启示意义

{1}. 相对于类加载过程的其他四个阶段加载阶段准确地说是加载阶段获取二进制流的动作)开发期间可控性最强的阶段

{2}. 这是因为加载阶段既可以通过系统提供的类加载器来完成也可以通过自定义类加载器来完成

{3}. 而此时可以通过自定义的类加载器控制加载阶段的“字节流获取的具体动作”

注意】除了在加载阶段用户的应用程序可以通过自定义的类加载器参与进来之外其余的四个阶段(验证阶段、准备阶段、解析阶段和初始化阶段)完全由JVM主导控制用户的应用程序无法参与!!!!

结论】如果想在类加载的全过程让自己的应用程序发挥作用的话,只能选择加载阶段通过自定义类加载器下手

(2). 验证 (Verification) 阶段

目的】是连接阶段( linking )第一步骤,为了确保Class文件的字节流含有的信息符合当前JVM的要求并且不会危害JVM自身的安全

(3). 准备 (Preparing) 阶段

[1]. JVM在准备阶段所做的动作

正式为类变量(静态变量)分配内存为类变量设置初始值阶段

[2]. 准备阶段分配内存具体位置.

由于全部是静态的东西,所以分配内存全部在方法区中进行

[3]. 准备阶段的为类变量设置初始值具体指成员变量的隐式初始化

(4). 解析 (Resolving) 阶段

[1]. JVM在解析阶段所做的动作

JVM常量池中的符号引用替换为直接引用的过程。

[2].【解释】说白了就是一个翻译的过程

Class文件中的字面常量哪些底层的JVM指令进行匹配的过程

(5). 初始化 (Initialization)阶段

[1]. JVM在初始化阶段所做的动作

开始真正执行Java程序定义的代码或者说是字节码

[2]. 初始化阶段JVM也要为成员变量进行显示初始化赋值

准备阶段的隐式初始化赋值不同初始化阶段对成员变量进行的是显示初始化

----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------

原创粉丝点击