ClassLoader

 

1.类加载器的最终功能是将java字节码转换成JVM中的Class对象。

   实例代码:

class FileSystemClassloader extends ClassLoader {
	private String directory;
	public FileSystemClassloader(String directory) {
		this.directory = directory;
	}
	
	@Override
	public Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] clsBytes = getClassBytes(name);
		if(clsBytes == null)
			throw new ClassNotFoundException();
		return defineClass(name, clsBytes, 0, clsBytes.length);
	}
	
	private byte[] getClassBytes(String name) {
		String location = getClassLoc(name);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(location);
			byte[] buffer = new byte[4096];
			int readLen = 0;
			while ((readLen = fis.read(buffer)) != -1) {
				baos.write(buffer, 0, readLen);
			}
			baos.flush();
			return baos.toByteArray();
		} catch(IOException e) {
			e.printStackTrace();
		} finally {
			if(fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(baos != null) {
				try {
					baos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}

	private String getClassLoc(String name) {
		return this.directory + File.separatorChar + name.replace('.', File.separatorChar) + ".class";
	}
}

//引导类加载器加载路径
System.out.println("sun.boot.class.path:" + System.getProperty("sun.boot.class.path"));
//扩展类加载器加载路径
System.out.println("java.ext.dirs:" + System.getProperty("java.ext.dirs"));
//系统类加载器加载路径
System.out.println("java.class.path:" +System.getProperty("java.class.path"));

2.Java虚拟机中是根据类加载器+类名来区分对象的,所以不同类加载器加载的同一段字节码是两个不同对象,可通过以下代码测试
String className = "com.meteor.classloader.example.Sample";
Class<?> cls1 = fscl1.loadClass(className);
Class<?> cls2 = fscl2.loadClass(className);
System.out.println("cls1 == cls2?" + (cls1 == cls2));
这段代码测试中如果一直打印true,请用上面代码输出加载类的路径,检查类是被哪个加载器加载的。测试过程如用eclipse等工具,还有路径问题,导致类一直由AppClassLoader加载。

3.线程上下文类加载器
  上下文类加载器解决了加载SPI(Service Provider Interface)实现类的方式,父子委托的加载模式并不总适用于Java应用。Java提供了很多SPI接口,如JDBC,JNDI等,这些接口的定义由引导类加载器加载,而实现一般由系统类加载器加载,最终导致类型转换的问题。对于SPI的加载问题,解决办法就是让核心JNDI类使用线程上下文类加载器加载(此处未验证,未看到源代码),打通类加载器的层次结构。

4.Web容器与类加载器
  Web容器一般有自己的加载方式,请参见Tomcat的ClassLoader的实现。
  Tomcat中的WebappClassLoader实现了ClassLoader的loadClass方法,一般自定义Class,建议实现ClassLoader的findClass方法(仅限于一般小的改动,Tomcat的实现比较复杂,对Class的加载有自己的方式)

5.OSGI与类加载器
  学习中。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值