精华内容
下载资源
问答
  • 系统类加载器

    2020-05-30 18:18:02
    系统类加载器(System) ​ 系统类加载器也称之为应用类加载器,也是纯java类,是原SUN公司实现的sun.misc.Launcher类(是​AppClassLoader)。它的父加载器是扩展类加载器。它负责从classpath环境变量或者系统属性...

    系统类加载器(System)

    ​ 系统类加载器也称之为应用类加载器,也是纯java类,是原SUN公司实现的sun.misc.Launcher类(是​AppClassLoader)。它的父加载器是扩展类加载器。它负责从classpath环境变量或者系统属性java.class.path所指定的目录中加载类。它是用户自定义的类加载器的默认父加载器。一般情况下,该类加载器是程序中默认的类加载器,可以通过ClassLoader.getSystemClassLoader()直接获得。

    public class ClassLoaderDemo {
        public static void main(String[] args) {
            //自己编写的类使用的类加载器
            ClassLoader classLoader = ClassLoaderDemo.class.getClassLoader();
            System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader
        }
    }

     

    展开全文
  • 类加载器分为根加载器(bootstrap classloader)、扩展类加载器(ext classloader)、系统类加载器(system classloader)、自定义类加载器(通常继承java.net.URLClassLoader,重写findClass()),它们的关系通常...
  • 系统类加载器 系统类加载器可能都耳详能熟,但是为了完整点,还是先简单的说说系统的类加载器吧。 public class Test { public static void main(String[] args) { ClassLoader cl1 = Test.class....

    系统类加载器

     系统类加载器可能都耳详能熟,但是为了完整点,还是先简单的说说系统的类加载器吧。

     

    public class Test {
    
    	public static void main(String[] args) {
    		ClassLoader cl1 = Test.class.getClassLoader().getParent().getParent();
    		System.out.println(cl1);
    		
    		ClassLoader cl2 = Test.class.getClassLoader().getParent();
    		System.out.println(cl2);
    		
    		ClassLoader cl3 = Test.class.getClassLoader();
    		System.out.println(cl3);
    	}
    }
    

     

      打印的结果是:

        null
        sun.misc.Launcher$ExtClassLoader@dc6a77
        sun.misc.Launcher$AppClassLoader@1016632

     其实这就是jdk系统中用到的三个类加载器,其中null就是bootstrap classloader,因为是有c++实现,所以在此打印出null。ExtClassLoader就是Extension ClassLoader。AppClassLoader就是App ClassLoader或者叫做system classloader。他们负责加载各自指定位置下的类:

      1)Bootstrap ClassLoader

        负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

      2)Extension ClassLoader

        负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

      3)App ClassLoader

        负责加载classpath中指定的jar包及目录中class

    这三个类加载器的关系通过代码就能看出来:App ClassLoader的parent是Extension ClassLoader,Extension ClassLoader的parent是Bootstrap ClassLoader。

    委托机制

    所谓委托机制就是,当加载一个类时,App ClassLoader委托他的parent(Extension ClassLoader)去加载,Extension ClassLoader又委托他的parent加载直到Bootstrap ClassLoader,如果parent没有加载成功,再由自身去加载。

    以上三个类加载器,除了Bootstrap ClassLoader都是间接继承自ClassLoader类(是一个抽象类不能实例化,但没有抽象方法),委托机制的实现就被loadClass方法作为模板方法实现。以下就通过loadClass的源码分析一下委托机制:

    定制类加载器

       有时我们可能需要定制我们的类加载器以满足我们的特殊需求。而且我们一般也不需要破坏委托机制(后边会介绍一个破坏了委托机制的类加载器的例子)通常可以有两种方法实现

     一、继承URLClassLoader,比如

    public class TestClassLoader extends URLClassLoader {
    
    	public TestClassLoader(URL[] urls) {
    		super(urls);
    	}
    	public TestClassLoader(URL[] urls,ClassLoader parent) {
    		super(urls,parent);
    	}
    	
    }
    

     你只需要调用父类构造方法,其它方法你一概不用重写。这也是最简单的实现。使用时只需要调用loadClass。缺点是你只能通过URL定位你要加载的class。

    二、继承ClassLoader类,重写findClass方法。比如

    public class TestClassLoader extends ClassLoader {
    
    	private String basedir;
    	
    	public TestClassLoader(String basedir,ClassLoader parent){
    		super(parent);
    		this.basedir = basedir;
    	}
    	
    	@Override
    	protected Class<?> findClass(String name) throws ClassNotFoundException {
    		Class<?> cls = null; 
            StringBuffer sb = new StringBuffer(basedir); 
            String classname = name.replace('.', File.separatorChar) + ".class";
            sb.append(File.separator + classname); 
            File classF = new File(sb.toString()); 
            if(!classF.exists()){
            	throw new ClassNotFoundException();
            }
            
            byte[] raw = new byte[(int) classF.length()];
    		try {
    			InputStream fin = new FileInputStream(classF);
    			fin.read(raw);
    	        fin.close();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
            
            cls = defineClass(name,raw,0,raw.length);
            return cls; 
    	}
    }
    

      在findClass方法里我们可以采用任意方式查找我们要加载的类,这里采用了读文件的方式。使用时同样是调用loadClass方法。

    线程上下文类加载器

      线程上下文类加载器(context class loader)是从 JDK 1.2 开始引入的。类 java.lang.Thread中的方法 getContextClassLoader()setContextClassLoader(ClassLoader cl)用来获取和设置线程的上下文类加载器。如果没有通过 setContextClassLoader(ClassLoader cl)方法进行设置的话,线程将继承其父线程的上下文类加载器。Java 应用运行的初始线程的上下文类加载器是系统类加载器。在线程中运行的代码可以通过此类加载器来加载类和资源。

      前面提到的类加载器的委托机制并不能解决 Java 应用开发中会遇到的类加载器的全部问题。Java 提供了很多服务提供者接口(Service Provider Interface,SPI),允许第三方为这些接口提供实现。常见的 SPI 有 JDBC、JCE、JNDI、JAXP 和 JBI 等。这些 SPI 的接口由 Java 核心库来提供,如 JAXP 的 SPI 接口定义包含在 javax.xml.parsers包中。这些 SPI 的实现代码很可能是作为 Java 应用所依赖的 jar 包被包含进来,可以通过类路径(CLASSPATH)来找到,如实现了 JAXP SPI 的 Apache Xerces所包含的 jar 包。SPI 接口中的代码经常需要加载具体的实现类。如 JAXP 中的 javax.xml.parsers.DocumentBuilderFactory类中的 newInstance()方法用来生成一个新的 DocumentBuilderFactory的实例。这里的实例的真正的类是继承自 javax.xml.parsers.DocumentBuilderFactory,由 SPI 的实现所提供的。如在 Apache Xerces 中,实现的类是 org.apache.xerces.jaxp.DocumentBuilderFactoryImpl。而问题在于,SPI 的接口是 Java 核心库的一部分,是由引导类加载器来加载的;SPI 实现的 Java 类一般是由系统类加载器来加载的。引导类加载器是无法找到 SPI 的实现类的,因为它只加载 Java 的核心库。它也不能代理给系统类加载器,因为它是系统类加载器的祖先类加载器。也就是说,类加载器的委托机制无法解决这个问题。

      线程上下文类加载器正好解决了这个问题。如果不做任何的设置,Java 应用的线程的上下文类加载器默认就是系统上下文类加载器。在 SPI 接口的代码中使用线程上下文类加载器,就可以成功的加载到 SPI 实现的类。线程上下文类加载器在很多 SPI 的实现中都会用到。

    转载于:https://www.cnblogs.com/metoy/p/3915990.html

    展开全文
  • 当jvm启动时,一块特殊的机器码会运行,它会加载扩展类加载器与系统类加载器, 这块特殊的机器码叫做启动类加载器(Bootstarp)。 启动类加载器并不是Java类,而其它加载器则都是Java类。 启动类加载器是特定于平台的...

    内建于JVM中的启动类加载器会加载java.lang.ClassLoader以及其他java平台类,
    当jvm启动时,一块特殊的机器码会运行,它会加载扩展类加载器与系统类加载器,
    这块特殊的机器码叫做启动类加载器(Bootstarp)。
    启动类加载器并不是Java类,而其它加载器则都是Java类。
    启动类加载器是特定于平台的机器指令,它负责开启整个加载过程。
    所有类加载器(除了启动类加载器)都被实现为Java类,不过,总归要有一个组件来加载第一个Java类加载器,从而让整个加载过程能够顺利进行下去,加载第一个纯Java类加载器就是启动类加载器的职责。
    启动类加载器还会负责加载供JRE正常运行所需要的基本组件,这包括java.util与java.lang包中的类等等。

    展开全文
  • 当jvm启动时,一块特殊的机器码会运行,它会加载扩展类加载器与系统类加载器, 这块特使的机器码叫作启动类加载器(Bootstrap)。 启动类加载器并不是Java类,而其他的列加载器则是java类,启动类加载器特定于 平台...

    内建于jvm中的启动类加载器会加载java.lang.classloader以及其他的java类平台,
    当jvm启动时,一块特殊的机器码会运行,它会加载扩展类加载器与系统类加载器,
    这块特使的机器码叫作启动类加载器(Bootstrap)。

    启动类加载器并不是Java类,而其他的列加载器则是java类,启动类加载器特定于
    平台的机器指令,它负责开启整个加载过程。

    所有的类加载器(除了启动类加载器)都是java类,不过,总归要有一个组件来加
    载第一个java类加载器,从而让整个加载过程能够顺利进行下去,加载第一个纯java
    类加载器就是启动类加载器的职责。

    启动类加载器还会负责加载供jre正常运行所需要的基本组件,这包括java.util与java.
    lang包中的类等等。

    1、实例代码

    /**
     * @author dc
     * @date 2020/6/15 - 10:30
     */
    
    
    /**
     * 在运行期,一个java类是由该类的完全限定名(binary name,二进制名)和用于加载该类的定义类加载器
     * (defining loader)所共同决定的。如果同样名字(即相同的限定名)的类是由两个不同的加载器所加载,
     * 那么这类就是不同的,即便.class文件的字节码完全一样,并且从相同的位置加载也如此。
     */
    
    import sun.misc.Launcher;
    
    /**
     * 在Oracle的Hostpot实现中,系统属性sun.boot.class.path如果修改错了,则运行会出错,提示如下错误信息:
     * Error occurred during initialization of VM
     * java/lang/NoClassDefFoundError: java/lang/Object
     */
    public class MyTest14 {
    
        public static void main(String[] args) {
           /*
            System.out.println(System.getProperty("sun.boot.class.path"));
            System.out.println(System.getProperty("java.ext.dirs"));
            System.out.println(System.getProperty("java.class.path"));
    
    */
            //验证类加载器是由启动类加载器加载的
            System.out.println("classLoader's loader is " + ClassLoader.class.getClassLoader());
    
            //验证扩展类加载器与系统类加载器是由启动类加载器加载的
            System.out.println("Launcher's loader is " + Launcher.class.getClassLoader());
            //System.out.println("-----------------------------");
    
            //System.out.println(System.getProperty("java.system.class.loader"));
    
        }
    }
    

    2、运行结果

    在这里插入图片描述

    展开全文
  • 实现自定义类加载器(自定义文件系统类加载器) package cn.com.lodar; import java.io.*; public class FileSystemClassLoader extends ClassLoader{ //自定义文件系统类加载器 private String rootDir; public...
  • package java_221_JVM核心机制_深入类加载器_自定义文件系统类加载器_网络自定义类加载器_练习; /** 文件系统加载器 */ import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io....
  • 默认情况下加载我们classpath下的class文件的类加载器就是这个APP_LOADER,好多地方也把这个AppClassLoader翻译成系统类加载器,个人觉得这个翻译不是很准确,我猜测翻译成功系统类加载器是因为ClassL...
  • 从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范却没有这么定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。 无论类加载器的类型如何...
  • 1 系统类加载器会成为上下文加载器 2 每一个类都会使用自己的类加载器(即加载自身的类加载器) 去加载其他类(指的是所依赖的类) 3如果classA引用了classB nam classA的类加载器就会去加载classB(前提是classB...
  • 平台特定的启动类加载器深入分析与自定义系统类加载器详解 1.关于根类加载器和其他类加载: ​ 内建于JVM中启动类加载器会加载java.lang.ClassLoader以及其他的Java平台类;当JVM启动时,一块特殊的机器码会运行,...
  • package java_221_JVM核心机制_深入类加载器_自定义文件系统类加载器_网络自定义类加载器_练习; /** 网络类加载器 注意几处修改 ;其他没有太大变化 */ import java.io.ByteArrayOutputStream; import java.io....
  • 系统类加载器的父类加载器是扩展类加载器 ExtClassLoader; 扩展类加载器的父类加载器是启动类加载器 BootStrapClassLoader,返回值以null表示; 代码实例: public class TestCode13 { public static void main...
  • JAVA系统类加载器

    千次阅读 2018-07-06 21:39:59
    JAVA系统类加载器 三个加载器类 Bootstrap ClassLoader 最顶层的加载类,主要加载核心类库,JRE_HOME\lib下的rt.jar、resources.jar、charsets.jar和class等。另外需要注意的是可以通过启动jvm时指定-...
  • AppClassLoader 系统类加载器 ExtClassLoader 扩展类加载器 关于类加载器的一些东西,可以看这篇类加载 Launcher的getClassPath(String classPath): private static File[] getClassPath(String classPath) { ...
  • 自定义文件系统类加载器 JDK的类加载机制是代理模式中的双亲委派机制, 先由父类加载,父类无法加载时由子类加载,用以保证加载安全。 import java.io.ByteArrayOutputStream; import java.io.FileInputStream; ...
  • 可以通过ClassLoader.getSystemClassLoader()方法获取系统类加载器,下面进入到ClassLoader的该方法中查看系统类加载器如何被创建。 1、通过initSystemClassLoader()方法来初始化系统类加载器 public static ...
  • 那么如果是系统类加载器加载的类,无法引用自定义加载器加载的类. 那么如果想要ASM生成的字节码,然后通过系统类加载进行加载,那么就没有上面的问题了. 而JVM基于安全考虑,是不允许在未经许可而是用系统类加载器...
  • <br />文件系统类加载器 第一个类加载器用来加载存储在文件系统上的 Java 字节代码。完整的实现如 代码清单 6 所示。 清单 6. 文件系统类加载器 public class FileSystemClassLoader extends...
  • 类的加载的最终产品是位于堆(heap)中的class对象 Class对象封装了类在方法区内的数据结构并向Java程序员提供访问方法区内的数据结构的接口。而反射就像一面镜子一样可这个接口是反射的...2、 用户自定义类加载器...
  • 默认情况下加载我们classpath下的class文件的类加载器就是这个APP_LOADER,好多地方也把这个AppClassLoader翻译成系统类加载器,个人觉得这个翻译不是很准确,我猜测翻译成功系统类加载器是因为ClassL...
  •  返回用于委托的系统类加载器,它是新建ClassLoader实例的默认的委托双亲,通常也是启动应用的类加载器。    这个方法在运行启动期间很早的时候就被调用,在调用时首先会创建系统加载器,而且会将其设置为调用该...
  • 通过上截图,可以看出,应用类加载器的加载目录为.也就是当前目录 下图就是.(点)目录 总结: 若是将 根加载器加载目录修改下 改成当前目录 虚拟机初始化的时候出错,先加载Object类 找不到object类,虚拟机...
  • 可以通过“java.system.class.loader"属性指定系统类加载器 默认情况下,该属性值为空: public class Test { public static void main(String[] args) { System.out.println(System.getProperty("java....
  • 源码: 获取APPClassLoader时,传入extcl,把他作为双亲 上图中,为当前执行的线程设置上下文类加载器,也就是APPClassLoader ...= null)也就是说,可以将自己设置的类加载器作为系统类加载器使用。 通...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,286
精华内容 2,514
关键字:

系统类加载器