一:jvm 虚拟机类加载机制

来源:互联网 发布:淘宝刷流量软件排名 编辑:程序博客网 时间:2024/06/06 02:08

    一:类的生命周期

                加载-->(验证 -->准备 -->解析)  

                                       连接(以上统称为连接)   -->初始化-->使用-->卸载

          (1)加载,验证,准备,初始化和卸载这个五个阶段顺序是确定的。但也不是完全依次进行,应该说是互相交叉混合进行。解析阶段则不一定。

          (2)类的初始化触发条件

                   首次主动使用的情形:

  •                                               创建某个类的新实例时--new、反射、克隆或反序列化;
  •                                                调用某个类的静态方法时;
  •                                                使用某个类或接口的静态字段或对该字段赋值时(final字段除外)
  •                                                调用Java的某些反射方法时
  •                                                初始化某个类的子类时
  •                                                 在虚拟机启动时某个含有main()方法的那个启动类。

                                                    除了以上几种情形以外,所有其它使用JAVA类型的方式都是被动使用的,他们不会导致类的初始化。

  二:类加载器

       Java虚拟机中类加载器:

         Java虚拟机中可以安装多个类加载器,系统默认三个主要的类加载器,每个类负责加载特定位置的类: 

        BootStrap(启动类加载器),ExtClassLoader(扩展类加载器),AppClassLoader(应用程序类加载器)

         类加载器也是Java类,因为Java类的类加载器本身也是要被类加载器加载的,显然必须有第一个类加载器不是Java类,这个正是BootStrap,使用C/C++代码写的,已经封装到JVM内核中了,而ExtClassLoader和AppClassLoader是Java类。

         应用程序都是三个类加载器相互配合加载的,也可以加入自己定义的类加载器。

    哈哈

       

loadClass方法的源代码:

[java] view plain copy
  1. public Class<?> loadClass(String name) throws ClassNotFoundException {  
  2.        return loadClass(name, false);  
  3.    }  
再来看一下loadClass(name,false)方法的源代码:

[java] view plain copy
  1. protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{  
  2.          //加上锁,同步处理,因为可能是多线程在加载类  
  3.          synchronized (getClassLoadingLock(name)) {  
  4.              //检查,是否该类已经加载过了,如果加载过了,就不加载了  
  5.              Class c = findLoadedClass(name);  
  6.              if (c == null) {  
  7.                  long t0 = System.nanoTime();  
  8.                  try {  
  9.                      //如果自定义的类加载器的parent不为null,就调用parent的loadClass进行加载类  
  10.                      if (parent != null) {  
  11.                          c = parent.loadClass(name, false);  
  12.                      } else {  
  13.                          //如果自定义的类加载器的parent为null,就调用findBootstrapClass方法查找类,就是Bootstrap类加载器  
  14.                          c = findBootstrapClassOrNull(name);  
  15.                      }  
  16.                  } catch (ClassNotFoundException e) {  
  17.                      // ClassNotFoundException thrown if class not found  
  18.                      // from the non-null parent class loader  
  19.                  }  
  20.   
  21.                  if (c == null) {  
  22.                      // If still not found, then invoke findClass in order  
  23.                      // to find the class.  
  24.                      long t1 = System.nanoTime();  
  25.                      //如果parent加载类失败,就调用自己的findClass方法进行类加载  
  26.                      c = findClass(name);  
  27.   
  28.                      // this is the defining class loader; record the stats  
  29.                      sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);  
  30.                      sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);  
  31.                      sun.misc.PerfCounter.getFindClasses().increment();  
  32.                  }  
  33.              }  
  34.              if (resolve) {  
  35.                  resolveClass(c);  
  36.              }  
  37.              return c;  
  38.          }  
  39.      }  
在loadClass代码中也可以看到类加载机制的原理,这里还有这个方法findBootstrapClassOrNull,看一下源代码:

[java] view plain copy
  1. private Class findBootstrapClassOrNull(String name)  
  2.    {  
  3.        if (!checkName(name)) return null;  
  4.   
  5.        return findBootstrapClass(name);  
  6.    }  

就是检查一下name是否是否正确,然后调用findBootstrapClass方法,但是findBootstrapClass方法是个native本地方法,看不到源代码了,但是可以猜测是用Bootstrap类加载器进行加载类的,这个方法我们也不能重写,因为如果重写了这个方法的话,就会破坏这种委托机制。

参考书:深入理解jvm虚拟机

原创粉丝点击