在类生命周期里面分析过,类首先要被加载,形成一个Class实例,然后进行动态连接,然后进行初始化、实例化等,最后在类型不可触及时,被卸载收集。然而类是被什么加载到JVM内存里的呢?当然是类加载器。下面,详细分析下类加载器。
文章参考:
http://weiwu83.iteye.com/blog/141207 (这位同学排版且整理的比较乱,我重新整理下)
超好的资料:
http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html
类加载器种类
类加载器包括JVM自带的加载器和自定义加载器。首先,看看JVM自带的加载器种类及作用范围:
1.
启动类加载器(Bootstrap):加载JVM的类加载器,它是采用本地代码实现的,如C/C++等。它涉及到了具体JVM的本地实现细节,所以,开发者无法获得该加载器的引用。它负责将%JAVA_HOME%/lib目录下的类库加载到内存中;
2.
标准扩展类加载器(Extension):开发者可以使用这种类型的加载器来加载类。它负责将%JAVA_HOME%/lib/ext或由系统变量 java.ext.dir 指定位置中的类库加载到内存中
3.
系统类加载器(System):开发者可以使用这种类型的加载器来加载类。它负责将CLASSPATH指定的路径中的类库加载到内存中
4.
用户自定义的类加载器:
具体的扩展以及系统类加载器继承结构图,看参考文章。
类的加载机制
JVM在加载类 时默认采用的是双亲委派机制。通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
为了更好的理解类的加载机制,我们先来看看类加载器中几个重要的方法:
loadClass()方法:加载器的总调度方法。它会根据加载器双亲委派机制来选择适当的加载器加载出指定类名称的Class实例
findClass()方法:读取class文件形成一个字节数组,然后将该字节数组传递给 defineClass方法,试着导入这个类型,返回一个Class实例
defineClass方法:根据传入的资源,调用本地方法进行具体的类的加载过程。加载成功会返回一个Class实例
为了对这些方法有个大概的了解,现对JDK中自带的加载器类中的一些方法进行分析。首先,我们看看
ClassLoader类中的
findClass()的源码:
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
//首先验证这个类型是否已经被加载了
Class c = findLoadedClass(name);
if (c == null) { //如果还没被加载,则调用父加载器或启动类加载器类进行类加载
try {
if (parent != null) {
//如果存在父类加载器,就委派给父类加载器加载
c = parent.loadClass(name, false);
} else {
//如果不存在父类加载器,就检查是否是由启动类加载器加载的类,通过调用本地方
//native Class findBootstrapClass(String name)
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then invoke findClass in order
// to find the class.
// 如 果父类加载器和启动类加载器都不能完成加载任务,才调用自身的加载功能
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
ClassLoader类中没有findClass方法的具体实现,但我们可以打开URLClassLoader类的源码,看看它的findClass具体实现:
protected Class<?> findClass(final String name)
throws ClassNotFoundException
{
try {
return (Class)
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
//根据完整类名,读取Class文件内容
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
//根据已读出的文件内容进行具体类型加载
return defineClass(name, res);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
} else {
throw new ClassNotFoundException(name);
}
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (ClassNotFoundException) pae.getException();
}
}
注意:本人写这文章的目的是为了加深了解以及为以后面试复习时用的,所以看起来不怎么详细。为了使感兴趣的朋友更加了解类加载器,我附上一份完整的资料,供大家参考
上面主要描述了类加载器的种类以及加载的规则,下章将分析下类加载器的特征以及程序的动态扩展
分享到:
相关推荐
总之,Java的类加载器父亲委托机制是一种设计精巧、安全可靠的类加载策略,它保证了JVM运行环境的稳定,同时也为开发者提供了灵活的扩展性。理解并掌握这一机制对于深入理解Java应用程序的运行机制至关重要。
【JVM】类的奇幻漂流——类加载机制探秘 Java虚拟机(JVM)是运行Java程序的核心组件,它负责将我们编写的类加载到内存中并执行。类加载机制是JVM的一个重要组成部分,它确保了程序的正常运行。本文将带你深入理解...
传统的Java应用程序在启动时,由JVM(Java虚拟机)通过类加载器将类加载到内存中,一旦加载完成,除非程序退出,否则这些类通常不会被重新加载。然而,在开发过程中,我们可能希望在不重启应用的情况下,对已加载的...
【深入Java虚拟机(二)——类的生命周期(上)类的加载和连接】 Java虚拟机(JVM)是Java程序的核心,它负责解释和执行Java字节码。类的生命周期在JVM中是一个关键的概念,它涵盖了从类的加载到卸载的整个过程。...
1. **Bootstrap ClassLoader**:这是JVM启动时的第一个类加载器,负责加载JDK核心库(rt.jar)中的类。 2. **Extension ClassLoader**:加载JRE扩展目录(java.ext.dirs)下的JAR文件。 3. **System ClassLoader**...
本教程——“深入JVM内核—原理、诊断与优化视频教程”,将重点讲解这些关键点,帮助开发者提升技术水平,更好地解决实际问题。 首先,我们来探讨JVM的内核原理。JVM主要由类加载子系统、运行时数据区、执行引擎、...
- **加载**:这是类加载的第一步,JVM会通过类加载器找到.class文件,并将其二进制数据读入内存。这些数据会被存储在方法区,这是一个用于存储已加载类元数据的区域。同时,在堆区创建一个`java.lang.Class`对象,...
《实战Java虚拟机——JVM故障诊断与性能优化》是一本深入探讨Java开发中的关键环节——Java虚拟机(JVM)的专著。本书聚焦于实际应用中的问题解决和性能调优,对于Java开发者和系统管理员来说,是提升技术水平的重要...
《Java实现的JVM——深入理解与实践》 在计算机科学领域,Java虚拟机(JVM)是Java语言的关键组成部分,它使得Java程序能够在不同平台上运行而无需重新编译。本项目“jvmjava”是一个开源项目,由Java语言实现,...
总之,在Java开发过程中,深入了解JVM的类加载机制以及相关的类加载器类型对于提高代码质量、优化程序性能具有重要意义。同时,掌握深拷贝与浅拷贝的概念有助于更好地管理对象间的引用关系,避免不必要的错误和内存...
双亲委派模型是JVM中类加载器之间的关系,每个类加载器都有一个父加载器,除了启动类加载器外,其他类加载器都有自己的父类加载器。当某个特定的类加载器接收到加载请求时,首先将加载任务委托给父类加载器,只有...
在深入理解Java虚拟机(JVM)如何加载Class文件之前,我们需要明确一点:Java的所有类都需要通过类加载器加载到JVM中才能被执行。这个过程对开发者来说通常是透明的,但在一些特殊情况下,例如使用反射时,了解类加载...
《深入JVM内核——原理、诊断与优化》是一份深度探讨Java虚拟机核心机制、问题诊断和性能优化的专业资料。这份资料涵盖了JVM的各个方面,对于Java开发者来说,理解和掌握这些知识至关重要。 首先,我们要了解JVM...
而JVM代理(JVM Agent)和类加载器(ClassLoader)则是两个关键的概念,它们对于深入理解Java应用程序的运行机制至关重要。 **JVM代理** JVM代理是一种在JVM启动时或者运行时插入额外功能的方式,它允许开发者在不...
本节介绍了一种特殊的类加载器——编译时类加载器。这类加载器能够在加载类之前自动编译源代码。这对于动态语言或需要即时编译的场景非常有用,比如当开发者希望在运行时修改某些行为而不需要重新编译整个项目时。 ...
此外,还有一个特殊类型的类加载器——线程上下文类加载器,稍后会单独讨论。 类加载器之间遵循双亲委派机制。这意味着当一个类加载器收到加载类的请求时,它会先委托给其父类加载器尝试加载。只有当父类加载器无法...
3. **应用程序类加载器**(Application ClassLoader):最常用的一种,负责加载用户类路径(ClassPath)中的类。 **2.5 双亲委派模型** 双亲委派模型是指类加载器在加载类之前,先委托给父类加载器尝试加载,如果...
Java类加载器是Java虚拟机(JVM)的核心组件之一,它负责将Java类加载到JVM中以供运行。Java类是Java类型系统的构建块,但它们还有一个基本目的:类是一个编译单元,是可以在JVM进程中单独加载和运行的最小代码单元...
### JVM之走进类加载 #### 一、Java及JVM简介 Java自1995年由Sun Microsystems发布以来,便迅速成为了最受欢迎的编程语言之一。根据TIOBE语言热度排行榜,Java持续保持在前列,这证明了其在编程领域的持久影响力。...
总的来说,理解和掌握Class文件结构、JVM的工作原理以及类加载器的功能对于Java开发者,尤其是系统架构师和性能调优专家而言,是必不可少的知识。通过深入学习这些内容,我们可以更好地理解Java程序的运行机制,从而...