查看原文
其他

深入了解Java之类加载和案例分析

2017-03-16 白痴狒狒 终端研发部



前言介绍

新的一天,祝愿大家开心愉快!

本片讲解了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之垃圾回收



如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809 微信公众号:终端研发部



            

Hello,伙伴们

长按二维码就可以关注我们啦!



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存