jvm自定义类的加载器
2016-04-10 17:44
405 查看
1. 创建用户自定义的类加载器:
要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定的类的名字,返回对应的Class对象的引用。
2. 自定义类加载器:
MyClassLoader.java 该例子主要用来验证父类委托机制!
test3方法中,MyClassLoader类由系统类加载器加载,而Sample类由loader3类加载器加载,因此MyClassLoader类看不见Sample类。
在MyClassLoader类的main()方法中使用Sample类会导致错误。
当两个不同命名空间内的类互相不可见时,可采用Java反射机制来访问对方实例的属性和方法,即反射可以突破命名空间的限制。
要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定的类的名字,返回对应的Class对象的引用。
2. 自定义类加载器:
MyClassLoader.java 该例子主要用来验证父类委托机制!
public class MyClassLoader extends ClassLoader { private String name; // 类加载器的名字 private String path = "d:\\"; // 加载类的路径 private final String fileType = ".class"; // class文件的扩展名 public MyClassLoader(String name) { super(); // 让系统类加载器成为该类加载器的父加载器 this.name = name; } public MyClassLoader(ClassLoader parent, String name) { super(parent); // 显式指定该类加载器的父加载器 this.name = name; } @Override public String toString() { return this.name; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } @Override public Class<?> findClass(String name) throws ClassNotFoundException { // 重写的时候把protected改为public // 获取字节数组 byte[] data = this.loadClassData(name); // 将字节数组转换成Class对象返回 return this.defineClass(name, data, 0, data.length); } /** * 得到class文件的二进制字节数组 * * @param name * @return */ private byte[] loadClassData(String name) { InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = null; try { // 将完整类名中的.转化成\ name = name.replace(".", "\\"); is = new FileInputStream(new File(path + name + fileType)); baos = new ByteArrayOutputStream(); int ch = 0; while (-1 != (ch = is.read())) { baos.write(ch); } data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { is.close(); baos.close(); } catch (Exception e2) { } } return data; } // main方法用来测试 public static void main(String[] args) throws Exception { MyClassLoader loader1 = new MyClassLoader("loader1"); // loader1的父加载器是系统类加载器 // 系统类加载器会在classpath指定的目录中加载类 loader1.setPath("d:\\myapp\\serverlib\\"); MyClassLoader loader2 = new MyClassLoader(loader1, "loader2"); // 将loader1作为loader2的父加载器 loader2.setPath("d:\\myapp\\clientlib\\"); MyClassLoader loader3 = new MyClassLoader(null, "loader3"); // loader3的父加载器是根类加载器 loader3.setPath("d:\\myapp\\otherlib\\"); // 测试加载 test(loader2); test(loader3); // 测试不同命名空间的类的互相访问 test2(loader3); } public static void test(ClassLoader loader) throws Exception { Class clazz = loader.loadClass("Sample"); Object object = clazz.newInstance(); } public static void test2(ClassLoader loader) throws Exception { Class clazz = loader.loadClass("Sample"); Sample object = (Sample) clazz.newInstance(); System.out.println("sample v1: " + object.v1); } }Sample.java
public class Sample { public int v1 = 1; public Sample() { System.out.println("Sample is loaded by: " + this.getClass().getClassLoader()); // 主动使用Dog类 new Dog(); } }Dog.java
public class Dog { public Dog() { System.out.println("Dog is loaded by: " + this.getClass().getClassLoader()); } }
test3方法中,MyClassLoader类由系统类加载器加载,而Sample类由loader3类加载器加载,因此MyClassLoader类看不见Sample类。
在MyClassLoader类的main()方法中使用Sample类会导致错误。
当两个不同命名空间内的类互相不可见时,可采用Java反射机制来访问对方实例的属性和方法,即反射可以突破命名空间的限制。
相关文章推荐
- iOS多线程-SDWebImage简单介绍 1 设置imageView的图片 (内存缓存&磁盘缓存) 1 [cell.imageView sd_setImageWithURL:[NSURL URL
- Javascript验证Textarea中是否有值/javascript验证select是否为空(是否选择)
- 桶式排序(C语言)
- java递归获取某个父节点下面的所有子节点
- pm命令
- 函数指针 指针函数 指针的指针 指向指针数组的指针
- 后台运行
- STM32 CubeMX HAL UART interface API
- 进程间通信 - 匿名管道实现
- 如何回答「未来5年如何规划?」【面试核心问题8】
- Struts2类型转换
- CI框架导出数据
- Lua语句
- 记账软件团队开发
- 进程间的通信
- JNI 开发笔记 - 示例代码
- Kafka源码分析之Sender
- sqlldr入库Oracle
- HDU 3436 Queue-jumpers
- [Zabbix3.0 ]添加Nginx监控