classloader
JVM装载
在说java的ClassLoader机制之前,我先了解下jvm的装载过程和其中的原理。
装载就是寻找一个类或者一个接口的二进制形式并且用二进制形式构造代表这个类或者是这个接口的class对象的过程。
类的生命周期是从被加载到虚拟机内存中开始,到卸载出内存结束。
加载->验证->准备->解析->初始化->使用->卸载
在java中,类装载器把一个类装入java虚拟机中,要经过三个步骤完成:装载、链接和初始化
这是java的装载流程,后面要说下java中,类的表现形式。
在java中,一个类代表着这个类要执行的代码,但是这个类可以有对应的各种不同的实例,不同的实例就是通过类中数据的表示状态来区分。状态是动态的,但是代码则不会。当我们将一个特定的状态和一个类对应起来,也就是意味着将一个类实例化。尽管相同的类呢,对应的实例有各种各样不同的状态,但是其基本底层还都是同一份代码,只是其中的数据状态有不同。jvm一般只加载一次类,以后相同的类就不会再加载。
下面就讲下JVM是如何区分不同的类的:
在Java中,一个类用其完全匹配类名(fully qualified class name)作为标识,这里指的完全匹配类名包括包名和类名。但在JVM中一个类用其全名和一个加载类ClassLoader的实例作为唯一标识。因此,如果一个名为Pg的包中,有一个名为Cl的类,被类加载器KlassLoader的一个实例kl1加载,Cl的实例,即C1.class在JVM中表示为(Cl, Pg, kl1)。这意味着两个类加载器的实例(Cl, Pg, kl1) 和 (Cl, Pg, kl2)是不同的,被它们所加载的类也因此完全不同,互不兼容的。
JVM规范定义了两种类型的类装载器:启动内装载器(bootstrap)和用户自定义装载器(user-defined class loader)。
JVM在运行时会产生三个ClassLoader:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader。Bootstrap是用C++编写的,我们在Java中看不到它,是null,是JVM自带的类装载器,用来装载核心类库,如java.lang.*等。
AppClassLoader的Parent是ExtClassLoader,而ExtClassLoader的Parent为Bootstrap ClassLoader。
package javatest;
public class TestClassLoader{
public static void main(String[] args){
Class cl = null;
ClassLoader cLoader;
cLoader = ClassLoader.getSystemClassLoader();
System.out.println(cLoader);
while(cLoader != null){
cLoader = cLoader.getParent();
System.out.println(cLoader);
}
try{
cl = Class.forName("java.lang.Object");
cLoader = cl.getClassLoader();
System.out.println("java.lang.Object loader is "+cl);
cl = Class.forName("javatest.TestClassLoader");
cLoader = cl.getClassLoader();
System.out.println("LoadTest loader is "+cl);
}catch(Exception e){
e.printStackTrace();
}
}
}
output:
sun.misc.Launcher$AppClassLoader@73d16e93
// 系统的类装载器来自类sun.misc.Launcher$AppClassLoader@73d16e93的实例化,
sun.misc.Launcher$ExtClassLoader@15db9742
// 系统的类装载器的parent来自sun.misc.Launcher$ExtClassLoader@15db9742的实例化
null
//系统的类装载器的爷爷是由上面的Bootstrap ClassLoader实例而来,但是呢,这个Bootstrap ClassLoader是由C++实现的(嘿嘿嘿,混血儿),在java中是看不到滴。
java.lang.Object loader is null
//核心类都是由Bootstrap ClassLoader进行装载滴
LoadTest loader is sun.misc.Launcher$AppClassLoader@73d16e93
//用户自己的类都是由AppClassLoader进行加载滴。
那么问题来了,JAVA为啥需要这么多类加载器(当然是多层负责每层对应的类系统,而且多态这个磨人的妖精很是厉害,需要多层加载机制进行处理。–个人理解)
因为java是动态加载类的,这样的话,用到什么类就加载什么类,不用的就不加载(模仿Linux的内存管理机制!!!也让我想起了C++里面的内存申请,如果申请内存,先不分配实际物理内存,当需要访问的时候,再进行分配内存进行操作)
点击关注阿里云科技快讯,跟多精美礼品等你来拿!
参考:兔子哥哥