操作流程都在代码注释中:
/** * 自定义文件系统类加载器 ---->使用自定义类加载器加载 某一目录下的字节码 * @author * 将d:/myjava/com/zm/HelloWorld.class 通过自定义类加载器加载 * * 1 extends ClassLoader 重写findClass(String name) * 2 findClass(String name)内先去findLoadedClass(name)中找 没找到在去parent.loadClass(name)找,在没找到则用自己的代码 * 写流获取目标文件的byte[] * 3 根据 c = defineClass(name, classData, 0,classData.length);得到Class对象并返回即可 * */ public class FileSystemClassLoader extends ClassLoader { // d:/myjava/ private String rootDir; public FileSystemClassLoader(String rootDir){ this.rootDir = rootDir; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { // 先去加载器里面看看已经加载到的类中是否有这个类 Class<?> c = findLoadedClass(name); // loader.loadClass("com.zm.HelloWorld"); //应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类。 if(c!=null){ return c; }else{ ClassLoader parent = this.getParent(); try { c = parent.loadClass(name); //委派给父类加载 调用JVM委托机制来加载,如果一层层上抛都没有加载到com.zm.HelloWorld的话 则走到46行 调用自己的类加载 } catch (Exception e) { // e.printStackTrace(); } if(c!=null){ return c; }else{// byte[] classData = getClassData(name); if(classData==null){ throw new ClassNotFoundException(); }else{ // 将字节码处理成 Class实例返回 c = defineClass(name, classData, 0,classData.length); } } } return c; } // 读取流 将读到的流处理成字节码数组返回 private byte[] getClassData(String classname){ //com.zm.HelloWorld d:/myjava/ com/zm/HelloWorld.class String path = rootDir +"/"+ classname.replace('.', '/')+".class"; // IOUtils,可以使用它将流中的数据转成字节数组 InputStream is = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try{ is = new FileInputStream(path); byte[] buffer = new byte[1024]; int temp=0; while((temp=is.read(buffer))!=-1){ baos.write(buffer, 0, temp); } return baos.toByteArray(); }catch(Exception e){ e.printStackTrace(); return null; }finally{ try { if(is!=null){ is.close(); } } catch (IOException e) { e.printStackTrace(); } try { if(baos!=null){ baos.close(); } } catch (IOException e) { e.printStackTrace(); } } } } 2 public class Demo03 { public static void main(String[] args) throws Exception{ FileSystemClassLoader loader = new FileSystemClassLoader("d:/myjava"); FileSystemClassLoader loader2 = new FileSystemClassLoader("d:/myjava"); Class<?> c = loader.loadClass("com.zm.HelloWorld"); Class<?> c2 = loader.loadClass("com.zm.HelloWorldd"); Class<?> c3 = loader2.loadClass("com.zm.HelloWorld"); Class<?> c4 = loader2.loadClass("java.lang.String"); Class<?> c5 = loader2.loadClass("com.zm.HelloWorld"); System.out.println(c.hashCode()); System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); //同一个类,被不同的加载器加载,JVM认为也是不相同的类 System.out.println(c4.hashCode()); System.out.println(c4.getClassLoader()); //引导类加载器 System.out.println(c3.getClassLoader()); //自定义的类加载器 System.out.println(c5.getClassLoader()); //系统默认的类加载器 } }
相关推荐
在Java编程语言中,类加载器(ClassLoader)是运行时环境...理解类加载机制并正确实现自定义加载器是提升Java应用开发能力的重要一步。在实际项目中,合理利用类加载器可以解决很多复杂问题,比如模块化、动态更新等。
创建自定义类加载器通常需要继承`java.lang.ClassLoader`类,并重写`findClass()`方法。`findClass()`方法会在类加载器中查找指定名称的类的字节码。以下是一个简单的基于磁盘的自定义类加载器示例: ```java ...
- **安全沙箱**:每个加载器都有自己的命名空间,可以通过自定义加载器限制代码访问权限。 - **插件系统**:插件有自己的类加载器,使得插件可以独立于主程序加载和卸载。 在编写`MyClassLoader`时,需要注意的是,...
1. **继承ClassLoader类**:自定义类加载器需要继承`java.lang.ClassLoader`,然后重写其关键方法`findClass(String name)`。这个方法用于查找并加载指定全名的类。 2. **读取字节码**:在`findClass`方法中,你...
要实现一个自定义类加载器,你需要继承`java.lang.ClassLoader`类,并重写其关键方法`findClass(String name)`。这个方法接收全限定类名作为参数,返回加载后的`Class`对象。在`findClass`中,你需要实现查找和读取...
3. Application ClassLoader:也称为系统类加载器,负责加载用户类路径`-cp`或`-classpath`指定的所有类。 当一个类被加载时,如果它的父类加载器无法加载该类,那么会将任务委派给子类加载器。这就是著名的"委托...
为了实现热部署,需要使用自定义的ClassLoader替换系统的加载器,创建一个新的ClassLoader,再用它加载Class,得到的Class对象就是新的(因为不是同一个类加载器),再用该Class对象创建一个实例,从而实现动态更新...
### Java自定义类加载器(Class Loader)详解 #### 一、引言 在Java语言中,类加载机制是其动态特性的核心之一。通过类加载器(Class Loader),Java程序能够在运行时根据需要加载所需的类,从而实现高度的灵活性...
Java 实现的自定义类加载器示例 Java 实现的自定义类加载器是 Java 语言中的一种机制,允许开发者自定义类加载器,以满足特定的需求。本文将详细介绍 Java 实现的自定义类加载器的原理和实现技巧。 ClassLoader 类...
但在特定条件下,如果类加载器不可达,那么该加载器加载的类可能会被卸载。不过,这是JVM的内部行为,对外部是透明的。 2. **重载**: 由于Java类一旦加载就不能被修改,因此不能直接重载类。但在某些场景下(如JSP...
Java自定义类加载器代码示例是一种使用Java语言实现的类加载器示例,主要用于加载Java类文件。类加载器是Java虚拟机(JVM)中的一种机制,用于将Java类文件加载到JVM中,以便JVM可以正确地执行Java程序。 在Java中...
此外,我们还可以看到,`Object`类是由启动类加载器加载的,而自定义类`Person`则是由系统的类加载器加载的。 #### 七、总结 类加载器在Java中扮演着至关重要的角色,不仅负责加载类,还维护了类的层次关系,确保...
- `findClass()`:从Java 1.2开始,自定义类加载器通常只需要重写此方法,当父类加载器找不到类时,此方法会被调用来查找类。 - `defineClass()`:这是一个final方法,用于将字节数组转换为Class对象,实现字节码...
自定义加载器需要重写`findClass()`或`loadClass()`方法。在`MyClassLoader2`示例中,它尝试从指定路径查找类的字节码文件,并通过`defineClass()`方法将字节码转换为Class对象。 ```java public Class<?> find...
不同类加载器加载的相同类会被视为不同的类,即使它们的字节码完全相同。这是实现多版本库共存的基础。 5. 动态加载与插件系统: 类加载器使得在运行时动态加载新类成为可能,这对于构建插件系统或服务发现等场景...
在这个例子中,`EncryptedClassLoader`是我们的自定义加载器,它覆盖了`findClass`方法以处理加密的类。`main`方法中,我们使用`Class.forName`加载类,并传入我们的自定义类加载器。找到main方法后,通过反射调用它...
系统类加载器在加载类时,会先尝试让扩展类加载器加载,如果扩展类加载器无法加载,则再由系统类加载器自己尝试加载。这样的设计是为了保证核心类库的唯一性和安全性,避免用户自定义的类覆盖了 JDK 内置的核心类。 ...
而`log4j`的配置文件可能被不同的类加载器加载,这就需要我们理解类加载器如何查找和加载资源,以及在多层类加载器结构下如何配置和管理`log4j`。 设计模式在类加载器的设计中也扮演着重要角色。例如,使用工厂模式...
开发者编写的大部分Java代码都由系统类加载器加载。 类加载器之间的关系遵循双亲委托模型。当一个类加载器接收到加载类的请求时,它首先会委托父类加载器尝试加载,只有当父类加载器无法加载时,当前类加载器才会...