探索JVM底层奥秘ClassLoader源码分析
1、JVM基本结构:*.java--------javac编译------>*.class-----ClassLoad加载---->运行时数据区------->执行引擎,接口库------>本地方法库 2、JVM运行流程:? public?class?Dome { private?static?int?tem=1; static?{ tem=2; System.out.println(tem); } public?static?void?main(String[] args) { tem=6; System.out.println(tem); } } 类的装载: 加载,连接(验证,准备,解析),初始化,使用,卸载 Class会保存类的定义或者结构到堆中 初始化:执行类的构造器《clinit》,为类的静态变量赋予正确的初始值 构造器: 1、static变量 2、Static{}语句块 构造方法:实列化对象 3、类加载器双亲委派模型Bootstrat ClassLoader :启动类加载器(C++,内核)【rt.jar】 ?null Extension ClassLoader:扩展类加载器---extends->【%JAVA_HOME%/lib/ext/*.jar】ClassLoader App ClassLoader:系统类加载器 ----extends-->【Classpath下加载】ClassLoader(扩展类加载器) 自定义类加载器: extends ClassLoader(系统类加载器 )---【自定义加载】 public?static?void?main(String[] args) { //System.out.println(Dome2.class.getClassLoader()); ClassLoader classLoader=Dome2.class.getClassLoader(); while(classLoader!=null) { System.out.println(classLoader); classLoader=classLoader.getParent(); } System.out.println(classLoader); } 编译: [email?protected]???》系统类加载器 [email?protected] ??》扩展类型加载器 Null??》启动类加载器 ? 在jdk的rt.jar下找到java.lang.classLoader类,找到类加载方法: @parem:name,类的二进制字节流 ??public?Class<?> loadClass(String name) throws?ClassNotFoundException{ ????????return?loadClass(name,false); ???} 查找是否有这个类: 有:从父类中加载 无:从BootstrapClass加载 //parent: ? // The parent class loader for delegation ????// Note: VM hardcoded the offset of this field,thus all new fields // must be added *after* it private?final?ClassLoader?parent;//父类委派机制 :包含关系 ?protected?Class<?> loadClass(String name,boolean?resolve) ????????throws?ClassNotFoundException ????{ ????????synchronized?(getClassLoadingLock(name)) { ????????????// First,check if the class has already been loaded ????????????Class<?> c?= findLoadedClass(name); ????????????if?(c?== null) { ????????????????long?t0?= System.nanoTime(); ????????????????try?{ ????????????????????if?(parent?!= null) { ?????????????????????? ?c?= parent.loadClass(name,false); ????????????????????} else?{ ????????????????????????c?= findBootstrapClassOrNull(name); ????????????????????} ????????????????} catch?(ClassNotFoundException e) { ????????????????????// ClassNotFoundException thrown if class not found ????????????????????// from the non-null parent class loader ????????????????} ? ????????????????if?(c?== null) { ????????????????????// If still not found,then invoke findClass in order ????????????????????// to find the class. ????????????????????long?t1?= System.nanoTime(); ????????????????????c?= findClass(name);?//自定义类加载【回调方法】 ? ????????????????????// this is the defining class loader; record the stats ????????????????????sun.misc.PerfCounter.getParentDelegationTime().addTime(t1?- t0); ????????????????????sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); ????????????????????sun.misc.PerfCounter.getFindClasses().increment(); ????????????????} ????????????} ????????????if?(resolve) { ????????????????resolveClass(c); ????????????} ????????????return?c; ????????} ????} 被子类重写: ?protected?Class<?> findClass(String name) throws?ClassNotFoundException { ????????throw?new?ClassNotFoundException(name); } 实列:自定义类加载器 一个本地的Demo.class文件,一个编译环境中的Demo.class文件 测试调用类: public?class?Dome { public?Dome() { System.out.println("A Dome:"+Dome.class.getClassLoader()); } } 需求实现类: package com.cn.classload; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; /** ?* @Description: 自定义类加载器 ?* @ClassName: MyClassLoader ?* @author 明 ?* @date 2019年9月15日 ?* ?*/ public class MyClassLoader extends ClassLoader { private String path;// 加载类的路劲 private String name;// 类加载器名称 ? public MyClassLoader(String name,String path) { super();// 让系统类加载器成为该类的父类 this.name = name; this.path = path; } ? // 父类委托机制:父类加载器 public MyClassLoader(ClassLoader parent,String name,String path) { super(parent); this.name = name; this.path = path; ? } ? /** ?* 加载自定义的ClassLoader Title: findClass Description: ?* ?* @param name:包路径 ?* @return ?* @throws ClassNotFoundException ?* @see java.lang.ClassLoader#findClass(java.lang.String) ?* ?*/ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { ? byte[] data = readClassFileToByteArray(name); return this.defineClass(name,data,data.length); } ? /** ?* Title: toString Description: ?* ?* @return ?* @see java.lang.Object#toString() ?* ?*/ @Override public String toString() { // TODO Auto-generated method stub return this.name; } ? /** ?* @Description: 获取.class文件的字节数组 ?* @Title: readClassFileToByteArray ?* @date 2019-09-15 17:27 ?* @param @param name2 ?* @param @return 参数 ?* @return byte [] 返回类型 ?* @throws @return byte [] ?* @param name2 ?* @return ?*/ private byte[] readClassFileToByteArray(String name) { InputStream iStream = null; byte[] returnData = null; name = name.replaceAll(".","/"); String filePath = this.path + name + ".class"; System.out.println("路径:"+filePath); File file = new File(filePath); ByteArrayOutputStream os = new ByteArrayOutputStream(); try { iStream = new FileInputStream(file); int tmp = 0; while ((tmp = iStream.read()) != -1) { os.write(tmp); ? } returnData = os.toByteArray(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (os != null) { try { os.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (iStream != null) { try { iStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return returnData; } } ? 测试类: public?static?void?main(String[] args) throws?ClassNotFoundException,InstantiationException,IllegalAccessException { MyClassLoader zhangfeimyClassLoader=new?MyClassLoader("zhangfei","D:/com/cn/classload/"); //MyClassLoader wukongmyClassLoader=new MyClassLoader(zhangfeimyClassLoader,"wukong","D:/com/cn/classload/");//现在张飞是悟空的父类委派加载器(输出的就是编译环境中的Dome.class文件) ? MyClassLoader wukongmyClassLoader=new?MyClassLoader(null,"wukong","D:/com/cn/classload/");//这里父类没有就是用自定义的加载器(输出的就是本地磁盘上的Dome.class文件) Class<?> c=wukongmyClassLoader.loadClass("Dome"); c.newInstance(); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |