Java界隐秘技能ClassLoader,吃透它看这一篇就够了
值得留意的是图中的 ExtensionClassLoader 的 parent 指针画了虚线,这是由于它的 parent 的值是 null,当 parent 字段是 null 时就暗示它的父加载器是「根加载器」。假如某个 Class 工具的 classLoader 属性值是 null,那么就暗示这个类也是「根加载器」加载的。留意这里的 parent 不是 super 不是父类,只是 ClassLoader 内部的字段。 Class.forName当我们在行使 jdbc 驱动时,常常会行使 Class.forName 要领来动态加载驱动类。
其道理是 mysql 驱动的 Driver 类里有一个静态代码块,它会在 Driver 类被加载的时辰执行。这个静态代码块会将 mysql 驱动实例注册到全局的 jdbc 驱动打点器里。
forName 要领同样也是行使挪用者 Class 工具的 ClassLoader 来加载方针类。不外 forName 还提供了多参数版本,可以指定行使哪个 ClassLoader 来加载。
通过这种情势的 forName 要领可以打破内置加载器的限定,通过行使自定类加载器应承我们自由加载其余恣意来历的类库。按照 ClassLoader 的转达性,方针类库转达引用到的其余类库也将会行使自界说加载器加载。 自界说加载器ClassLoader 内里有三个重要的要领 loadClass()、findClass() 和 defineClass()。 loadClass() 要领是加载方针类的进口,它起首会查找当前 ClassLoader 以及它的双亲内里是否已经加载了方针类,假如没有找到就会让双亲实行加载,假如双亲都加载不了,就会挪用 findClass() 让自界说加载器本身来加载方针类。ClassLoader 的 findClass() 要领是必要子类来包围的,差异的加载器将行使差异的逻辑来获取方针类的字节码。拿到这个字节码之后再挪用 defineClass() 要领将字节码转换成 Class 工具。下面我行使伪代码暗示一下根基进程:
自界说类加载器不易粉碎双亲委派法则,不要等闲包围 loadClass 要领。不然也许会导致自界说加载器无法加载内置的焦点类库。在行使自界说加载器时,要明晰好它的父加载器是谁,将父加载器通过子类的结构器传入。假如父类加载器是 null,那就暗示父加载器是「根加载器」。
双亲委派法则也许会酿成三亲委派,四亲委派,取决于你行使的父加载器是谁,它会一向递归委派到根加载器。 Class.forName vs ClassLoader.loadClass 这两个要领都可以用来加载方针类,它们之间有一个小小的区别,那就是 Class.forName() 要领可以获取原生范例的 Class,而 ClassLoader.loadClass() 则会报错。
钻石依靠(编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |