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

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

一般情况下.保证同一个类中所关联的其他类都是由当前类的类加载器所加载的。

比如,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);//[email protected]

        //获得上下文类加载器,默认也是应用类加载器
        ClassLoader loader2 = Thread.currentThread().getContextClassLoader();
        System.out.println(loader2);//[email protected]

        //设置为自定义的文件系统类加载器
        Thread.currentThread().setContextClassLoader(
                new FileSystemClassLoader("G:/program/java/hello/bin"));
        System.out.println(Thread.currentThread().getContextClassLoader());//[email protected]

        try {
            Class<Demo> c = (Class<Demo>)Thread.currentThread().getContextClassLoader().loadClass("JVMProcess.Demo");
            System.out.println(c);
            System.out.println(c.getClassLoader());//[email protected]

            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@cb6009
sun.misc.Launcher$AppClassLoader@cb6009
JVMProcess.FileSystemClassLoader@da4b71

class JVMProcess.Demo
sun.misc.Launcher$AppClassLoader@cb6009

class hello.HelloWorld
JVMProcess.FileSystemClassLoader@da4b71

注:

关于自定义的FileSystemClassLoader类,请查找

http://blog.csdn.net/scgaliguodong123_/article/details/46914759

自定义类加载器。

服务器类加载原理

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

TOMCAT不能使用系统默认的类加载。

如果tomcat运行你的web项目使用类加载器(双亲委派机制)的话是相当危险的,你可以肆无忌惮的操作系统的各个目录。

对于运行在JavaEE容器中的Web应用来说,类加载器的实现方式与一般的Java应用有所不同。

每个Web应用都有一个对应的类加载器实例。该类加载器也使用化理模式(不同于前面说的双亲委托机制),所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的。

为了保证安全,这样核心库就不在查询范围之内。

为了安全丁0MCAT需要实现自己的类加载器。–我可以限制你只能把类写在指定的地方,否则我不给你加载。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 15:51:22

线程上下文类加载器与服务器类加载原理的相关文章

(二十七)JVM类加载器机制与类加载过程

一.Java虚拟机启动.加载类过程分析 下面我将定义一个非常简单的java程序并运行它,来逐步分析java虚拟机启动的过程. package org.luanlouis.jvm.load; import sun.security.pkcs11.P11Util; /** * Created by louis on 2016/1/16. */ public class Main{ public static void main(String[] args) { System.out.println(

Java类加载器及Android类加载器基础

引子 Android插件化与热更新技术日渐成熟,当你研究这些技术时会发现类加载器在其中占据重要地位.Java语言天生就有灵活性.动态性,支持运行期间动态组装程序,而这一切的基础就是类加载器. Java中的类加载器 Java灵活性和动态性的原因 Java源代码被编译器编译成字节码,即从.java文件编译为.class文件,而.class文件就是通过类加载器加载到虚拟机内存中的. 虚拟机的类加载(Class Loading)过程分为加载.链接(验证.准备.解析).初始化.使用.卸载等过程.这里仅考虑

JAVA类加载器二 通过类加载器读取资源文件

一.getResourceAsStream方法 getResourceAsStream方法实现如下: public InputStream getResourceAsStream(String name) { URL url = getResource(name); try { return url != null ? url.openStream() : null; } catch (IOException e) { return null; } } 可见getResourceAsStream

框架学习前基础加强 泛型,注解,反射(泛型&注解)应用案例,IOC,Servlet3.0,动态代理,类加载器

泛型 1. 泛型类 :具有一个或多个类型变量的类,称之为泛型类! class A<T> { } 2. 在创建泛型类实例时,需要为其类型变量赋值 A<String> a = new A<String>(); * 如果创建实例时,不给类型变量赋值,那么会有一个警告! 3. 泛型方法 :具有一个或多个类型变量的方法,称之为泛型方法! class A<T> { public T fun(T t1) {} } fun()方法不是泛型方法!它是泛型类中的一个方法! pu

线程上下文类加载器ContextClassLoader内存泄漏隐患

前提 今天(2020-01-18)在编写Netty相关代码的时候,从Netty源码中的ThreadDeathWatcher和GlobalEventExecutor追溯到两个和线程上下文类加载器ContextClassLoader内存泄漏相关的Issue: ThreadDeathWatcher causes custom classLoader script memory leaks Ensure ThreadDeathWatcher and GlobalEventExecutor will no

线程上下文类加载器

Java 提供了很多服务提供者接口(Service Provider Interface,SPI),允许第三方为这些接口提供实现.常见的 SPI 有 JDBC.JCE.JNDI.JAXP 和 JBI 等. 这些 SPI 的接口由 Java 核心库来提供,而这些 SPI 的实现代码则是作为 Java 应用所依赖的 jar 包被包含进类路径(CLASSPATH)里.SPI接口中的代码经常需要加载具体的实现类.那么问题来了,SPI的接口是Java核心库的一部分,是由启动类加载器来加载的:SPI的实现类

线程上下文类加载器分析与实现

在上一次[https://www.cnblogs.com/webor2006/p/9246850.html]分析源码中发现有两处设置线程上下文类加载器的代码,如下: 因为它是非常重要的东东,所以这次专门对它进行主题展开,主要的作用为了改变委托双亲模式在某些场景不太适用或者是无法满足需求的,下面先写一个简单的测试代码: 那输出是啥呢? 也就是说当前线程的上下文类加载器是应用类加载器,而第二输出null不足为奇,因为Thread是JDK中的系统类当然是由启动类加载器加载喽. 对于上面的例子先有一个初

深入理解Java类加载器(1):Java类加载原理解析

1 基本信息 每个开发人员对Java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载.Java的类加载机制是技术体系中比较核心的部分,虽然和大部分开发人员直接打交道不多,但是对其背后的机理有一定理解有助于排查程序中出现的类加载失败等技术问题,对理解java虚拟机的连接模型和java语言的动态性都有很大帮助. 2 Java虚拟机类加载器结构简述 2.1 JVM三种预定义类型类加载器 我们首先看一下JVM预定义的三种类型类加载器

JVM 类加载器的工作原理

Java类加载器的作用就是在运行时加载类.Java类加载器基于三个机制:委托.可见性和单一性.委托机制是指将加载一个类的请求交给父类加载器,如果这个父类加载器不能够找到或者加载这个类,那么再加载它.可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类.单一性原理是指仅加载一个类一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类.正确理解类加载器能够帮你解决NoClassDefFoundError和java.lang.ClassNotFo