一、什么是类加载器?
- 与普通程序不同的是Java程序class文件并不是本地的可执行程序。
- 当运行Java程序时首先运行JVM
- 然后再把Java class加载到JVM里头运行
- 负责加载Java class的这部分就叫做Class Loader。
- 动态的类加载是JVM的一个重要特征,它为Java平台提供了在运行时间安装软件组件的能力。
- JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader
- 和JVM一样BootstrapClassLoader是用本地代码实现的
- 它负责加载核心JavaClass即所有java.*开头的类
- 另外JVM还会提供两个ClassLoader它们都是用Java语言编写的,由BootstrapClassLoader加载
- Extension ClassLoader负责加载扩展的Javaclass例如所有javax.*开头的类和存放在JRE的ext目录下的类
- ApplicationClassLoader负责加载应用程序自身的类。
- java虚拟机中的所有类加载器采用具有父子关系的树形结构进行组织
- 在实例化每个类加载器对象时
- 需要为其指定一个父级类加载器对象或默认采用系统类加载器为其父级类加载器
二、加载流程
- 当运行一个程序的时候JVM启动运行bootstrapclassloader
- 该ClassLoader加载java核心API,ExtClassLoader和AppClassLoader也在此时由jvm创建
- 然后调用ExtClassLoader加载扩展API
- 最后AppClassLoader加载CLASSPATH目录下定义的Class
三、类加载器体系
四、类加载器的委托机制
- 每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类加载器去加载类,这就是类加载器的委托模式
- 委托机制可以保证内存中只有一份相应类的字节码
- 当java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
- 首先,当前线程的类加载器去加载线程中的第一个类
- 如果类A中引用了类B,java虚拟机将实用加载类A的类加载器加载类B
- 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类
- 每个类加载器加载类时,又先委托给其上级类加载器
- 当所有祖宗类加载器没有加载到类,回到发起者类加载器
- 还加载不了,则抛出ClassNotFoundException,而不是再去找发起者类加载器的儿子
- 因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
五、简单示例
public class ClassLoaderTest {
public static void main(String[] args){
String name = ClassLoaderTest.class.getClassLoader().getClass().getName();
System.out.println(name);
System.out.println(System.class.getClassLoader());//null就是说是由BootStrap加载的
ClassLoader loader = ClassLoaderTest.class.getClassLoader();
while(loader != null)
{
System.out.println(loader.getClass().getName());
loader = loader.getParent();
}
System.out.println(loader);
}
}
结果是:
sun.misc.Launcher$AppClassLoader
null
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
null
六、java.lang.ClassLoader类
/**
* 类加载器是负责加载类的对象
* ClassLoader 类是一个抽象类
* 如果给定类的二进制名称,那么类加载器会试图查找或生成构成类定义的数据。
* 一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。
* 数组类的 Class 对象不是由类加载器创建的,而是由 Java 运行时根据需要自动创建
* 数组类的类加载器由 Class.getClassLoader() 返回,该加载器与其元素类型的类加载器是相同的
* 如果该元素类型是基本类型,则该数组类没有类加载器。
*/
public abstract class ClassLoader
{
//使用方法 getSystemClassLoader() 返回的 ClassLoader 创建一个新的类加载器,将该加载器作为父类加载器
protected ClassLoader(){}
//使用指定的、用于委托操作的父类加载器创建新的类加载器
protected ClassLoader(ClassLoader parent){}
***********************************************
//返回委托的系统类加载器。该加载器是新的 ClassLoader 实例的默认委托父类加载器,通常是用来启动应用程序的类加载器
public static ClassLoader getSystemClassLoader(){}
/**
* 使用指定的二进制名称查找类
* 此方法应该被类加载器的实现重写,该实现按照委托模型来加载类。
* 在通过父类加载器检查所请求的类后,此方法将被 loadClass 方法调用
*/
protected Class<?> findClass(String name)
throws ClassNotFoundException{}
/**
* 使用指定的二进制名称来加载类。此方法的默认实现将按以下顺序搜索类:
* 调用 findLoadedClass(String) 来检查是否已经加载类。
* 在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。
* 调用 findClass(String) 方法查找类。
* 如果使用上述步骤找到类,并且 resolve 标志为真,则此方法将在得到的 Class 对象上调用 resolveClass(Class) 方法。
* 鼓励用 ClassLoader 的子类重写 findClass(String),而不是使用此方法。
*/
protected Class<?> loadClass(String name,
boolean resolve)
throws ClassNotFoundException{}
//调用此方法等效于调用 loadClass(name, false)
public Class<?> loadClass(String name)
throws ClassNotFoundException{}
//将一个 byte 数组转换为 Class 类的实例。必须分析 Class,然后才能使用它
protected final Class<?> defineClass(String name,
byte[] b,
int off,
int len)
throws ClassFormatError{}
//返回委托的父类加载器。
public final ClassLoader getParent(){}
//返回读取指定资源的输入流
public InputStream getResourceAsStream(String name){}
}
七、自定义类加载器
package day27;
import java.util.Date;
public class Demo extends Date{
public String toString()
{
return "你好吗";
}
}
package day27;
import java.io.*;
//自定义的类加载器,有加密功能
public class MyClassLoader extends ClassLoader{
public static void main(String[] args)throws Exception {
String srcFileName = args[0];
System.out.println(srcFileName);
InputStream is = new FileInputStream(srcFileName);
String destFileName = args[1] + srcFileName.substring(srcFileName.lastIndexOf("\\"));
OutputStream os = new FileOutputStream(destFileName);
cypher(is,os);
is.close();
os.close();
}
/**
* 加密
* @param is 输入流
* @param os 输出流
* @throws Exception
*/
private static void cypher(InputStream is,OutputStream os) throws Exception{
int b;
while((b=is.read())!=-1)
{
os.write(b ^ 0xff);
}
}
private String dir;
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classFileName = dir + "\\" + name.substring(name.lastIndexOf(".")+1) + ".class";
try {
FileInputStream fis = new FileInputStream(classFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cypher(fis,bos);
fis.close();
bos.close();
byte[] bytes = bos.toByteArray();
System.out.println("my ClassLoader");
return defineClass(bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name);
}
public MyClassLoader(){
}
public MyClassLoader(String dir){
this.dir = dir;
}
}
package day27;
import java.util.Date;
public class ClassLoaderTest {
public static void main(String[] args) throws Exception{
MyClassLoader loader = new MyClassLoader("mylib");
Date d = (Date) loader.loadClass("day27.Demo").newInstance();
System.out.println(d);
}
}
- 大小: 90.5 KB
分享到:
相关推荐
8. **热部署与类加载器** 在开发环境中,为了快速调试和更新,可以通过自定义类加载器实现类的热替换,达到无需重启应用就能更新代码的效果。 9. **类加载器的可见性** 子类加载器可以访问父类加载器加载的类,但...
Java的类加载器是Java虚拟机(JVM)的核心组件之一,它负责将类的字节码从磁盘、网络或其他数据源加载到内存中,并转换为可执行的Java对象。类加载器不仅关乎程序的运行,还在实现动态加载、插件系统等方面发挥着...
Java 类加载器是Java运行时环境的一个重要组成部分,它的主要职责是将编译后的字节码(.class文件)加载到JVM中,使得程序能够运行。类加载器的机制保证了类的唯一性,同时也提供了灵活性,允许我们自定义加载逻辑。...
8. OSGi与类加载器: OSGi(Open Service Gateway Initiative)框架使用类加载器实现模块化,每个模块(Bundle)都有自己的类加载器,允许模块间的类隔离和动态加载。 总结,Java类加载器是Java平台的关键组成部分...
WebLogic的主要类加载器包括Bootstrap类加载器、Extension类加载器、Application类加载器以及Domain类加载器等。 2. **Bootstrap类加载器** Bootstrap类加载器是JVM的一部分,负责加载JDK的核心类库,如rt.jar,这...
Java中的类加载器分为三个主要层次:启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和系统类加载器(AppClassLoader)。启动类加载器负责加载JRE核心库,如`rt.jar`;扩展类加载器...
类加载器分为根加载器(bootstrap classloader)、扩展类加载器(ext classloader)、系统类加载器(system classloader)、自定义类加载器(通常继承java.net.URLClassLoader,重写findClass()),它们的关系通常...
### 利用类装载器动态加载类并启动类 #### 概述 本文将详细介绍如何通过自定义类装载器来动态加载并启动类的过程,同时介绍一个简单的位移加密算法和非运算加密算法,以及如何使用这些算法进行文件的加密与解密。此...
Java中的类加载器通常分为三种:启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader)。它们遵循双亲委派模型,即较低层次的类加载器会将...
Java的类加载器分为Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(扩展类加载器)和App ClassLoader(应用程序类加载器)。自定义类加载器可以继承`java.lang.ClassLoader`,并覆盖`loadClass()`...
5. 引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(AppClassLoader): - 这是JVM内置的三种类加载器,它们分别负责加载JDK的核心类库、JRE的扩展类库以及用户...
Java中的类加载器主要有三种:Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(扩展类加载器)和AppClassLoader(应用程序类加载器)。用户还可以自定义类加载器来满足特定需求。 2. **双亲委派...
类加载器有三种:引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader)。用户还可以自定义类加载器。 2. **验证**:验证是确保字节码安全...
Java中类的卸载并不常见,因为只有当类加载器被垃圾回收,且该类加载器加载的所有类都没有被引用时,JVM才会卸载这些类。这使得类的卸载变得困难,但在特定场景下,如内存管理严格的系统,仍需要考虑类的卸载问题。...
Tomcat通过自定义的类加载器实现了特定的类加载顺序,以确保能够正确处理不同来源的类文件,避免类的重复加载和类版本冲突问题。以下是Tomcat启动过程中类加载的具体顺序: #### 三、类加载顺序详述 1. **Bootstrap...
这是一种特殊的类加载机制,当一个类加载器收到加载类的请求时,它首先会委托父类加载器去尝试加载,只有当父类加载器无法加载时,当前类加载器才会尝试自己加载。这样可以确保Java核心类库的唯一性,避免类的重复...
默认有三个内置的类加载器:Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(扩展类加载器)和App ClassLoader(应用程序类加载器)。开发者可以自定义类加载器,实现`java.lang.ClassLoader`接口,...
Java中的类加载器分为Bootstrap ClassLoader、Extension ClassLoader和AppClassClassLoader,以及用户自定义的类加载器。Bootstrap ClassLoader负责加载JDK核心库,Extension ClassLoader加载扩展库,而...
### 《链接器和加载器》(中文版)—— 关键知识点详解 #### 第1章 链接和加载 **链接器和加载器的作用**: - **链接器**负责将多个目标文件(通常是由编译器产生的)链接成一个可执行文件或库。 - **加载器**则是在...
Java有三种基本类型的类加载器:Bootstrap ClassLoader(启动类加载器)、Extension ClassLoader(扩展类加载器)和AppClassloader(应用程序类加载器)。此外,用户还可以自定义类加载器。加载类时,遵循双亲委派...