张孝详系列
深入理解JVM机制 - 周志明
ClassLoader机制 ? 由下及上委托,上面没有再往下,直到自身(自身没有目标类,就抛ClassNotFoundException,不用子类类加载器)
1、AppClassLoader:加载ClassPath目录下的.class文件
2、ExtClassLoader:加载~/jre/lib/ext.jar中的.class文件
3、Bootstrap:加载 ~/jre/lib/rt.jar中的.class文件(eg、System,String,Object等类)
package cool.pengych.java.classloader; import java.util.Date; /** * ClassLoader 分析 * @author pengyucheng * * 一、认识类加载器 * JDK自带内加载器 * AppClassLoader => ExtClassLoader => Bootstrap用(C++写的二进制代码,同JVM启动时被加入内存) * 1、AppClassLoader:加载ClassPath目录下的.class文件 * 2、ExtClassLoader:加载~/jre/lib/ext.jar中的.class文件 * 3、Bootstrap:加载 ~/jre/lib/rt.jar中的.class文件(eg、System,String,Object等类) *二、类加载器工作机制 *由下及上委托,上面没有再往下,直到自身(自身没有目标类,就抛ClassNotFoundException,不用子类类加载器) *三、自定义类加载器 * className extends java.lang.ClassLoader * 应用 */ public class ClassLoader { public static void main(String[] args) throws Exception { System.out.println(ClassLoader.class.getClassLoader().getClass().getName());// sun.misc.Launcher$AppClassLoader System.out.println(System.class.getClassLoader());// null :BootStrap 类加载器不是java类,这里返回null是合理的 java.lang.ClassLoader loader = ClassLoader.class.getClassLoader(); while(null != loader) { System.out.println(loader.getClass().getName()); loader = loader.getParent(); } System.out.println(loader); /* * 执行结果 * sun.misc.Launcher$AppClassLoader * sun.misc.Launcher$ExtClassLoader * null */ System.out.println(new ClassLoaderAttachment()); Class clazz = new MyClassLoader("//home//pengyucheng//eclipse//java//bin/cool//pengych//java//classloader").loadClass("ClassLoaderAttachment"); Date d1 = (Date) clazz.newInstance(); System.out.println(d1); } }
package cool.pengych.java.classloader; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * 自定义类加载器 * @author pengyucheng */ public class MyClassLoader extends java.lang.ClassLoader // 继承 ClassLoader { public static void main(String[] args) { String srcPath = args[0]; String desDir = args[1]; String desFileName = srcPath.substring(srcPath.lastIndexOf("//") + 1); InputStream ips; OutputStream ops; try { ips = new FileInputStream(srcPath); ops = new FileOutputStream(desDir+desFileName); encryt(ips,ops); ips.close(); ops.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 对输入流中的字节数据取反 */ public static void encryt(InputStream ips, OutputStream ops) throws IOException { int b = -1; while ((b = ips.read()) != -1) { ops.write(b ^ 0xff); } } private String classDir; public MyClassLoader() { // TODO Auto-generated constructor stub } public MyClassLoader(String classDir) { this.classDir = classDir; } @Override protected Class<?> findClass(String name) { String classFileName = classDir + "//" + name + ".class"; try { InputStream is = new FileInputStream(classFileName); ByteArrayOutputStream bos = new ByteArrayOutputStream(); encryt(is,bos); is.close(); byte[] bytes = bos.toByteArray(); bos.close(); return defineClass(bytes,0,bytes.length); } catch ( IOException e) { e.printStackTrace(); } return null; } }
package cool.pengych.java.classloader; import java.util.Date; /** * @author pengyucheng * 自定义类加载器测试用实例 */ public class ClassLoaderAttachment extends Date { private static final long serialVersionUID = 1L; public ClassLoaderAttachment() { // TODO Auto-generated constructor stub } @Override public String toString() { return "just for fun"; } }
一、JDK自带三种类加载器:AppClassLoader、ExtClassLoader及Bootstrap。
二、自制类加载器需继承java.lang.ClassLoader , 重写 findClass方法。可自定义加载类的行为。eg、加载前后可以对类的字节码进行加解密。