深入理解JVM(五)-Java类加载器
来源:互联网 发布:centos系统备份 编辑:程序博客网 时间:2024/05/03 10:22
对于C/C++开发者来说,他们在内存管理方面具有至高的权利,但是也承担着巨大的维护责任。而对于Java程序员来说,有了JVM(Java虚拟机)管理机制的帮助,再也不用担心内存泄漏和内存溢出问题了。因此,这篇文章我将深入探讨一下JVM,它的内部结构以及运行原理。
Java中的类加载器
启动(Bootstrap)类加载器:引导类装入器是用本地代码实现的类装入器,它负责将 < Java_Runtime_Home>/lib 下面的类库加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。注意:启动加载器用C++实现,是虚拟机自身的一部分。
标准扩展(Extension)类加载器:扩展类加载器是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader) 实现的。它负责将 < Java_Runtime_Home >/lib/ext 或者由系统变量 java.ext.dir 指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
系统(System)类加载器:系统类加载器是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器。
自定义的类加载器:
要创建用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定类的名字,返回对应的Class对象的引用。
protected Class< ?> findClass(String name)
throws ClassNotFoundException
参数:
name - 类的二进制名称
返回:
得到的 Class 对象
抛出:
ClassNotFoundException - 如果无法找到类
双亲委派模型
双亲委派的过程:当一个类加载器收到了类加载的请求,它首先不会自己尝试去加载类,而是将这个类委派给父类加载器去加载,这样一层层向上递进,只有在父类加载器都反馈加载不了的时候,子加载器才尝试自己去加载。
使用双亲委派机制的一个好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,另外保证Java中类的加载都使用唯一的类加载器加载,保证内存里只会加载一份system字节码。
Java双亲委派模型对保证Java的稳定运行很重要,但是它的实现却很简单,实现的代码都在 java.lang.ClassLoader 的loadClass()方法中。
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 首先检查请求的类是否已经被加载过 Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // 如果父类加载器抛出ClassNotFoundException // 说明父类加载器无法完成加载请求 } if (c == null) { // 父类加载器无法加载之后 // 调用自身的findClass方法 long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
先检查是否已经被加载过,若没有加载则调用父类的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。若父加载器加载失败,抛出 ClassNotFoundException 异常后,再调用自己的findClass()方法进行加载。
注意:Java双亲委派机制并不是一个强制性的约束模型,而是Java设计者们推荐给大家的类加载器的实现方式。
感谢
如果大家想了解更多,欢迎继续阅读接下来的章节,推荐大家熟读《深入理解Java虚拟机》这本书。
- 深入理解JVM(五)-Java类加载器
- [深入理解JVM 五]---虚拟机类加载机制
- 【深入理解JVM】类加载
- 深入理解JVM-类加载
- 深入理解JVM(四)-Java虚拟机类加载机制
- 深入理解Java虚拟机(五)类加载机制
- 深入理解Java虚拟机——JVM类加载机制(类加载过程和类加载器)
- Java高级篇(四十六)------【深入理解JVM】:类加载器与双亲委派模型
- 【深入理解JVM】:类加载器与双亲委派模型
- 深入理解JVM(十)——类加载器
- 深入理解JVM(十)——类加载器
- 【深入理解JVM】:类加载器与双亲委派模型
- 【深入理解JVM】:类加载机制
- 深入理解JVM类加载过程
- 深入理解jvm — 类加载篇
- 《深入理解JVM》--JVM类加载机制总结
- 深入理解java虚拟机---类加载器
- 深入理解java类加载器ClassLoader
- SpringMVC 基于注解的Controller @RequestMapping @RequestParam..
- VLCKit编译过程中live555报404的问题解决
- gson总结
- USBWriter 使用手册
- 自动化运维工具Ansible详细部署
- 深入理解JVM(五)-Java类加载器
- 前端头部标签汇总
- 趣写算法系列之--匈牙利算法
- JDK 动态代理的简单理解
- js Eventutil内容
- Proxy.php-梧桐雨的遨游内网漫游
- Jenkins的分布式构建及部署——节点
- 图像插值
- 【BZOJ3049】Island Travels,SPFA预处理+状态压缩DP