黑马程序员技术交流社区

标题: defineClass(),loadClass(),findClass()它们有什么区别? [打印本页]

作者: 赵亚威    时间: 2013-4-8 22:12
标题: defineClass(),loadClass(),findClass()它们有什么区别?
本帖最后由 赵亚威 于 2013-4-9 23:01 编辑

defineClass(),loadClass(),findClass()它们有什么区别?委托机制是谁具有的 还是有的有委托机制 有的没有这一特性
作者: 赵亚威    时间: 2013-4-9 09:41
呵呵 算是吧 再做入学测试
作者: 杨玉辉    时间: 2013-4-9 10:43
就最近的理解情况,希望能给你的帮助
loadClass();是加载 类名.class 字节码文件的工具

findClass();是类加载器在JVM内部实现查找指定路径下的 . class 文件的机制,BootStrap ,ExtClassLoader,AppClassLoader,按照这个顺序查找,有就给JVM加载,没有就往下找, 在基础加强里,张老师 就是复写了该方法,将指定目录下的字节码文件,通过ByteArrayOutputStream 解密后的字节码文件,给JVM 去加载,实现解密的过程

defineClass();是将你定义的字节码文件经过字节数组流解密之后,将该字节流数组生成字节码文件,也就是该类的 文件的类名.class,
注意一点,视频里用的是过时的方法,defineClass( byte[] b ,0, b.length) ,这样生成的字节码就是默认的字节码文件。
他的替代方法是 defineClass(String name  , byte[]  b , 0, b.length ),声明时,name 是指定该类名,这里的类名是指包含它所属的 包名+类名
作者: 李罡    时间: 2013-4-9 15:38
本帖最后由 李罡 于 2013-4-9 15:40 编辑

我的理解是:
CLassLoader类中loadClass的具体实现
(1)查看请求的类装载器是否已经被装载进这个类装载器的命名空间。如果确实如此,返回这个已经装载的Class实例。
(2)否则调用委托机制,如果父类加载成功,则返回这个Class实例。
(3)否则,调用findClass(),findClass会试图寻找或生成一个字节数组。如果成功,findClass()把字节数组传递给defineClass,后者试着导入这个类型,返回一个Class实例。如果findClass返回了一个Class实例,loadClass()把这个实例返回。
(4)否则,findClass抛出某些异常,loadClass返回同样异常。

loadClass()方法里面分为两部分:
第一部分是主要流程:即把一个类加载进内存的时候它要先去一级一级地找父类,看父类能不能加载,如果父类能加载的话,就不用再返回到该类了让该类加载,这部分相当于委托机制。
第二部分是部分细节:就是如果由该类自己加载该怎么加载。也就是findClass()部分。(这些老师上课说过一些)

loadClass()方法相当于采用了模板设计模式,
public abstract class ClassLoader{
private loadClass(){
....//loadClass()中的主要流程
findClass();//loadClass()中的部分细节。
}
public abstract findClass();
}

所以我们自定义加载器只需复写ClassLoader类中的findClass()方法就行了~~

主要方向:loadClass()-->findClass(String name)-->defineClass(String name,byte[] bytes, off, len)


作者: fengzhiku    时间: 2013-7-26 13:53
杨玉辉 发表于 2013-4-9 10:43
就最近的理解情况,希望能给你的帮助
loadClass();是加载 类名.class 字节码文件的工具

虽然loadClass和findClass我不是很清楚你说得是否是对的,但是defineClass显然你理解是错误的,defineClass是将符合class文件格式的字节数组加载到内存当中,从而生成class对象。而不是像你说得生成字节码文件,而defineClass的好处就是类加载器不需要管你的class是怎么来的,你可以从网络中获取,也可以从本地文件中获取,你只要提供符合class格式的字节数组,它就能正确的生成class对象
作者: diedie123    时间: 2018-4-20 00:05
做下源码注释的搬运工。
  ClassLoader loader = new NetworkClassLoader(host, port);
*   Object main = loader.loadClass("Main", true).newInstance();
  * <blockquote><pre>
*     class NetworkClassLoader extends ClassLoader {
*         String host;
*         int port;
*
*         public Class findClass(String name) {
*             byte[] b = loadClassData(name);
*             return defineClass(name, b, 0, b.length);
*         }
*
*         private byte[] loadClassData(String name) {
*             // load the class data from the connection
*             &nbsp;.&nbsp;.&nbsp;.
*         }
*     }
* </pre></blockquote>
总结下就是李罡说的对,这里需要理解的是loadClass返回一个是java.lang.class的实例,findClass里获得二进制字节数组,并调用defineClass方法生成java.lang.class的实例。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2