深入了解Java之类加载和案例分析
新的一天,祝愿大家开心愉快!
本片讲解了JVM内存区域分析以及ava程序执行的过程。来自于简书作者为的第二篇投稿。通过这篇文章对JVM内存和Java虚拟机类加载机制的分析。希望大家JVM能进一步的了解。
来自简书博客地址:
在讨论JVM内存区域分析之前,先来看一下Java程序具体执行的过程:
Java程序执行过程
Java 程序的执行过程:Java 源代码文件(.Java文件)-> Java Compiler(Java编译器)->Java 字节码文件(.class文件)->类加载器(Class Loader)->Runtime Data Area(运行时数据)-> Execution Engine(执行引擎)。上篇文章已经分析了 Runtime Data Area(运行时数据) 这一块,那我们今天就来分析一下Java程序执行过程的 类加载器(Class Loader) 这一块
一、类加载器(ClassLoader)
把Java类的数据从Class文件加载到虚拟机内存中,然后对这部分数据进行验证、准备、解析、初始化,最终形成可以被虚拟机直接使用的Java类型。
学习这个有什么好处呢?
1、有助于了解Java虚拟机的执行过程
2、程序能动态的控制类加载,比如热部署、热修复等
类加载器(ClassLoader)的一些方法:
方法 | 说明 |
---|---|
getParent() | 返回该类加载器的父类加载器 |
loadClass(String name) | 加载名称为 name的类 |
findClass(String name) | 查找名称为 name的类 |
findLoadedClass(String name) | 查找名称为 name的已经被加载过的类 |
defineClass(String name, byte[] b, int off, int len) | 把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为 final的 |
二、类加载的分类
Bootstrap Loader(启动类加载器) :是用C++语言写的,是虚拟机自身的一部分,主要负责加载Java的核心类;
Extended Loader(扩展类加载器) :Extended Loader的父加载器为 Bootstrap Loader,该加载器使用Java写的,它用来加载Java的扩展库;
AppClass Loader(系统类加载器):AppClass Loader的父加载器为 Extended Loader,该加载器使用Java写的,它用来加载Java应用的类路径(CLASSPATH)上的类库。
三、类加载过程
寻找jre目录,寻找jvm.dll,并初始化JVM,JVM启动后,运行Bootstrap Loader,该Bootstrap Loader(启动类加载器)自动加载Extended Loader(扩展类加载器)和AppClass Loader(系统类加载器),最后AppClass Loader加载CLASSPATH目录下定义的Class。
四、双亲委派模型
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
代码实现:
"双亲委派模型"有什么作用呢?
1、这样保证了每个类都只会加载一次
2、维护系统自身类的安全
五、类加载的三种方式
1、通过JVM初始化加载
2、通过Class.forName()方法动态加载
3、通过ClassLoader.loadClass()方法动态加载
六、案例分析
基于上篇文章的"深入了解Java之虚拟机内存"和这篇"深入了解Java之类加载"的理论知识,我们用这个例子简单的来了解一下类的加载和内存分配的一些逻辑:
过程分析
public class TestMain
通过JVM初始化加载;通过Class.forName()方法动态加载;通过ClassLoader.loadClass()方法动态加载通过以上方法加载这个类的时候,会从Bootstrap Loader(启动类加载器),Extended Loader(扩展类加载器)从上往下加载,发现都加载不了,最后由AppClass Loader从CLASSPATH中找到加载TestMain这个类,读取这个文件中的二进制数据,接着对这部分数据进行验证、准备、解析、初始化,最后会把这个类的类信息、常量、静态变量、以及编译器编译后的代码等存入运行时数据区中的方法区。
public void TestMethod()
TestMethod 也被放入方法区。
Sample testSample = new Sample(" test ");
先看"="右边的:“new Sample(" test ")”也是一个类跟上面一样,加载这个类的相关信息到方法区中,然后就是就是要在运行时数据区中的堆进行分配内存,方法区的类信息和堆怎么对应呢?其实堆只是存放了这个Sample实例的一个指向方法区的引用地址testSample,他主要是存放在运行时数据的Java虚拟机栈的栈帧中的局部变量表中"="其实不是赋值,而是testSample这个变量指向了堆中的Sample实例
testSample.getName();
testSample指向了堆中Sample的实例,然后根据这个实例持有的引用拿到了方法区这个类的相关信息,其中的一个方法getName();接着执行这个方法打印数据
几个不错的java虚拟机类加载的学习地址:
Java虚拟机类加载机制
Java虚拟机类加载机制——案例分析
类加载及执行子系统的案例与实战
深入了解Java之垃圾回收
Hello,伙伴们
长按二维码就可以关注我们啦!