线程上下文类加载器与服务器类加载原理

来源:互联网 发布:淘宝头条申请 编辑:程序博客网 时间:2024/05/16 11:23

双亲委派机制以及类加载器的问题

一般情况下.保证同一个类中所关联的其他类都是由当前类的类加载器所加载的。
比如,class A本身在Ext下找到.那么他里面new出来的一些类也就只能用Ext去查找了(不会低一个级别)。所以有些明明App可以找到的,却找不到了。

JDBC API他有实现的driver部分(mysql,sql server)。我们的JDBC APl都是由Boot或者Ext来载入的。但是JDBC driver却是由Ext或者App来载入,那么就有可能找不到driver了。在Java领城中,其实只要分成这种Api+SPI(Service Provide Interface,特定厂商提供的),就会遇到此问题。
常见的SPI有JDBC、JCE、JNDI、JAXP和JBI等。这些SPI的接口由Java核心库来提供,如JAXP的SPI接口定义包含在javax.xml.parsers包中。SPI的接口是Java核心库的一部分,是由引导类加载器来加载的SPI实现的*Java类一般是由系统类加载器来加载的。引导类加载器是无法找到SPI的实现类的,因为它只加载Java的核心库。*

通常当你需要动态加载资源的时候,你至少有三个ClassLoader可以选择:
1.系统类加载器或叫作应用类加载器system classloader,or application classloader。
2.当前类加载器
3.当前线程类加载器

线程上下文类加载器

线程类加载器是为了抛弃双亲委派加载链模式。

每个线程都有一个关联的上下文类载器。如果你使用new Thread()方式生成新的线程,新线程将继承其父线程的上下文类加载器。如果程序对线程上下文类加载器没有任何改动的话,程序中所有的线程将都使用系统类加载器作为上下文类加载器。

Thread.currentThread().getContextClassLoader()Thread.currentThread().setContextClassLoader()

Demo:

package JVMProcess;/** * 线程上下文类加载机制 * @author liguodong */public class ThreadClassLoader {    public static void main(String[] args) {        ClassLoader loader = ThreadClassLoader.class.getClassLoader();        //系统默认是应用类加载器        System.out.println(loader);//sun.misc.Launcher$AppClassLoader@cb6009        //获得上下文类加载器,默认也是应用类加载器        ClassLoader loader2 = Thread.currentThread().getContextClassLoader();        System.out.println(loader2);//sun.misc.Launcher$AppClassLoader@cb6009        //设置为自定义的文件系统类加载器        Thread.currentThread().setContextClassLoader(                new FileSystemClassLoader("G:/program/java/hello/bin"));        System.out.println(Thread.currentThread().getContextClassLoader());//JVMProcess.FileSystemClassLoader@3e0ebb        try {            Class<Demo> c = (Class<Demo>)Thread.currentThread().getContextClassLoader().loadClass("JVMProcess.Demo");            System.out.println(c);            System.out.println(c.getClassLoader());//sun.misc.Launcher$AppClassLoader@cb6009            Class<?> c2 = (Class<?>)Thread.currentThread().getContextClassLoader().loadClass("hello.HelloWorld");            System.out.println(c2);            System.out.println(c2.getClassLoader());        } catch (ClassNotFoundException e) {            e.printStackTrace();        }    }}

运行结果:

sun.misc.Launcher$AppClassLoader@cb6009sun.misc.Launcher$AppClassLoader@cb6009JVMProcess.FileSystemClassLoader@da4b71class JVMProcess.Demosun.misc.Launcher$AppClassLoader@cb6009class hello.HelloWorldJVMProcess.FileSystemClassLoader@da4b71

注:
关于自定义的FileSystemClassLoader类,请查找
http://blog.csdn.net/scgaliguodong123_/article/details/46914759
自定义类加载器。

服务器类加载原理

Tomcat服务器的类加载机制–一切都是为了安全!

TOMCAT不能使用系统默认的类加载。
如果tomcat运行你的web项目使用类加载器(双亲委派机制)的话是相当危险的,你可以肆无忌惮的操作系统的各个目录。
对于运行在JavaEE容器中的Web应用来说,类加载器的实现方式与一般的Java应用有所不同。
每个Web应用都有一个对应的类加载器实例。该类加载器也使用化理模式(不同于前面说的双亲委托机制),所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的。
为了保证安全,这样核心库就不在查询范围之内。
为了安全丁0MCAT需要实现自己的类加载器。–我可以限制你只能把类写在指定的地方,否则我不给你加载。

0 0
原创粉丝点击