紧接着上一篇,Java的类加载器对读进来的类文件的二进制流进行加载的过程,其在整个处理过程中我认为最重要的就是这个概念:不同的类进行比较时不光比较的是类本身,更有对加载器的比较,同样的一个类由不同的加载器进行实现,在Java的默认比较方法中它也是完全不同的存在,只有同一个class由同一个加载器实现加载才能确定这个类对象在整个系统中的唯一性。
这里谈到加载器,顺便说一下双亲委派模式。加载器总体上分为两个大类,其中之一是启动类的加载器,还有就是其他类加载器,启动类加载器是由C++进行实现的,而其他类的加载器则是由Java类实现的。
启动类加载加载就是Java_home之下lib中的文件。
拓展类加载器,加载Java_home中lib下,ext中的文件
应用程序类加载器,加载用户路径下的指定类库,一般情况下这个加载器就是默认的加载器。
接着说双亲委派模型,类加载器是不会直接尝试加载类的,而是通过逐层传递,不断的往上进行传递,交给父类加载器进行完成,如果父类加载器表示无法完成此类请求就会把它在往下传递,主要也是为了符合Java的特性,保证了各种类在不同情况加载是有规则的,例如object无论在哪里实现,object都会被判断在同一加载器执行,而不是出现很多加载器加载的object这样之前也提到过这些object是完全不同的类,打破了Java的规则。
关于类加载器的事情就说完了,这里顺便讲解一下动态代理技术,这个技术在太多层面都能应用得到,所以简单说一下。
这里是深入理解Java虚拟机中一个很简单的例子:会给出结果,方便大家理解。
public class DynamicProxyTest{
interface IHello{
void sayHello();
}
static class Hello implements IHello{
public void sayHello(){
System.out.println("this is static content");
}
}
static class DynamicProxy implements InvocationHandler{
Object original;
Object bind(Object original){//传入的是实现接口的类,里面是写好的方法实现
this.original=original;//赋值给外面一层的变量
return
Proxy.newProxyInstance(original.getClass().getClass().getClassLoader(),original.getClass().getInterfaces(),this);
}//将代理实例返回,里面的参数是实现类的加载器,实现类的接口,this对象
pbulic Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
System.out.println("dynamic test ");
return method.invoke(original,args);调用了方法,参数分别是实现类,参数
}
}
public static void main(String[] args){
IHello hello=(IHello) new DynamicProxy().bind(new Hello());//接口使用了动态的代理实现
hello.sayHello();//调用里面的方法
}
}