`

使用自定义类加载器加载class

 
阅读更多

 

 

 

操作流程都在代码注释中:

 

 

/**
 * 自定义文件系统类加载器 ---->使用自定义类加载器加载 某一目录下的字节码 
 * @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 ...

    自定义Java类加载器

    - **安全沙箱**:每个加载器都有自己的命名空间,可以通过自定义加载器限制代码访问权限。 - **插件系统**:插件有自己的类加载器,使得插件可以独立于主程序加载和卸载。 在编写`MyClassLoader`时,需要注意的是,...

    Java加壳源码-自定义类加载器

    1. **继承ClassLoader类**:自定义类加载器需要继承`java.lang.ClassLoader`,然后重写其关键方法`findClass(String name)`。这个方法用于查找并加载指定全名的类。 2. **读取字节码**:在`findClass`方法中,你...

    自定义类加载代码

    要实现一个自定义类加载器,你需要继承`java.lang.ClassLoader`类,并重写其关键方法`findClass(String name)`。这个方法接收全限定类名作为参数,返回加载后的`Class`对象。在`findClass`中,你需要实现查找和读取...

    ClassLoader类加载器

    3. Application ClassLoader:也称为系统类加载器,负责加载用户类路径`-cp`或`-classpath`指定的所有类。 当一个类被加载时,如果它的父类加载器无法加载该类,那么会将任务委派给子类加载器。这就是著名的"委托...

    Java基于自定义类加载器实现热部署过程解析

    为了实现热部署,需要使用自定义的ClassLoader替换系统的加载器,创建一个新的ClassLoader,再用它加载Class,得到的Class对象就是新的(因为不是同一个类加载器),再用该Class对象创建一个实例,从而实现动态更新...

    java自定义类加载classloader文档,包括代码

    ### Java自定义类加载器(Class Loader)详解 #### 一、引言 在Java语言中,类加载机制是其动态特性的核心之一。通过类加载器(Class Loader),Java程序能够在运行时根据需要加载所需的类,从而实现高度的灵活性...

    Java实现的自定义类加载器示例

    Java 实现的自定义类加载器示例 Java 实现的自定义类加载器是 Java 语言中的一种机制,允许开发者自定义类加载器,以满足特定的需求。本文将详细介绍 Java 实现的自定义类加载器的原理和实现技巧。 ClassLoader 类...

    类加载器文件

    但在特定条件下,如果类加载器不可达,那么该加载器加载的类可能会被卸载。不过,这是JVM的内部行为,对外部是透明的。 2. **重载**: 由于Java类一旦加载就不能被修改,因此不能直接重载类。但在某些场景下(如JSP...

    java自定义类加载器代码示例

    Java自定义类加载器代码示例是一种使用Java语言实现的类加载器示例,主要用于加载Java类文件。类加载器是Java虚拟机(JVM)中的一种机制,用于将Java类文件加载到JVM中,以便JVM可以正确地执行Java程序。 在Java中...

    java类加载器

    此外,我们还可以看到,`Object`类是由启动类加载器加载的,而自定义类`Person`则是由系统的类加载器加载的。 #### 七、总结 类加载器在Java中扮演着至关重要的角色,不仅负责加载类,还维护了类的层次关系,确保...

    Java类加载器原理

    - `findClass()`:从Java 1.2开始,自定义类加载器通常只需要重写此方法,当父类加载器找不到类时,此方法会被调用来查找类。 - `defineClass()`:这是一个final方法,用于将字节数组转换为Class对象,实现字节码...

    java 类加载与自定义类加载器详解

    自定义加载器需要重写`findClass()`或`loadClass()`方法。在`MyClassLoader2`示例中,它尝试从指定路径查找类的字节码文件,并通过`defineClass()`方法将字节码转换为Class对象。 ```java public Class&lt;?&gt; find...

    Java的类加载器

    不同类加载器加载的相同类会被视为不同的类,即使它们的字节码完全相同。这是实现多版本库共存的基础。 5. 动态加载与插件系统: 类加载器使得在运行时动态加载新类成为可能,这对于构建插件系统或服务发现等场景...

    java 类加载器 加密

    在这个例子中,`EncryptedClassLoader`是我们的自定义加载器,它覆盖了`findClass`方法以处理加密的类。`main`方法中,我们使用`Class.forName`加载类,并传入我们的自定义类加载器。找到main方法后,通过反射调用它...

    JVM类加载器说明文档

    系统类加载器在加载类时,会先尝试让扩展类加载器加载,如果扩展类加载器无法加载,则再由系统类加载器自己尝试加载。这样的设计是为了保证核心类库的唯一性和安全性,避免用户自定义的类覆盖了 JDK 内置的核心类。 ...

    类加载器(java)

    而`log4j`的配置文件可能被不同的类加载器加载,这就需要我们理解类加载器如何查找和加载资源,以及在多层类加载器结构下如何配置和管理`log4j`。 设计模式在类加载器的设计中也扮演着重要角色。例如,使用工厂模式...

    深入Java虚拟机_002_深入详解JVM之类加载器深度剖析、根、扩展及系统类加载器

    开发者编写的大部分Java代码都由系统类加载器加载。 类加载器之间的关系遵循双亲委托模型。当一个类加载器接收到加载类的请求时,它首先会委托父类加载器尝试加载,只有当父类加载器无法加载时,当前类加载器才会...

Global site tag (gtag.js) - Google Analytics