JAVA_类加载器学习

26 篇文章 0 订阅

类加载器分层
1.引导类加载器,使用C++实现,位于rt.jar
2.扩展类加载器
3.应用类加载器

使用双亲委派机制,保证java核心库的安全
例如用户自定义一个java.lang.String类,该类在被加载的时候,会交由应用类加载器,应用类加载器再交由扩展类加载器,扩展类加载器交由引导类加载器,引导类加载器发现java核心库中已存在java.lang.String类,故不会加载用户自定义的java.lang.String类,从而保证了java核心库的安全

1.初识类加载器
public class Demo02 {
	public static void main(String[] args) {
		System.out.println(ClassLoader.getSystemClassLoader()); // 应用类加载器
		System.out.println(ClassLoader.getSystemClassLoader().getParent()); //扩展类加载器
		System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent()); // 引导类加载器,C++实现,此处无法获取,位于rt.jar
		
		System.out.println(System.getProperty("java.class.path"));
		
		System.out.println("====================================================");
//		StringBak a = "gaogao";
		
		// 根据双亲委派机制(代理模式的一种(自己的事交给别人来做)),用户自定义的String 在引导类加载器中已存在,故不会加载用户自定义的String,以抱着呢个java核心库的安全
//		System.out.println(a.getClass().getClassLoader());  // null,即不会被加载
//		System.out.println(a);
	}
}
2.自定义文件系统类加载器
package com.bjsxt.test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 自定义文件系统类加载器
 * @author WL20180732
 *
 */
public class FileSystemClassLoader extends ClassLoader {
	
	private String rootDir;

	public FileSystemClassLoader(String rootDir) {
		this.rootDir = rootDir;
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		Class<?> c = findLoadedClass(name);
		
		// 应该要先查询有没有加载过这个类。如果已经加载,则直接返回。如果没有,则加载新类
		if (c != null) {
			return c;
		} else {
			ClassLoader parent = this.getParent();
			try {
				c = parent.loadClass(name); // 委派给父类加载器
			} catch (Exception e) {
			}
			if (c != null) {
				return c;
			} else {
				byte[] classData = getClassData(name);
				if (classData == null) {
					throw new ClassNotFoundException();
				} else {
					c = defineClass(name, classData, 0, classData.length);
					return c;
				}
			}
		}
	}

	private byte[] getClassData(String name) {
		String path = rootDir + "/" + name.replace(".", "/") +".class";
		InputStream is = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			is = new FileInputStream(path);
			byte[] buffer = new byte[1024];
			int len = 0;
			while((len = is.read(buffer)) != -1) {
				bos.write(buffer, 0, len);
			}
			return bos.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
}

/**
 * 测试自定义的FileSystemClassLoader
 * @author WL20180732
 *
 */
public class Demo03 {
	public static void main(String[] args) throws ClassNotFoundException {
		FileSystemClassLoader loader = new FileSystemClassLoader("E:/mycode");
		FileSystemClassLoader loader2 = new FileSystemClassLoader("E:/mycode");
		Class<?> c = loader.loadClass("Welcome");
		Class<?> c2 = loader.loadClass("Welcome");
		Class<?> c3 = loader2.loadClass("Welcome");  // 不同的类加载器加载同一个类文件,创建的是不同的类
		Class<?> c4 = loader2.loadClass("java.lang.String");
		Class<?> c5 = loader2.loadClass("com.bjsxt.test.Demo01");
		System.out.println(c.hashCode());
		System.out.println(c2.hashCode());
		System.out.println(c3.hashCode());  // 同一个类,被不同的加载器加载,JVM也认为是不同的类
		System.out.println(c3.getClassLoader()); // 自定义类加载器
		System.out.println(c4.getClassLoader());  // 引导类加载器加载,返回 null
		System.out.println(c5.getClassLoader());  // AppClassLoader加载
		
	}
}

在这里插入图片描述

3.自定义网络类加载器
package com.bjsxt.test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * 自定义网络类加载器
 * @author WL20180732
 *
 */
public class NetClassLoader extends ClassLoader {
	
