JVM-类加载器

类加载器

  对于虚拟机的角度来拘禁,只存在个别种植恍若加载器:
启动类加载器(Brootstrap
ClassLoader)和“其他类似加载器”。启动类加载器是出于C++写的,属于虚拟机的一样片段,其他类加载器都是由java语言实现,独立为虚拟机外部,全体继续自抽象类java.lang.ClassLoader。

  从出的角度来拘禁,有两种植类似加载器:

  1)启动类加载器(Bootstrap
ClassLoader):这些类似加载器首如若承担加载${JAVA_HOME}/lib目录的jar(比如rt.jar、resources.jar)或者被-Xbootclasspath参数所指定的路中之jar。

  (调用ClassLoader类的loadClass方法加载一个好像,并无是对类的积极向上下,不相会导致类似的开始化。)

  2)增加类加载器(Extension
ClassLoader):它承担加载${JAVA_HOME}/lib/ext目录或者被java.ext.dirs系统变量所指定的门路中之兼具类库,开发者可以一直动用扩大类加载器。

  3)应用类加载器(Application
ClassLoader):这些仿佛加载器是ClassLoader中之getSystemClassLoader()方法的回值,所以又给系统类加载器。它当加载用户类路径(ClassPath)上所指定的类库。

  仿佛加载器的层次结构:

  Bootstrap 1                     
          Bootstrap 2                 
        

 ClassLoader加载类的规律:

  ClassLoader使用的凡老人委托模型来搜索类的,每个ClassLoader实例都出一个父类加载器的援(不是延续的关系,是一个含有的涉),虚拟机内置的类加载器(Bootstrap
ClassLoader)本身没有父类加载器,但足据此作其余ClassLoader实例的底父类加载器。当一个ClassLoader实例需要加载某个类时,它会准备亲自搜索某个类在此之前,先把此职责委托为她的父类加载器,这多少个过程是贯穿依次检查的,首先由最顶层的好像加载器Bootstrap
ClassLoader试图加载,虽然无加载到,则把任务转交给Extension
ClassLoader试图加载,如果也绝非加载到,则转交给App ClassLoader
举办加载,假如其也远非加载得到的话,则归给寄的发起者,由它到指定的文件系统或网络等URL中加载该类。假诺她还没有加载到这些类似时,则抛出ClassNotFoundException分外。否则将那找到的类生成一个类的定义,并以她加载到内存当中,最终回来那几个类似在内存中的Class实例对象。

 为何要为此家长委托模型:

  因为如此可免重新加载,当大早就加载了此类的早晚,就无必要子ClassLoader再加载一遍等。考虑到平安因素,大家试想一下,如果未使这种委托情势,这我们不怕得每日使用自定义之String来动态替代java主题api中定义的连串,这样会设有相当坏之安全隐患,而父母委托的计,就可以免这种意况,因为String已经于启动时尽管为指导类加载器(Bootstrcp
ClassLoader)加载,所以用户从定义之ClassLoader永远也无力回天加载一个要好写的String,除非您转移JDK中ClassLoader搜索类的默认算法。

JVM在搜索类的下,是怎么判定六只class是千篇一律的也?

  相比较简单单近乎是否“相等”,唯有这有限只类似是由于和一个接近加载器加载的前提下才发生义,否则,尽管那点儿个像样来自和一个.class文件,被和一个虚拟机加载,只要加载他们之近乎加载器不同,那有限独八九不离十即必不顶。这里的相当于包括Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的回到结果,也囊括instanceof关键字做靶子所属涉判定等情事。例如,我们得编制一个类似加载器,它好拒绝加载没有标记为”paid
for”的类似。

  假如假如编制好之接近加载器,只需要持续抽象类 ClassLoader
然后再写findClass()方法。ClassLoader 中之 loadClass()方法用于将类的加载操作委托为这父类加载器去开展,惟有当该类尚未加载并且父类加载器也无从加载该类时,才调用findClass()方法。

  

于定义类加载器

  咱们得编制好之用来特殊目标的切近加载器,这叫我们可于通往虚拟机传递字节码往日实施定制的反省。

 

