JVM(1)类加载器
JVM位置:
jvm是运行在操作系统之上的;它和硬件没有直接交互;
JVM架构体系:
类加载器 Class loader
负责加载class文件(java -c编译的java文件),class文件在文件开头有特定的文件标示(class文件由开头,作为校验,判断该文件是否合法),将class文件字节码内容加载到内存中,并将这些内容转换成方法区中—运行时数据结构,并且class loader只负责class文件的加载,至于它是否运行,由Executiong engine决定;
类加载器可以想为快递员,把小class文件,加载并初始化成为java.lang.Class(反射的时候得到的该对象,又称为字节码对象)(即进入内存);随后实例化成为jvm堆内存中的对象;
类加载器分类
- 虚拟机自带的类加载器
- 启动类加载器BootstrapClassLoader;C++
- 拓展类加载器ExtensionCLassLoader;Java
- 应用程序类加载器ApplicationClassLoader;(亦称系统类加载器)
- 用户自定义类加载
- java.lang.ClassLoader的子类;用户可以定制的类加载器;
不同类加载对应的作用
public class MyObject {
public static void main(String[] args) throws ClassNotFoundException {
Object o = new Object();
System.out.println(o.getClass().getClassLoader());//null
MyObject myObject = new MyObject();
sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(myObject.getClass().getClassLoader());
}
}
因BootstrapClassLoader为C++语言编写,故此时输出为null;Object这个包载哪儿呢?
1. Object的class文件位于java/jre/lib/rt.jar内,故由上图可知,BootsrapClassLoader加载jvm所需的运行环境
而自己编写的类由ApplicationClassLoader进行加载,输出为sun.misc.Launcher$AppClassLoader@18b4aac2;
那么sun.misc.Launcher是什么呢?查看rt.jar在该路径下sun/misc/Launcher.class,这是一个启动类–入口程序;
那么ExtensionCLassLoader加载什么呢?在java/jre/lib/ext内还有许多jar包,随着java的升级,该类加载器可用于更好的拓展java,故此类加载器是用于加载java/jre/lib/ext内的jar包的;
分析以下输出结果:
public class MyObject {
public static void main(String[] args) throws ClassNotFoundException {
Object o = new Object();
//java.lang.NullPointerException
//System.out.println(o.getClass().getClassLoader().getParent());
MyObject myObject = new MyObject();
sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(myObject.getClass().getClassLoader());
//sun.misc.Launcher$ExtClassLoader@61bbe9ba
System.out.println(myObject.getClass().getClassLoader().getParent());
//null
System.out.println(myObject.getClass().getClassLoader().
getParent().getParent());
}
}
可知类加载器也父子关系:层级如上图所示
双亲委派机制
创建java.lang的package,同时创建String类,
public class String {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println("test");
}
}
运行报错:在java.lang.String中找不到main方法;实际运行的是JDK的String类;同时该段代码能通过编译;
原因解析如下:
在运行自定java.lang.String类时,即ApplicationClassLoader运行,不查找直接向往上,到ExtCLassLoader,不查找,直接找父亲,BootstrapClassLoader,找到了jdk的String类;
双亲委派:当一个类收到了类加载的请求时,它首先不会尝试去处理这个类,而是把这个请求委派给它的父类,每一层的类加载器都是如此,当父类无法完成该请求时(该父类的加载路径下无该类),该子类才会尝试自己加载;
意义:不污染java的源代码,从顶级父类开始查找;(健壮性);