现在的位置: 首页 > 综合 > 正文

ClassLoader类加载器

2018年04月04日 ⁄ 综合 ⁄ 共 2029字 ⁄ 字号 评论关闭
文章目录

ClassLoader

  .

JVM结束生命周期

1.       System.exit(0)  正常退出

System.exit(-1)  非0异常退出

2.       正常运行结束

3.       发现异常或错误退出

4.       操作系统退出

 

class二进制文件的加载过程

1.       class二进制文件加载到内存

2.       连接

A.     验证文件的正确性,防止恶意修改

B.      类的静态成员设为默认值,即int(0) , boolean(false), Object(null)

C.      解析,即把类中的符号引用转换成直接的引用(指针,内存地址)

3.       静态初始化: 静态变量初始化为正确的值(即静态初始化代码段里的语句)

文件名: clip_image001.png , 字节: 7606

主动使用

1.       Test t = new Test() ;

2.       使用了静态变量:   Test.A ;

3.       使用了静态方法    Test.do() ;

4.       反射出一个对象    Object  t = Class.forName(“Test”);

5.       New 了Test的子类

6.       程序的启动类

 

除此6种处,其它的都是被动使用,被动使用不会导致类的重新加载,也就不会导致类的初始化,即不会执行

static {
       .....
}

 

类的加载

指的是将类的class文件中的二进制数据读到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来描述该类的数据结构(如方法Method, 属性Field)

1.  本地class文件加载

2.  Zip,jar文件中加载

3.  网络加载(java.lang.URLClassLoader)

4.  专用数据库中加载

5.  Java源文件动态加载

文件名: clip_image003.png , 字节: 10359

类加载器

系统自带的ClassLoader

A.     根类加载器 Bootstrap (C++实现)

B.      扩展类加载器 Extension (java实现)

C.      系统(应用)类加载器 (java实现, 如AppClassLoader)

 

用户自定义的ClassLoader

继承java.lang.ClassLoader类,重写findClass方法

如:

public class MyClassLoader extends ClassLoader {

       @Override

       protected Class<?> findClass(String name) throws ClassNotFoundException {

              byte[] buf = getClassData("");

              return this.defineClass(name, buf, 0,buf.length); 

       }

       //从某处把.class文件的内容读取成为一个byte[]

       private byte[] getClassData(String name){

              return new byte[100];
       }    
}

 

接受ClassLoader作为参数的例子:

invocationHandler. newProxyInstance( classloader, interfaces................);

 

JVM加载类加载器

类加载器不需要某个类被“首次主动使用”的时候加载它。JVM允许类加载器在预料到某个类将在被使用时加载。

当加载出现错误时,先隐藏,直到主动使用该类的时候才报告。如果一直不主动使用该类,则错误一直不报告.

 

类初始化步骤

1.       如果类还没加载和连接,则先加载和连接

2.       如果存在父类,则先加载父类

3.       如果有静态初始化,则从上到下初始化

4.       注意事项:

a)       编译时常量(即编译的时候就能确定它的值的常量)

public static final int A =1主动使用时不会对类进行初始化

b)      运行时的常量(即在运行的时候才能确定它的值的常量)

public static final int A = new Ramdon().nextInt(10);主动使用时会对类进行初始化

c)       初始化类时,不会初始化它所实现的接口。初始化接口时,不会初始它的父接口,当首次使用接口的静态变量时,才会初始化

d)      只有当访问的静态变量(方法)确定在当前类(接口)中定义时,才可以认为是对该类或接口的主动使用

Test.A   Test.do()时,只有当Ado()是在Test类定义的,才算是主动使用

classLoader. loadClass(“java.lang.String”) 这样加载的类不是主动使用

 

父亲委托机制

总是委托父加载器去加载一个类,能加载则加载,不能加载则用子类加载。父子加载器之间不一定是继承关系,很多都是组合关系。每个加载器有且只有一个父加载器。

子加载器加载的类能看到父加载器所加载的类,反之则不行

运行时包:类名,包名相同,并且加载器也要相同。同一个运行包里的类才能随意访问,但通过反射可突破这一限制

文件名: clip_image005.png , 字节: 41987

 

 

 

【上篇】
【下篇】

抱歉!评论已关闭.