大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> JSP专区 -> 初探Java类加载机制

初探Java类加载机制

时间: 2021-07-31 作者:daque

一、在jdk1.2此后,类加载是经过委派来实行的,这表示着即使 classloader 不许找到类,它会乞求父代 classloader 来实行此项工作,一切 classloaders 的根是体例 classloader,它会以缺省办法装入类 -- 即,从当地文献体例。即日咱们就来商量一下在jvm中那些体制是还好吗运转的。让咱们假如有一个class字节码文献(比方hello.class文献),那么在运用步调中,他是怎样被加载进入,并产生一个类东西的呢?咱们这篇作品的手段即是为领会释这个题目。   在java.lang包里有个classloader类,classloader 的基础目的是对类的乞求供给效劳。当 jvm 须要运用类时,它按照称呼向 classloader 乞求这个类,而后 classloader 试图归来一个表白这个类的 class 东西。经过掩盖对应于这个进程各别阶段的本领,不妨创造定制的 classloader。个中有个loadclass(string name, boolean resolve)本领,该本领为classloader的进口点,在jdk1.2此后,loadclass本领将缺省挪用findclass本领,精细实质不妨参考api文书档案,咱们编写的classloader重要即是为了掩盖之上两个本领。回到咱们方才的题目,还好吗读进字节码文献,并把它形成一个类东西呢?在classloader里有个本领,class defineclass(string name, byte[] b, int off, int len),谜底就在这边了,咱们按照把class字节码文献(如hello.class)读进一个字节数组里,byte[] b,并把它变化为class东西,而那些数据不妨根源于文献,搜集等,神秘吧:)   defineclass处置 jvm 的很多搀杂、神奇和依附于实行的上面 -- 它把字节码领会成运转时数据构造、校验灵验性之类。不用担忧,您无需亲身编写它。究竟上,纵然您想要这么做也不许掩盖它,由于它已被标志成最后的。   其余少许本领:   findsystemclass本领:从当地文献体例装入文献。它在当地文献体例中探求类文献,即使生存,就运用 defineclass 将原始字节变换成 class 东西,以将该文献变换成类。   findclass本领:jdk1.2此后loadclass 的缺省实行挪用这个新本领。findclass 的用处包括您的 classloader 的一切特出代码,而无须要复制其它代码(比方,当特意的本领波折时,挪用体例 classloader)。   getsystemclassloader: 即使掩盖 findclass 或 loadclass,getsystemclassloader 使您能以本质 classloader 东西来考察体例 classloader(而不是恒定的从 findsystemclass 挪用它)。   getparent:为了将类乞求委派给父代 classloader,这个新本领承诺 classloader 获得它的父代 classloader。当运用特出本领,定制的 classloader 不许找到类时,不妨运用这种本领。   resolveclass: 不妨不实足地(不带领会)装入类,也不妨实足地(带领会)装入类。当编写咱们本人的 loadclass 时,不妨挪用 resolveclass,这在于于 loadclass 的 resolve 参数的值。   findloadedclass:充任一个缓存,当乞求 loadclass 装入类时,它挪用该本领来察看 classloader 能否已装入这个类,如许不妨制止从新装入已生存类所形成的烦恼。应开始挪用该本领。   二、处事过程:   1)挪用 findloadedclass(string) 来察看能否生存已装入的类,即使没有,那么沿用那种特出的神秘办法来获得原始字节。   2)经过父类classloader挪用loadclass本领,即使父类classloader是null,那么按缺省办法装入类,即体例classloader。   3)挪用findclass(string)去搜索类并获得类;   4)即使loadclass 的 resolve 参数的值为true,那么挪用 resolveclass 领会 class 东西.   5)即使还没有类,归来 classnotfoundexception。   6)要不,将类归来给挪用步调。   三、一个实行了classloader的例子:   /**   *compilingclassloader.java   *copyright 2005-2-12   */   import java.io.*;   public class compilingclassloader extends classloader{   //读取一个文献的实质   private byte[] getbytes(string filename) throws ioexception{   file file=new file(filename);   long len=file.length();   byte[] raw=new byte[(int)len];   fileinputstream fin=new fileinputstream(file);   int r=fin.read(raw);   if(r!=len) throw new ioexception("can't read all,"+r+"!="+len);   fin.close();   return raw;   }   private boolean compile(string javafile) throws ioexception{   system.out.println("ccl:compiling "+javafile+"...");   //挪用体例的javac吩咐   process p=runtime.getruntime().exec("javac "+javafile);   try{   //其余线程都等候这个线程实行   p.waitfor();   }catch(interruptedexception ie){   system.out.println(ie);   }   int ret=p.exitvalue();   return ret==0;   }   public class loadclass(string name,boolean resovle) throws classnotfoundexception{   class clas=null;   clas=findloadedclass(name);   //这边说领会包的表白   string filestub=name.replace('.','/');   string javafilename=filestub+".java";   string classfilename=filestub+".class";   file javafile=new file(javafilename);   file classfile=new file(classfilename);   //即使生存class文献就不编写翻译   if(javafile.exists()&&(!classfile.exists()||javafile.lastmodified()>classfile.lastmodified())){   try{    if(!compile(javafilename)||!classfile.exists()){     throw new classnotfoundexception("classnotfoundexcetpion:"+javafilename);    }   }catch(ioexception ie){    throw new classnotfoundexception(ie.tostring());   }   }   try{   byte[] raw=getbytes(classfilename);   //经过读入数据来结构一个类构造,这是中心   clas=defineclass(name,raw,0,raw.length);   }catch(ioexception ie){   //   }   if(clas==null){   clas=findsystemclass(name);   }   system.out.println("findsystemclass:"+clas);   if(resovle && clas!=null){   resolveclass(clas);   }   if(clas==null){   throw new classnotfoundexception(name);   }   return clas;   }   }   尝试该loader:   /**   *testrun.java   *copyright 2005-2-11   */   import java.lang.reflect.*;   public class testrun{   public static void main(string[] args) throws exception{   string progclass=args[0];   string progargs[]=new string[args.length-1];   system.arraycopy(args,1,progargs,0,progargs.length);   compilingclassloader ccl=new compilingclassloader();   class clas=ccl.loadclass(progclass);   //归来一个class的type   class[] mainargtype={(new string[0]).getclass()};   method main=clas.getmethod("main",mainargtype);   object argsarray[]={progargs};   main.invoke(null,argsarray);   }   }   之上的中心实质仍旧编写结束,编写翻译后,咱们获得两个文献:   compilingclassloader.class,testrun.class   四、编写一个例子,而后运转咱们的classloader   /**   *hello.java   */   public class hello{   public static void main(string[] args){   if(args.length!=1){    system.err.println("error,exit!");    system.exit(1);   }   string name=args[0];   system.out.println("hello,"+name);   }   }   好了,运转java testrun hello 阿飞   ....   ....   ....   hello,阿飞

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.