类加载器分析(高新技术)

类加载器分析


一、类加载器

1、什么是类加载器?

    加载类的工具,当程序需要的某个类,那么需要通过类加载器把类的二进制加载到内存中,类加载器也是Java类

2、类的加载过程

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
加载: 
就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。
连接:
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
初始化: 这里就不细说了。。。


3、类初始化时机

创建的时机有下面6种情况
a.创建类的实例
b.访问类的静态变量,或者为静态变量赋值
c.调用类的静态方法
d.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
e.初始化某个类的子类
f.直接使用java.exe命令来运行某个主类

4、java.lang.ClassLoader类介绍

java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class类的一个实例。

ClassLoader提供了一系列的方法,比较重要的方法如:



5、类加载器的树状组织结构

Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。

5.1、系统提供的类加载器

系统提供的类加载器主要有下面三个:
引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,比如System,String等,是用原生代码(C++)来实现的,并不继承自java.lang.ClassLoader
扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。 可以通ClassLoader.getSystemClassLoader()来获取它。

5.2、Java 应用开发人员编写的类加载器

属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。除了引导类加载器之外,所有的类加载器都有一个父类加载器。通过 上面表中给出的 getParent()方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java 类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。
下图中给出了一个典型的类加载器树状组织结构示意图。



5.3、演示类加载器的树状组织结构

package cn.wangjing_10;


public class ClassLoaderTree {


	public static void main(String[] args) {
		ClassLoader loader = ClassLoaderTree.class.getClassLoader();
		while (loader != null) {
			System.out.println(loader.toString());
			loader = loader.getParent();
		}
	}
}

程序输出结果是:
sun.misc.Launcher$AppClassLoader@1c0ec97
sun.misc.Launcher$ExtClassLoader@ecb281


6、类加载器的委托机制:

        1>当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
①首先当前线程的类加载器去加载线程中的第一个类.
②如果类A中引用了类B,Java虚拟机将使用加载类A的类加载器加载类B
③还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类.
        2>每个类加载器加载类时,又先委托给其上级类加载器.
            ①当所有祖宗类加载器没有加载到类,回到发起者类加载器,如果还加载不了,则抛出ClassNotFoundException异常,它不会 去找发起者类加载器的儿子,因为没有getChild()方法,即使有,有那么多的儿子交给那一个呢?所以干错就不叫给儿子处理了.委托机制有什么好处?集中管理,如果我们写了几个类加载器,都去加载某个类,那么内存中就有多份这个类的字节码。 能不能自己写一个类叫java.lang.System?为了不让我们写System类,类加载采用委托机制,这样可以保证爸爸优先,也就是使用的永远是爸爸的(系统的)System类,而不是我们写的System类.

7、自定义类加载器演示

public class People {
	public void say(){
        System.out.println("hello world!");
    }
}

class MyClassLoader extends ClassLoader {
    //类加载器的名称
    private String name;
    //类存放的路径
    private String path = "C:\\eclipse_workplace1\\File\\src\\cn\\wangjing_10\\";
 
    MyClassLoader(String name) {
        this.name = name;
    }
     
    MyClassLoader(ClassLoader parent, String name) {
        super(parent);
        this.name = name;
    }
    /**
     * 重写findClass方法
     */
    @Override
    public Class<?> findClass(String name) {
        byte[] data = loadClassData(name);
        return this.defineClass(name, data, 0, data.length);
    }
    public byte[] loadClassData(String name) {
        try {
            name = name.replace(".", "//");
            FileInputStream is = new FileInputStream(new File(path + name + ".class"));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int b = 0;
            while ((b = is.read()) != -1) {
                baos.write(b);
            }
            return baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

public class ClassLoaderTest {
	 
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        //新建一个类加载器
        MyClassLoader cl = new MyClassLoader("myClassLoader");
        //加载类,得到Class对象
        Class<?> clazz = cl.loadClass("classloader.Animal");
        //得到类的实例
        People people=(People) clazz.newInstance();
        people.say();
    }
 
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值