	private String rootUrl;

	public NetClassLoader(String rootUrl) {
		this.rootUrl = rootUrl;
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		Class<?> c = findLoadedClass(name);
		
		// 应该要先查询有没有加载过这个类。如果已经加载,则直接返回。如果没有,则加载新类
		if (c != null) {
			return c;
		} else {
			ClassLoader parent = this.getParent();
			try {
				c = parent.loadClass(name); // 委派给父类加载器
			} catch (Exception e) {
			}
			if (c != null) {
				return c;
			} else {
				byte[] classData = getClassData(name);
				if (classData == null) {
					throw new ClassNotFoundException();
				} else {
					c = defineClass(name, classData, 0, classData.length);
					return c;
				}
			}
		}
	}

	private byte[] getClassData(String name) {
		String path = rootUrl + "/" + name.replace(".", "/") +".class";
		InputStream is = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			URL url = new URL(path);
			is = url.openStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while((len = is.read(buffer)) != -1) {
				bos.write(buffer, 0, len);
			}
			return bos.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
}

4.自定义加解密类加载器
package com.bjsxt.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 加密工具类
 * @author WL20180732
 *
 */
public class EncryptUtil {

	public static void main(String[] args) {
		encrypt(new File("E:/mycode/Welcome.class"), new File("E:/mycode/temp/Welcome.class"));
	}
	
	public static void encrypt(String src, String dest) {
		encrypt(new File(src), new File(dest));
	}
	public static void encrypt(File src, File dest) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		
		try {
			fis = new FileInputStream(src);
			fos = new FileOutputStream(dest);
			
			int temp = -1;
			while((temp = fis.read()) != -1) {
				fos.write(temp^0xff); //取反,加密
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}



```java
package com.bjsxt.test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 加载文件系统中加密后的字节码文件的类加载器
 * @author WL20180732
 *
 */
public class DecryptClassLoader extends ClassLoader {
	
	private String rootDir;

	public DecryptClassLoader(String rootDir) {
		this.rootDir = rootDir;
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		Class<?> c = findLoadedClass(name);
		
		// 应该要先查询有没有加载过这个类。如果已经加载,则直接返回。如果没有,则加载新类
		if (c != null) {
			return c;
		} else {
			ClassLoader parent = this.getParent();
			try {
				c = parent.loadClass(name); // 委派给父类加载器
			} catch (Exception e) {
			}
			if (c != null) {
				return c;
			} else {
				byte[] classData = getClassData(name);
				if (classData == null) {
					throw new ClassNotFoundException();
				} else {
					c = defineClass(name, classData, 0, classData.length);
					return c;
				}
			}
		}
	}

	private byte[] getClassData(String name) {
		String path = rootDir + "/" + name.replace(".", "/") +".class";
		InputStream is = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			is = new FileInputStream(path);
			
			int temp = -1;
			while((temp = is.read()) != -1) {
				bos.write(temp^0xff); //取反,解密
			}
			return bos.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
}


package com.bjsxt.test;

/**
 * 测试简单的加密解密(取反)操作
 * @author WL20180732
 *
 */
public class Demo04 {
	public static void main(String[] args) throws ClassNotFoundException {
		// 测试取反操作
//		int a = 3; //011
//		System.out.println(Integer.toBinaryString(a^0xff));  // 取反
		
		// 加密后的class文件,正常的类加载器无法加载,报ClassFormatError
//		FileSystemClassLoader loader = new FileSystemClassLoader("E:/mycode/temp");
//		Class<?> c = loader.loadClass("Welcome");
//		System.out.println(c);
		
		// 
		DecryptClassLoader loader2 = new DecryptClassLoader("E:/mycode/temp");
		Class<?> c2 = loader2.loadClass("Welcome");
		System.out.println(c2);
	}
}

```![在这里插入图片描述](https://img-blog.csdnimg.cn/20200707095414272.png)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值