import java.io.*;

/**
 *  @ProjectName: base-project 
 *  @Description: 实现自己的类加载器
 */
public class MyClassLoader extends ClassLoader {
    private String name; //类加载器的名字
    private String path = "D:\\"; //加载类的路径
    private final String fileType = ".class"; //class文件的扩展名

    public MyClassLoader(String name) {
        super();
        this.name = name;
    }

    public MyClassLoader(ClassLoader parent, String name) {
        super(parent);
        this.name = name;
    }

    @Override
    public String toString() {
        return "MyClassLoader{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] data = loadClassData(name);
        return defineClass(name, data, 0, data.length);
    }

    private byte[] loadClassData(String name) {
        InputStream is = null;
        byte[] data = null;
        ByteArrayOutputStream baos = null;

        try {
            this.name = this.name.replace(".", "\\");
            //流读取文件
            is = new FileInputStream(new File(path + name + fileType));
            baos = new ByteArrayOutputStream();
            int ch = 0;
            while(-1 != (ch = is.read())) {
                baos.write(ch);
            }

            data = baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                baos.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return data;
    }

    public static void test(ClassLoader loader) throws Exception{
        Class clazz = loader.loadClass("Sample");
        Object object = clazz.newInstance();
    }

    public static void main(String[] args) throws Exception {
        MyClassLoader loader1 = new MyClassLoader("loader1");
        loader1.setPath("D:\\myapp\\serverlib\\");
        MyClassLoader loader2 = new MyClassLoader(loader1, "loader2");
        loader2.setPath("D:\\myapp\\clientlib\\");
        MyClassLoader loader3 = new MyClassLoader(null, "loader3");
        loader3.setPath("D:\\myapp\\otherlib\\");

        test(loader2);
//        System.out.println("==================");
        test(loader3);

//        Class clazz = loader1.loadClass("Sample");
//        Object obj = clazz.newInstance(); //创建一个Sample类的对象
//        Sample sample = (Sample)obj;
//        System.out.println(sample.v1);
    }

}

 

岂运作此程序来观察类加载过程为?

 1、在D: 盘下分别立文件夹

  D:\myapp\serverlib\
  D:\myapp\clientlib\
  D:\myapp\Bootstrap,otherlib\
  D:\myapp\syslib\

2、新建Dog.java、Sample.java

public class Dog {
    public Dog() {
        System.out.println("Dog is loaded by : " + this.getClass().getClassLoader());
    }
}

 

public class Sample {
    public int v1 = 1;

    public Sample() {
        System.out.println("Sample is loaded by: " + this.getClass().getClassLoader());

        new Dog();
    }
}

 

3、把MyClassLoader.class、Dog.class、山姆(Sam)ple.class五只.class文件分别坐(注意:要管代码中的package去丢)

Bootstrap 3

  斯时候 clientlib目录和other目录没有另外的.class文件

public static void main(String[] args) throws Exception {
        MyClassLoader loader1 = new MyClassLoader("loader1");
        loader1.setPath("D:\\myapp\\serverlib\\");
        MyClassLoader loader2 = new MyClassLoader(loader1, "loader2");
        loader2.setPath("D:\\myapp\\clientlib\\");
        MyClassLoader loader3 = new MyClassLoader(null, "loader3");
        loader3.setPath("D:\\myapp\\otherlib\\");

        test(loader2);
//        System.out.println("==================");
        test(loader3);

 

4、在windows环境下进入DOS命令窗口上及 D:\myapp\syslib 目录下

5、运行 java MyClassLoader.class 看输入

Bootstrap 4

怎么会生这种输出为?
先是bootstrap类加载器加载,发现没找到,然后是Extentian类加载器加载发现呢没找到,App类加载器加载也没找到,然后loader1类加载器加载发现找到了,就已加载了。

 https://gitee.com/play-happy/base-project

参考:

[1] 《深远了然Java虚拟机:JVM高级特性以及最佳实践》,周志明
,机械工业出版社

[2] 《Java 主题技术卷》,机械工业出版社

[3] 博客,http://blog.csdn.net/xyang81/article/details/7292380

相关文章