JVM加载class文件的原理

阅读:307 2019-03-19 14:42:03 来源:新网

当java编译器编译(javac)为.class文件后,我们需要将class加载到jvm当中。

1、jvm加载类的过程。当我们执行一个java程序时。(1)、java.exe会帮助我们找到jre,接着找到jre内部的jvm.dll。这才是真正的java虚拟机,最后机载动态库,激活java虚拟机。(2)、虚拟机激活以后,会先做一些初始化的动作,不如读取系统参数等。一旦初始化动作完成后,就会产生第一个类装载器--bootstraploader(启动类装载器)。(3)、bootstraploader所做的初始化工作中,除了一些基本的初始化动作外,最重要的就是加载launcher.java之中的extclassloader(扩展类装载器),并将其的parent设为null,代表其父加载器为bootstraploader。(4)、然后bootstraploader再要求加载launcher.java之中的appclassloader(用户自定义类装载器),并设定其parent为之前产生的extclassloader实体。这两个加载器都是以静态类的形式存在的。launcher$extclassloader.class与launcher$appclassloader.class都是由bootstraploader所加载,所以parent和由哪个类加载器加载无关。2、类加载器体系结构jvm加载class文件必须通过一个叫做类装载器的程序。(1)、bootstrapclassloader:启动类加载器,负责加载存放在%java_home%lib目录中的,并且被java虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库,即使放在制定路径中也不会被加载)类库到虚拟机的内存中,启动类加载器无法被java程序直接引用。(2)、extensionclassloader:扩展类加载器。由sun.misc.launcher$extclassloader实现,负责加载%java_home%libext目录中的类库,开发者可以直接使用扩展类加载器。(3)、applicationclassloader:应用程序类加载器,由sun.misc.launcher$appclassloader实现,负责加载用户类路径classpath上所指定的类库,是类加载器classloader中的getsystemclassloader()方法的返回值,开发者可以直接使用此加载器。如果程序中没有自定义过类加载器,该加载器就是程序中默认的类加载器。注:上述三个jdk提供的类加载器虽然是父子类加载器关系,但是没有使用继承,而是使用了组合关系。3、双亲委派模式(parentsdelegationmodel)(双亲并不是两个。而是父类们。。)用户自定义类装载器经常依赖其他类装载器--至少依赖虚拟机启动时创建的启动装载器来帮助他实现一些类装载请求。在版本1.2之后,类装载器请求另一个类装载器来装载类型的过程被形式化,称为双亲委派模式。除启动类装载器之外的每一个类装载器,都有一个'双亲'类装载器,在某个特定的类装载器试图已常用方式装载类型以前,它会先默认的将其分配给它的双亲-请求它的双亲来装载这个类型。这个双亲再一次请求他的双亲来装载这个类型。这个委派的过程一直向上继续,直到达到启动类装载器。packagetest;importjava.net.url;importjava.net.urlclassloader;publicclassclassloadertest{privatestaticintcount=-1;publicstaticvoidtestclassloader(objectobj){if(count<0&&obj==null){system.out.println("inputobjectisnull";return;}classloadercl=null;if(obj!=null&&!(objinstanceofclassloader)){cl=obj.getclass().getclassloader();}elseif(obj!=null){cl=(classloader)obj;}count++;stringparent="";for(inti=0;i以上例程的输出为:classloadername=java.net.urlclassloaderparentclassloadername=sun.misc.launcher$appclassloaderparentparentclassloadername=sun.misc.launcher$extclassloaderparentparentparentclassloadername=bootstrapclassloader4、由于是找到最上层的加载器来加载所以当类重复时会不会加载我们自定义的类的。packagejava.lang;publicclassstring{publicstaticvoidmain(string[]args){}}java.lang.nosuchmethoderror:mainexceptioninthread"main"结论:我们当然可以自定义一个和api完全一样的类,但是由于双亲委托模型,使得我们不可能加载上我们自定义的这样一个类。所以j2se规范中希望我们自定义的包有自己唯一的特色(网络域名)。还有一点,这种加载器原理使得jvm更加安全的运行程序,

相关文章
{{ v.title }}
{{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
你可能感兴趣
推荐阅读 更多>
推荐商标

{{ v.name }}

{{ v.cls }}类

立即购买 联系客服