Java Classloader
来源:互联网 发布:破解八零网络验证 编辑:程序博客网 时间:2024/04/27 06:36
Java类装载器可分为Bootrap类装载器,扩展类装载器,应用类装载器,自定义类装载器。其中,根类装载器和扩展类装载器是不能直接控制的,应用类装载器和自定义装载器则可以用来自行装载类。
应用类装载器将类装载到应用类Classloader中,而自定义类装载器将类装载到自定义(如使用URLClassloader)中,不同的自定义Classloader装载同样的Class,具有独立的内存空间,即使是类中的静态变量,也是相互隔离,不受对方赋值操作的影响。
1、一个应用类装载器的例子:
/** * 装载jar文件 * @param file * @throws Exception */ public static void loadJar(String file) throws Exception { JarFile jar = new JarFile(file); Enumeration<JarEntry> entries = jar.entries(); ClassLoader cl = (ClassLoader) Thread.currentThread().getContextClassLoader(); //获取ClassLoader类的defineClass(String, byte[], int, int) 方法,对protected类型修改访问权限 Method md1 = java.lang.ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); md1.setAccessible(true); String name; // 装载所有的jar文件 while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); if (entry.getName().endsWith(".class")) { name = entry.getName(); name = name.substring(0, name.length() - 6); name = name.replaceAll("/", "."); InputStream is = jar.getInputStream(entry); ByteArrayOutputStream dataOut = new ByteArrayOutputStream(); byte[] packData = new byte[2048]; int readLen = 0; while (-1 != (readLen = is.read(packData))) { dataOut.write(packData, 0, readLen); } if (dataOut.size() <= 0) { throw new ClassNotFoundException(name); } byte[] classFile = dataOut.toByteArray(); System.out.println("class name:" + name); md1.invoke(cl, name, classFile, 0, classFile.length); } } } /** * */ public void loadTest(){ String file = "D:\\test2\\TestedClass.jar"; try { ClassLoaderTest.loadJar(file); Class<?> c = Class.forName("dictquery.Hello"); Method[] ms = c.getDeclaredMethods(); Object obj = c.newInstance(); for(int i=0;i<ms.length;i++){ Method m = ms[i]; System.out.println("Method:" + m.getName()); m.invoke(obj, new Object[]{}); } Field[] fs = c.getDeclaredFields(); for (int i = 0; i < fs.length; i++) { Field f = fs[i]; System.out.println("Field:" + f.getName() + ", Modifier:" + f.getModifiers()); if((Modifier.PUBLIC+ Modifier.STATIC) == f.getModifiers()){ System.out.println("Used public and static qualify!"); } //改变可访问属性 f.setAccessible(true); try { String value = (String)f.get(obj); System.out.println("Field " + f.getName() + " default value:" + value); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } } /** * * @param args */ public static void main(String[] args) { ClassLoaderTest ct = new ClassLoaderTest(); ct.loadTest(); }
该方法装载类后,类的内存空间在应用装载类中。
2、一个自定义类装载器的例子:
import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;public class FileSystemClassLoader extends ClassLoader {private String rootDir;public FileSystemClassLoader(String rootDir) {this.rootDir = rootDir;}protected Class<?> findClass(String name) throws ClassNotFoundException {byte[] classData = getClassData(name);if (classData == null) {throw new ClassNotFoundException();}else {return defineClass(name, classData, 0, classData.length);}}private byte[] getClassData(String className) {String path = classNameToPath(className);try {InputStream ins = new FileInputStream(path);ByteArrayOutputStream baos = new ByteArrayOutputStream();int bufferSize = 4096;byte[] buffer = new byte[bufferSize];int bytesNumRead = 0;while ((bytesNumRead = ins.read(buffer)) != -1) {baos.write(buffer, 0, bytesNumRead);}return baos.toByteArray();} catch (IOException e) {e.printStackTrace();}return null;}private String classNameToPath(String className) {return rootDir + File.separatorChar+ className.replace('.', File.separatorChar) + ".class";}}该类装载器装载类后,类的运行空间在自定义Classloader中,对两个使用上述
FileSystemClassLoader或URLClassloadeer而言,对同一类,在不同的Classloader中是相互隔离的,互不受干扰。
3、自定义类装载器测试
使用URLClassloader装载:
/** * 类装载到自定义类装载器,分别使用不同的自定义装载器装载 */public void classLoadTest3c(){try {URL[] urls = new URL[]{ new File("D:\\Users\\workspace\\ClassLoadTest\\bin").toURI().toURL() };ClassLoader clsLoader = new URLClassLoader(urls);Class<?> c1 = clsLoader.loadClass("test.ClassLoaderTest");Field f = c1.getDeclaredField("testVar");Method m = c1.getMethod("showTestVar", null);Object obj = c1.newInstance();m.invoke(obj, new Object[]{});f.set(obj, "The testVar's value is modified!");m.invoke(obj, new Object[]{});System.out.println("--------------------");System.out.println(this.getClass().getClassLoader());ClassLoader clsLoader2 = new URLClassLoader(urls);System.out.println(clsLoader2.getSystemClassLoader());Class<?> c2 = clsLoader2.loadClass("test.ClassLoaderTest");Object obj2 = c2.newInstance();Method m2 = c2.getMethod("showTestVar", null);m2.invoke(obj2, new Object[]{});m.invoke(obj, new Object[]{});m2.invoke(obj2, new Object[]{});} catch (Exception e) {e.printStackTrace();}}
ClassLoaderTest.java, 参见1.
4、在已有的自定义类装载器中装载
/** * 类装载到自定义类装载器,共用一个自定义类装载器 */public void classLoadTest3d(){try {URL[] urls = new URL[]{ new File("D:\\Users\\workspace\\ClassLoadTest\\bin").toURI().toURL() };ClassLoader clsLoader = new URLClassLoader(urls);Class<?> c1 = clsLoader.loadClass("test.ClassLoaderTest");Field f = c1.getDeclaredField("testVar");Method m = c1.getMethod("showTestVar", null);Object obj = c1.newInstance();m.invoke(obj, new Object[]{});f.set(obj, "The testVar's value is modified!");m.invoke(obj, new Object[]{});System.out.println("--------------------");System.out.println(this.getClass().getClassLoader());ClassLoader clsLoader2 = new URLClassLoader(urls, clsLoader);System.out.println(clsLoader2.getSystemClassLoader());Class<?> c2 = clsLoader2.loadClass("test.ClassLoaderTest");Object obj2 = c2.newInstance();Method m2 = c2.getMethod("showTestVar", null);m2.invoke(obj2, new Object[]{});m.invoke(obj, new Object[]{});m2.invoke(obj2, new Object[]{});} catch (Exception e) {e.printStackTrace();}}clsLoader2使用clsLoader 的Classloader,因而,clsLoader2的类"test.ClassLoaderTest" 使用clsLoader中的"test.ClassLoaderTest"
5、注意,这些测试的类均不要放置在当前项目的类路径底下。否则因为Bootrap类装载器会自动装载,再行加载已加载的类无效。
6、
- java ClassLoader
- JAVA classLoader
- java ClassLoader
- Java ClassLoader
- Java ClassLoader
- java ClassLoader
- java classloader
- Java ClassLoader
- java ClassLoader
- java classLoader
- Java Classloader
- Java ClassLoader
- Java ClassLoader
- java classloader
- Java Classloader
- java classloader
- java classLoader
- Java ClassLoader
- NetBeans配置Android开发环境
- “Cache-control”常见的取值有private、no-cache、max-age、must-revalidate等
- MVC带多个参数的router(sample)
- Another method get instance of JAVA Object
- jsoncpp第二篇------API
- Java Classloader
- CSS控制页面的几种方式以及各种方式的优先级
- boost 库 timer组件的源码分析 [大三四八九月实习]
- HDOJ 1056 HangOver
- Django学习笔记3:Model,Template,View 基本概念
- PCI register driver
- HDU 3401 Trade
- Android系统广播
- 创建字符设备的三种方法