您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > java加载机制整理
java加载机制整理本文是根据李刚的《疯狂讲义》作的笔记,程序有的地方做了修改,特别是路径,一直在混淆,浪费了好多时间!!希望懂的同学能够指导本人,感激尽。。。。。。。。。。。。1.jvm和类的关系当调用java命令运行一个java程序时,必会启动一个jvm即java虚拟机。(5.6.处有联系!!)该java程序的所有线程,变量都处于jvm中,都使用该jvm的内存区jvm终止的情况:1.程序自然运行结束2.遇到System.exit();Runtime.getRuntime.exit();3.遇到未捕获异常或错误时4.程序所在的平台强制结束了JVM进程jvm终止,jvm内存中的数据全部丢失。举例:定义一个类,包含静态变量classAClass{publicstaticinta=1;}使变量自加复制代码publicclassATest{publicstaticvoidmain(String[]args){AClass.a++;System.out.println(a的值:+AClass.a);//输出:a的值:2}}复制代码另起一类,查看变量变化情况publicclassATest2{publicstaticvoidmain(String[]args){System.out.println(a的值:+AClass.a);//输出:a的值:1}}从输出对比可知,虽然ATest1自加,改变的类变量a的值,但是ATest1与ATest2处于不用的JVM中,当ATest1结束时,对a的修改都丢失了2.类的加载类的加载又称为类的初始化,实际上可细分为类的加载、连接、初始化。下面将讲述着三个阶段的过程!类的加载指.class文件读入内存,并为之创建一个java.lang.Class对象类加载,是通过类加载器来完成的,类加载器通常由JVM提供,通常称为系统类加载器(也可以是自己写的加载器,只要继承ClassLoader基类)。类加载无须等到“首次使用该类”时加载,jvm允许预加载某些类。。。。加载来源:1.本地.class文件2.jar包的.class文件3.网络.class文件4.把一个java源文件动态编译,加载3.类的连接负责把类的二进制数据合并到JRE(java运行环境)中1.验证检测被加载的类是否有正确的内部结构,并和其他类协调一致2.准备负责为类的类变量(非对象变量)分配内存,并设置默认初始值3.解析将类的二进制数据中的符号引用替换成直接引用。。(staticfinal好像跟这个有点关系????5.6.处有联系)4.类初始化主要对类变量(而非对象变量)的初始化声明类变量的初始值=静态初始化块他们是相同的,等效的。都会被当成类的初始化语句,JVM会按照这些语句在程序中的顺序依次执行他们复制代码publicclassTest{staticinta=5;//初始化时赋值staticintb;//初始化时赋值--静态块staticintc;//连接时赋默认值值static{b=6;}publicstaticvoidmain(String[]args){System.out.println(a);System.out.println(b);System.out.println(c);}复制代码输出:JVM初始化一个类包含如下几个步骤:1.假设类还没有被加载和连接,那么先加载和连接该类2.假设该类的父类还没被初始化,那么先初始化父类----jvm总是最先初始化java.lang.Object类3.假设类中有初始化语句,则一次执行这些初始化语句当程序主动使用任何一个类时,系统会保证该类以及所有父类(直接父类和间接父类)都会被初始化5.类初始化的时机:1.创建类的实例。new,反射,反序列化2.使用某类的类方法--静态方法3.访问某类的类变量,或赋值类变量4.反射创建某类或接口的Class对象。Class.forName(Hello);---注意:loadClass调用ClassLoader.loadClass(name,false)方法,没有link,自然没有initialize5.初始化某类的子类6.直接使用java.exe来运行某个主类。即cmdjava程序会先初始化该类。复制代码classTester{publicstaticintvalue=10;publicstaticStringname;publicstaticvoidmethod(){System.out.println(一个类方法);}static{System.out.println(Tester的类的静态初始化。。。);}}publicclassClassLoadTest{staticStringclassPath=Chapter18.Tester;publicstaticvoidmain(String[]args)throwsClassNotFoundException,Exception,IllegalAccessException{ClassLoadercl=ClassLoader.getSystemClassLoader();Class?a=cl.loadClass(classPath);//用到了Tester类加载一个类,并不会导致一个类的初始化/*初始化的时机*///调用newInstance()方法a.newInstance();//输出:____________静态块加载//使用Class.forName方法Class.forName(classPath);//输出:____________静态块加载//调用类变量intvalue=Tester.value;Tester.name=jason;//输出:____________静态块加载//调用类方法Tester.method();//输出:____________静态块加载一个类方法//new实例化Testt=newTest();//输出:____________静态块加载}}复制代码特殊情形:final类型的类变量,如果在编译时(转成.class文件)就可以确定,那么这个类变量就相当于“宏变量”,编译时,直接替换成值。所以,即使使用这个类变量,程序也不会导致该类的初始化!!----相当于直接使用常量复制代码publicclassTest{publicstaticvoidmain(String[]args){System.out.println(aClass.A);}}classaClass{staticfinalintA=111;//可以确定static{System.out.println(静态块初始化);}}复制代码输出:111复制代码publicclassTest{publicstaticvoidmain(String[]args){System.out.println(aClass.A);}}classaClass{staticfinallongA=System.currentTimeMillis();//在编译时无法确定static{System.out.println(静态块初始化);}}复制代码输出:静态块初始化1468309845203使用ClassLoader类的loadClass方法来加载类时,只是加载该类,而不会执行该类的初始化!!使用Class的forName()静态方法,才会导致强制初始化该类。6.类加载器类加载器负责加载所有的类,为被加载如内存中的类生成一个java.lang.Class实例。一旦类被载入内存,同一个类就不会再加载第二次如何判断是同一个类:java中一个类用其全限定类名标示--包名+类名jvm中一个类用其全限定类名+加载器标示---包名+类名+加载器名加载器层次结构:JVM启动时,姓曾的三个类加载器组成的机构1.BootstrapClassLoader根类------引导类加载器,加载java核心类。非java.lang.ClassLoader子类,而是JVM自身实现2.ExtensionClassLoader扩展类-----加载JRE的扩展目录中的JAR包的类(%JAVA_HOME%/jre/lib/ext或java.ext.dirs系统属性指定的目录)3.SystemClassLoader系统类-----加载cmdjava-cp**,环境变量指定的jar包和类路径。ClassLoader.getSystemClassLoader获得系统类加载器。4.用户类加载器。。。复制代码publicclassBootstrapTest{publicstaticvoidmain(String[]args){//获取根类加载器所加载的全部URL数组URL[]urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();//无需理会警告//遍历输出根类加载器加载的全部URLfor(inti=0;iurls.length;i++){System.out.println(urls[i].toExternalForm());}}}复制代码输出:file:/C:/Program%20Files/Java/jre1.8.0_20/lib/resources.jarfile:/C:/Program%20Files/Java/jre1.8.0_20/lib/rt.jarfile:/C:/Program%20Files/Java/jre1.8.0_20/lib/sunrsasign.jarfile:/C:/Program%20Files/Java/jre1.8.0_20/lib/jsse.jarfile:/C:/Program%20Files/Java/jre1.8.0_20/lib/jce.jarfile:/C:/Program%20Files/Java/jre1.8.0_20/lib/charsets.jarfile:/C:/Program%20Files/Java/jre1.8.0_20/lib/jfr.jarfile:/C:/Program%20Files/Java/jre1.8.0_20/classes7.类的加载机制:1.全盘负责。某类以及其所依赖的所有类,都由一个加载器负责加载。除非显示使用另外一个加载器。2.父类委托。先父类加载器加载改Class,不行后,才尝试从自己的类路径中加载该类3.缓存机制。缓存机制将会保证所有加载过的Class都会被缓存。。当程序需要Class时,先从缓存区中寻找Class对象,没有的话,才加载该类的.class对象。8.访问类加载器复制代码publicstaticvoidmain(String[]args)throwsIOException{ClassLoadersystemLoader=ClassLoader.getSystemClassLoader();//getsystemloader获得系统的类加载器System.out.println(系统类加载器:+systemLoader);/**获取系统类加载器的加载路径--通常由CLASSPATH环境变量指定,*如果,操作系统没有指定CLASSPATH环境变量,则默认以当前路径作为系统类加载器的家在路径*/EnumerationURLeml=systemLoader.getResources();while(eml.hasMore()){System.out.println(SYSTEMClassLoaderRoute:+eml.nextElement());//系统类加载器的加载路径是程序运行的当前路径}//获取系统类加载器的父类加载器,得到扩展类加载器ClassLoaderextenionLoader=systemLoader.getParent();System.out.println(扩展类加载器:+extenionLoader);System.out.pri
本文标题:java加载机制整理
链接地址:https://www.777doc.com/doc-2880745 .html