Java类的加载、链接和初始化

来源:互联网 发布:我的世界js大全。 编辑:程序博客网 时间:2024/04/28 10:44
     
     Java字节码表现形式是二进制数组byte[],而在jvm中为java.lang.Class对象
     一个Java类从字节码到能够在jvm中被使用,需要经过加载、链接和初始化,而我们可见的只有类的加载这一过程,我们可以利用类加载器在程序运行时刻动态的去加载一个类,在一个类使用之前链接和初始化已经完成
     
     Java类的加载
     类加载器分为两类:启动类加载器(bootstrap)和用户自定义的类加载器(user-defined)
bootstrap由jvm的原生代码实现,user-defined类加载器继承自java.lang.ClassLoader,jvm会帮我们提供一些基本的实现
     Java类加载器两个比较重要的特征:层次组织结构和代理模式
     每个类加载器都有一个父类加载器,父-子组成了一个树状结构
     一个类加载器去定义某个Java类时可以代理给其他的类加载器来完成,启动一个类的加载的类加载器和定义一个类的类加载器不同,一个类的定义类加载器是这个类引入的其他类的初始类加载器
     一般的类加载器当尝试去加载某个类之前,会首先代理给其父类加载器,当父类加载器加载不到时,才会去自己加载,这部分的逻辑封装在loadClass()方法中,父类优先原则往往比较好了,但有些地方可能会采取相反的策略,Java的web容器中采用这种做法
     类加载器的一个重要用途是为相同名称的Java类创建隔离空间,在jvm中判断两个类是否相同不仅是根据二进制名称还会根据定义类的类加载器是否相同,这种机制可以为相同名称的类的不同版本共存

     Java类的链接
     java类的链接指的是把java类的二进制代码合并到jvm的运行状态之中。前提是类必须先被成功加载,链接包括验证、准备和解析,验证是确保类的二进制代码在结构上是否完全正确,准备是对类的静态域进行创建并赋予默认值,准备过程并不会执行代码;解析是确保类引入的其他类能够被找到,解析的过程可能会导致引入的类被加载
     
     public class LinkTest{
          public static void main(String[] args){
               ToBeLinked toBeLinked = null;
          }
     }
     
     LinkTest引用了ToBeLinked类,声明了一个变量,但没有访问ToBeLinked中的静态域或方法,ToBeLinked类没有使用到,所以ToBeLinked并没有加载

     Java类的初始化
     当一个类被使用到时会对静态代码块和静态域(安装顺序)进行初始化,当访问一个类或接口的静态域时,只有真正声明这个静态域的类或接口会被初始化,如下代码A类并不会被初始化
     public class InitTest {

//     public static String a = "a";
//     
//     static{
//           a = "b";
//     }
       
        public static void main(String[] args){
             
             System. out.println(B.b);
       }
       

}
class A{
        public static String b = "a";
        static{
             System. out.println(b );
       }
}
class B extends A{
        public static String b = "b";
        static{
             System. out.println(b );
       }
}


     创建自己的类加载器
     典型场景:实现特定的字节码查找方式、对字节码进行加密和解密、隔离同名类
     只需继承java.lang.ClassLoader类,实现特定的方法
     
     
     常见模式
     public class InitTest extends java.lang.ClassLoader{

        @Override
              protected Class<?> findClass(String name) throws ClassNotFoundException {
                     byte[] b = null ;//类的字节代码
                     return defineClass(name,b,0,b. length);
             }
     }
原创粉丝点击