MS系列:Java类加载

类的完整生命周期
Java源文件(.java文件)  -->编译
Java字节码(.class文件, 存储于本地本地硬盘、网络、内存等)  -->类加载
    加载 <主要的考点>
    验证
    准备
    解析
Class对象               -->实例化
实例对象
使用
卸载

什么时候触发类加载?
1. 使用new关键字实例化对象,读取或者设置一个类的静态变量的时候,调用类的静态方法的时候;
2. 对类进行反射调用的时候;
3. 初始化子类时,父类会先被初始化;
4. 对类使用动态代理的时候需要先被初始化;

JDK自带类加载器

参考http://blog.csdn.net/briblue/article/details/54973413
启动类加载器 Bootstrap ClassLoader
加载的范围:存放在 \lib 目录中的,加载到虚拟机内存中
扩展类加载器 Extension ClassLoader
加载的范围:存放在\lib\ext目录中的所有类库,开发者可以直接使用;
应用程序加载器 Application ClassLoader
加载用户类路径上指定的类库,开发者可以直接使用,一般情况下这个就是程序中默认的类加载器;


类加载器加载顺序
1. Bootstrap CLassloder 
2. Extention ClassLoader 
3. AppClassLoader
4. 用户自定义类加载器    

谈下你对双亲委派模型理解?
双亲委派模型过程
    某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
双亲委派模型好处
    Java类随着它的类加载器一起具备了带有优先级的层次关系,保证java程序稳定运行
具体步骤:
    1. 一个AppClassLoader查找资源时,先看看缓存是否有,缓存有从缓存中获取,否则委托给父加载器。 
    2. 递归,重复第1部的操作。 
    3. 如果ExtClassLoader也没有加载过,则由Bootstrap ClassLoader出面,它首先查找缓存,如果没有找到的话,就去找自己的规定的路径下,也就是sun.mic.boot.class下面的路径。找到就返回,没有找到,让子加载器自己去找。 
    4. Bootstrap ClassLoader如果没有查找成功,则ExtClassLoader自己在java.ext.dirs路径中去查找,查找成功就返回,查找不成功,再向下让子加载器找。 
    5. ExtClassLoader查找不成功,AppClassLoader就自己查找,在java.class.path路径下查找。找到就返回。如果没有找到就让子类找,如果没有子类会怎么样?抛出各种异常。

JDK的双亲委派逻辑体现在 java.lang.ClassLoader.loadClass(String name, boolean resolve)中
自定义的ClassLoader通常通过重写findClass()方法实现自己的类加载逻辑
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException{
        synchronized (getClassLoadingLock(name)) {
            Class c = findLoadedClass(name);                // First, check if the class has already been loaded
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);   //load the class parent
                    } else {
                        c = findBootstrapClassOrNull(name);  //if parent is null, load the class by Bootstrap ClassLoader, which will invoke native method
                    }
                } catch (ClassNotFoundException e) {
                }

                if (c == null) {
                    c = findClass(name);   //if c is still null, using customer classLoader
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

可以绕过双亲委托逻辑吗
可以,继承java.lang.ClassLoader.loadClass,直接调用defineClass()方法就可以了
http://blog.csdn.net/qq_26182553/article/details/79641451

为什么要区分不同类加载器,有什么好处
不同类加载器的主要区别在于加载路径不同, 这样保证了java.lang.String的字节码一定是先从<JAVA_HOME>\lib路径下查找,只有再父加载器加载不到的情况下才会委托给当前加载器去加载,
这样保证了系统的类一定是正确的被加载,防止对系统类的篡改,或者由于同名造成加载对象的混乱。

同一个tomcat容器下的两个应用以及lib目录中都有UserServiceImpl类,tomcat怎么样保证类的隔离性?
类加载器与类的唯一性:
    类加载器虽然只用于实现类的加载动作,但是对于任意一个类,都需要由加载它的类加载器和这个类本身共同确立其在Java虚拟机中的唯一性。通俗的说,JVM中两个类是否“相等”,首先就必须是同一个类加载器加载的,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要类加载器不同,那么这两个类必定是不相等的。
Tomcat目录结构中,有三组目录(“/common/*”,“/server/*”和“shared/*”)可以存放公用Java类库,此外还有第四组Web应用程序自身的目录“/WEB-INF/*”,把java类库放置在这些目录中的含义分别是:
    放置在common目录中:类库可被Tomcat和所有的Web应用程序共同使用。
    放置在server目录中:类库可被Tomcat使用,但对所有的Web应用程序都不可见。
    放置在shared目录中:类库可被所有的Web应用程序共同使用,但对Tomcat自己不可见。
    放置在/WebApp/WEB-INF目录中:类库仅仅可以被此Web应用程序使用,对Tomcat和其他Web应用程序都不可见。
    注意:tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_26182553

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值