Java 类加载器 (一)

首先,可以简单地来看一下java类加载器以及反射机制如何来得到class loader。其次深入探究一下java类加载器。最后总结一下Java 的类加载器。

 

Java 类加载器和反射机制得到class loader

 

    JAVA 中类文件加载是动态的。JVM指令是被封装在了. class文件里面,而.class文件的加载过程是动态的,也就是说当我们用到的时候才会去加载,如果不用的话,就不会去加载我们的类。这里所说的用到包括两种 方式,第一种就是new一个对象的时候(这个时候要特别注意,当设计到多态的时候,就会有一点点变化,这时候编译器会做一些优化,这样以来当加载的时候会 提前加载设计到多态的类,关于这一点下面有个例子(example 1)来说明。另一种就是当一个类的静态代码被调用的时候。

 

运行此测试程序结果如Example1.1图 :
Example 1.1

 

当我们注释掉Example.1.1行时,运行Example1.2行,结果如下:

Example 1.2

 
分析以上两图的运行结果我们可以看出:当我们将子类对象赋值给父类时,编译器会做一点优化,于是加载器在还没有new 子类对象的时候已经加载了父类以及子类(example1.1结果),当不存在多态的时候,我们可以看到是当要new Dog()的时候才会加载Dog以及父类。无论何种方式,在new之前,类确实已经加载到了内存中。
      

      JAVA 为我们提供了两种动态机制。第一种是隐式机制。其实new一个对象和调用类的静态方法时,就是隐式机制在工作。第二种是显示机制。显示的机制又有两种策略(第一种是用java .lang.Class的forName(String str)方法,第二种是用java .lang.ClassLoader的loadClass())。
 
      第一种:利用forName方法
      当我们查API文档就会发现forName方法有两种形式。分别如下:
      public static Class<?> forName(String className)
                        throws ClassNotFoundException
    
     
      public static Class<?> forName(String name,
                               boolean initialize,
                               ClassLoader loader)
                        throws ClassNotFoundException

      先来说说第二种方法:第二个方法值得注意的就是第二个参数boolean initialize,如果我们把这个参数设置为false,那么当我们加载完类后就不会执行静态代码和静态的初始化动作。只有当我们new一个对象的时 候才会初始化。而第三个参数是用来指明类的加载器的。
      如果查看java .lang.Class类的源代码,上述两种方法最终都会调用Class类中的私有的native方法forName0(),此方法的声明如下:
      private static native Class forName0(String name, boolean  init , ClassLoader loader)
                  throws ClassNotFoundException;

所以当我们调用Class.forName(name )时,其实是在方法内部调用了:
                  forName0(name, true, ClassLoader.getCallerClassLoader());
    当我们调用Class.forName(name,  initialize, loader )的时候,实际上此方法内部调用了:
                 forName0(name, initialize, loader);
下面看一个例子,如果方法中第二个参数为false的情况:

 

Example2.1结果:

 

从上图可以看出来类加载完成后并没有立即执行静态初始化代码,而是到了实例化的时候才进行了静态初始化。有时候我们会说静态代码是在类第一次被加载时执行的,并且只执行一次。其实这是对与new一个对象,第一次访问类的静态代码以及第二个参数为true时而言的,对于动态的加载来说,如果forName方法的第二个参数设置为false,那么就是在实例化的时候才会执行静态初始化。当然默认情况下第二个参数是true.

第二种方法:利用Class对象获取的ClassLoader装载。

下面是一个简单的例子:

 

 

Example 2.2结果:

 

 

 

从上图可以看出loader完成以后并没有立即进行静态代码的执行。只有当newInstance()的时候才执行静态初始化,这和把
public static Class forName(String name, boolean initialize,  ClassLoader loader)的第二个参数指定为false的情况完全一样。其实每当我们写完一个编译单元以后就会得到一个.calss文件,这个文件中就包含了该类的 Class对象。JVM就是利用这个class对象来进行动态装载类的.

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值