JVM的虚拟机类加载机制

首先,我们要知道为什么会存在类的加载机制。Java语言编写的.java在经过编译器编译后会生成.class文件,这个和C\C++语言是不一样的。

C语言它们是会被编译生成为本地机器码,然后在被执行。这种做法的缺点就是无法完成编写代码的跨平台使用。想想就知道,windows下编译好的代码在linux就不能运行是有多郁闷啊。

Java就不一样,它做到了一次编译,到处运行。为什么它可以呢?因为Java是将编译好的class文件是放在Java虚拟机中执行的。windows下就放在windows环境中的Java虚拟机中执行,所以它是不受平台的影响的。

那么,怎么将class文件放入JVM中运行。这就需要类的加载机制。还有一点大家要知道,一个class文件对应的就是你用Java编写的一个类。所以我们将完成class文件的加载的过程称为虚拟机类的加载机制。

-------------------------------------------------------8------------------------------------------------------------------------

Java中,类的加载、连接和初始化都是在程序的运行期间完成的。Java是天生的可动态扩展的语言,主要就是依赖运行期间动态的加载和动态的连接来完成的。下面给出一张Java中类的生命周期图:


由上图我们就知道了原来一个类的生命周期是这样的。只有我们让虚拟机加载某个类,我们才能在程序中使用这个类。那么虚拟机是什么时机加载一个类呢?这个是由虚拟机自己决定的。

接下来说说类的加载器。

JVM在类的加载阶段,通过一个类的全限定名来获取磁盘中描述此类的二进制字节流,这个动作是发生在Java虚拟机的外部实现的,而这个动作的实现所需要的代码模块被称为“类的加载器”。这是官方给的定义,原来类的加载器就是一段可以完成读取二进制字节流的代码块。

类的加载器只能用于实现类的加载动作。每一个类加载器都有一个独立的类名称空间。

下面来重点介绍类的加载器的种类。

JVM中只存在两种不同的类的加载器:

1、启动类加载器(Bootstrap ClassLoader)。这个类是使用C++语言编写的,是属于虚拟机内部的一部分。

2、其他的类加载器:这些类的加载器是使用Java语言实现的。包括:扩展类加载器、应用程序类加载器、自定义类加载器。它们是独立于虚拟机之外的,并且全部都是继承自抽象类java.lang.ClassLoader

JVM的类加载器中存在这一个叫做双亲委派模型。什么意思呢?先看一下这种模型的结构:


这个模型是自下向上的,除了启动类加载器之外,所有的类加载器均有父类的加载器。比如自定义加载器1的父类加载器是应用程序加载器。

那为什么要这样做?

这里我大概的介绍一下,当一个类加载器接收到加载某个类的请求时,首先它是不会加载的。它会上传给父类加载器去加载。直到上传至启动类加载器时为止,如果启动类加载器完成请求时,在向下给它的子类加载器去加载。直到最后会有子类加载器来加载这个类。

这么做又有什么好处呢?

这样做会是一些类具有了优先级。你想想假如现在某个类要请求加载System类时,无论是哪个类请求的。最后都是由启动类加载器加载Java.lang.System这个类。不管在什么情况下,加载的都会是这个类。但是如果不使用双亲委派模型,这时候不同的用户都自定义一个System的类。那么在执行System类请求时,JVM的类加载器就会出现加载混乱。从而最终导致程序运行出错。


猜你喜欢

转载自blog.csdn.net/LULEI1217/article/details/50954246