zoukankan      html  css  js  c++  java
  • jvm2

    public class TT {
        public static void main(String[] args) throws Exception {
            String[] ss = new String[3];
            //String是boot加载器加载的。
            System.out.println(ss.getClass().getClassLoader());//null,
            
            int[] tr = new int[3];
            //如果元素是原生类型是没有类加载器的。
            System.out.println(tr.getClass().getClassLoader());//null。这里的null是因为原生类型,上面的null是因为boot加载器。
            
            TT[] t = new TT[3];
            //数组对象的getClassLoader()返回值跟数组元素的类加载器是一样的
            System.out.println(t.getClass().getClassLoader());//AppClassLoader@73d16e93
            
            Integer[] gg = new Integer[3];
            //如果元素是原生类型是没有类加载器的。
            System.out.println(gg.getClass().getClassLoader());//null
        }
    }

    ClassLoader抽象类,用于加载类,不是加载对象。给定类的二进制名字,

     "java.lang.String"

     "javax.swing.JSpinner$DefaultEditor" 内部类名字

     "java.security.KeyStore$Builder$FileBuilder$1" 内部类FileBuilder中的第一个匿名内部类名字

     "java.net.URLClassLoader$3$1"  第三个匿名内部类中的第一个匿名内部类(内部类没有名字,就用数字表示)

    也可以从网络获取。

    Class类里面有private final ClassLoader classLoader;

    数组类的Class对象不是类加载器创建的,是由虚拟机运行时自动创建的。只有数组的特殊的。

    数组对象的getClassLoader()返回值跟数组元素的类加载器是一样的; 如果元素是原生类型是没有类加载器的。

     默认是双亲委托方式,这是为了安全起见,如果要改变这种方式,就要自己实现类加载器。

    每个ClassLoader都有一个private final ClassLoader parent;就是他的父类加载器,所以加载器的父类加载器是包含关系

    不同的类加载器都是加载不同环境变量指定目录下的类。

    public class T {
        public static void main(String[] args) {
            System.out.println(System.getProperty("sun.boot.class.path"));//bootStrap启动.根 类加载器加载的路径:
            //C:Program FilesJavajdk1.8.0_181jrelibendorsed
    t_debug.jar;
            //C:Program FilesJavajdk1.8.0_181jrelib
    esources.jar;
            //C:Program FilesJavajdk1.8.0_181jrelib
    t.jar;
            //C:Program FilesJavajdk1.8.0_181jrelibjsse.jar;
            //C:Program FilesJavajdk1.8.0_181jrelibjce.jar;
            //C:Program FilesJavajdk1.8.0_181jrelibcharsets.jar;
            //C:Program FilesJavajdk1.8.0_181jrelibjfr.jar;
            //C:Program FilesJavajre1.8.0_181libendorsed
    t_debug.jar
            System.out.println(System.getProperty("java.ext.dirs"));//扩展类加载器加载的路径:
            //C:Program FilesJavajdk1.8.0_181jrelibext;
            //C:WindowsSunJavalibext
            System.out.println(System.getProperty("java.class.path"));//app.应用.系统  类加载器加载的路径:
            //H:2019326spring蚂蚁课堂005-(每特教育&每特学院&蚂蚁课堂)-3期-并发编程专题-线程池原理分析005-
            //(每特教育&每特学院&蚂蚁课堂)-3期-并发编程专题-线程池原理分析上课代码	hread_day_day06_testin
        }
        //手动把class文件放在bootstarp类加载器的目录下,那么这个class文件就由根加载器加载。
    }

    Loader1Loader22个不同的类加载器对象,虽然是同一个类加载器类。Class1class2是同一个包和类名的类的Class对象。Loader1Loader2构成了2个命名空间。

    同一个命名空间加载同一个包和类名的类,是失败的,因为他说已经加载了这个类。

    2个不同的类加载器loader1loader2可以加载同一个包名和类名的类,因此class1class2虽然包名和类名一样,但是再虚拟机中是可以共存的

    同一个包名和类名的类对象,由于是不同的类加载加载,所以在不同的命名空间,是不可见的,不能使用,更不能赋值和转换。Object1不能转换成object2

    类加载器找的是class对象。

    子加载器可以看到父加载器的,父加载器看不到子加载器的。

    一个java类是由类的完全限定名和加载这个类的定义类加载器共同决定的。

    数组不是类加载器加载的,是jvm运行时候创建的。

    扩展类加载器和应用类加载器是由启动类加载器加载的,启动类加载器是由jvm加载的。

    Ideal自带的反编译器反编译的。

    Jdbc是一个标准,oracle厂商会根据这个标准去实现,jdbc是一个标准,原生的在jdkConnectionStatement接口在rt.jar里面,由bootStrap加载器加载。但是ConnectionStatement实现是由厂商实现的,那么就是将厂商提供的jar包放在应用的类路径下,所以厂商的实现就不能由bootstrap加载,因为bootstarp不会去扫描应用的类路径,只能由系统加载器appclassloader加载。

    Connection接口是启动类加载器加载的,Connection的实现启动类加载器加载不了,只能由系统加载器加载。Connection接口看不到他的实现,这是双亲委托出现的问题。

    jdbc,jndi,xml解析都会出现,就是说在SPI场合都有这个问题。

    SPI:Service Provider Intefercejdbc,jndi都是SPIJdk服务提供者仅仅提供一些标准和接口,具体的实现由厂商来实现的。父加载器的类看不到子加载器的,子加载器的类可以看到父加载器的。

    父加载器可以使用当前线程Thread.currentThread().getContextClassLoader()所指定的类加载器加载的类。这就改变了父加载器不能使用子加载器的类的情况。就改变了双亲委托模型。

    线程上下文类加载器就是当前线程的类加载器

    SPI:通过给当前线程设置上下文类加载器,就可以由线程的上下文类加载器来加载接口的实现类。

    框架开发和组件的开发有用到线程上下文类加载器。

     

    package com.ssss;
    public class T {
        /*当前类加载器:
        每个类都会使用加载自身的类加载器,去加载所引用的类。
        
        线程上下文类加载器从jdk1.2引入。
        Thread.currentThread().setContextClassLoader()
        Thread.currentThread().getContextClassLoader()分别用于设置和获取上下文类加载器。
        默认下,线程继承父线程的上下文类加载器,启动应用线程的上下文加载器是系统加载器。所以默认是AppClassLoder。
        在线程中运行的代码可以通过这个类加载器加载类和资源。
        
        jdbc提供的是接口,米有提供实现。实现是厂商提供的,mysql和oracle不同的厂商来提供。
        JDBC,JNDI,JAXP:这些spi都是利用的是线程上下文类加载器。
        
        TOMCAT为每一个应用一个类加载器,使用到了类加载器的隔离,并且违反了双亲委派原则。
        */
        public static void main(String[] args) {
            System.out.println(Thread.currentThread().getContextClassLoader());//AppClassLoader,线程上下文加载器,
            System.out.println(Thread.class.getClassLoader());//null,Thread是根加载器加载的,
        }
    }
    package com.ssss;
    
    public class rrr implements Runnable {
        private Thread t;
        
        public rrr() {
            t = new Thread(this);
            t.start();
        }
        
        public void run() {
            ClassLoader cl = this.t.getContextClassLoader();//这个线程的上下文类加载器是App。
            System.out.println(cl.getClass());//AppClassLoader
            System.out.println(cl.getParent().getClass());//ExtClassLoader
        }
        
        public static void main(String[] args) {
            new rrr();
        }
    }
    package com.ssss;
    
    /*
     线程上下文使用模式:获取-------使用-------还原
     
     类A的依赖类也是加载A的加载器加载。
     
     线程上下文就是为了破坏java的委托机制。默认线程上下文加载器是系统app加载器,spi接口的代码中会使用线程上下文加载器
    加载spi的实现类。
    
    高层提供统一的接口让底层去实现,高层要加载底层的实现类时候,就呀通过线程上下文加载器来帮助高层加载实现类。
    本质是因为高层的加载器和底层加载器不一样,而高层加载器不能加载底层的类。
    
    运行期间放置在了线程中,无论当前程序是在启动类加载器范围还是在扩展加载器范围内,都可以通过Thread.currentThread().getContextClassLoader()
    获取应用类加载器。ThreadLocal是拿空间换时间,每个线程都有一个拷贝。
    
    ClassLoader.getSystemClassLoader()也可以获取app加载器。
     */
    public class Cat {
        public static void main(String[] args) {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();//获取
            try {
                Thread.currentThread().setContextClassLoader(target);
                incokeMeath();//使用线程上下文的类加载器
            }finally {
                Thread.currentThread().setContextClassLoader(cl);//还原
            }
            System.out.println(ClassLoader.getSystemClassLoader());//AppClassLoader
        }
    }

     

     

  • 相关阅读:
    IT民工的时间哪儿来的
    解决Office2007安装时出现错误1706的方法
    情人节特献:有心之函数必然就有分手函数
    mathematica汉化 版本二
    项目经理职责与权利
    什么是产品经理?主要职责是什么?
    调查收藏
    如何在CLI命令行下运行PHP脚本,同时向PHP脚本传递参数?
    PHP的GC垃圾收集机制
    AWStats分析Tomcat\Apache\IIS\nginx 的访问日志
  • 原文地址:https://www.cnblogs.com/yaowen/p/10959256.html
Copyright © 2011-2022 走看看