JVM在运行时会产生三个ClassLoader,Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader.其中,Bootstrap是用C++编写的,我们在Java中看不到它,是null。它用来加载核心类库,在JVM源代码中这样写道:
static const char classpathFormat[] =
"%/lib/rt.jar:"
"%/lib/i18n.jar:"
"%/lib/sunrsasign.jar:"
"%/lib/jsse.jar:"
"%/lib/jce.jar:"
"%/lib/charsets.jar:"
"%/classes";
知道为什么不需要在classpath中加载这些类了吧?人家在JVM启动的时候就自动加载了,并且在运行过程中根本不能修改Bootstrap加载路径。
Extension ClassLoader用来加载扩展类,即/lib/ext中的类。
最后AppClassLoader才是加载Classpath的。
ClassLoader加载类用的是委托模型。即先让Parent类(而不是Super,不是继承关系)寻找,Parent找不到才自己找。看来ClassLoader还是蛮孝顺的。三者的关系为:AppClassLoader的Parent是ExtClassLoader,而ExtClassLoader的Parent为Bootstrap ClassLoader。加载一个类时,首先BootStrap先进行寻找,找不到再由ExtClassLoader寻找,最后才是AppClassLoader。
为什么要设计的这么复杂呢?其中一个重要原因就是安全性。比如在Applet中,如果编写了一个java.lang.String类并具有破坏性。假如不采用这种委托机制,就会将这个具有破坏性的String加载到了用户机器上,导致破坏用户安全。但采用这种委托机制则不会出现这种情况。因为要加载java.lang.String类时,系统最终会由Bootstrap进行加载,这个具有破坏性的String永远没有机会加载。
我们来看这段代码:
//A.java
public class A{
public static void main(String[] args){
A a=new A();
System.out.println(System.getProperty("java.ext.dirs"));
System.out.println(a.getClass().getClassLoader());
B b=new B();
b.print();
}
}
//B.java
public class B{
public void print(){
System.out.println(this.getClass().getClassLoader());
}
}
1、我们将它放在Classpath中,则打印出
sun.misc.Launcher$AppClassLoader@92e78c
sun.misc.Launcher$AppClassLoader@92e78c
可见都是由AppClassLoader来加载的。
2、我们将其放在%jre%/lib/ext/classes(即ExtClassLoader的加载目录。其加载/lib/ext中的jar文件或者子目录classes中的class文件)中。则会打印出:
sun.misc.Launcher$ExtClassLoader
sun.misc.Launcher$ExtClassLoader
3、我们将A.class放到%jre%/lib/ext/classes中,而将B.class放到classpaht中又会怎么样呢?结果是:
sun.misc.Launcher$ExtClassLoader
Exception in thread "main" java.lang.NoClassDefFoundError:B
at A.main(A.java:6)
怎么会这样呢?这其中有一个重要的问题:A类当然是由ExtClassLoader来加载的,B类要由哪个加载呢?B类要由调用它自己的类的类加载器(真拗口)。也就是说,A调用了B,所以B由A的类加载器ExtClassLoader来加载。ExtClassLoader根据委托机制,先拜托Bootstrap加载,Bootstrap没有找到。然后它再自己寻找B类,还是没找到,所以抛出异常。ExtClassLoader不会请求AppClassLoader来加载!你可能会想:这算什么问题,我把两个类放到一起不就行了?
呵呵,没这么简单。比如JDBC是核心类库,而各个数据库的JDBC驱动则是扩展类库或在classpath中定义的。所以JDBC由Bootstrap ClassLoader加载,而驱动要由AppClassLoader加载。等等,问题来了,Bootstrap不会请求AppClassLoader加载类啊。那么,他们怎么实现的呢?我就涉及到一个Context ClassLoader的问题
分享到:
相关推荐
Java ClassLoader是Java运行时系统的关键但经常被忽视的组件,负责在运行时查找和加载类文件。通过创建自定义ClassLoader,你可以定制JVM,使类文件的引入方式完全重新定义,这提供了很多实用和有趣的可能。这篇教程...
在Java中,Classloader是加载类的关键组件,它负责查找、加载和初始化字节码文件。自定义Classloader允许开发者根据特定需求定制类的加载逻辑,例如加密类文件、隔离不同版本的库或者动态加载代码。本文将深入探讨...
在Java编程语言中,ClassLoader是一个至关重要的组成部分,它负责加载类到JVM(Java虚拟机)中。理解ClassLoader的工作原理以及如何定制它,对于深入学习Java的运行机制和进行高级应用开发具有重要意义。本篇文章将...
在Java编程语言中,ClassLoader是一个至关重要的组成部分,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。本示例"ClassLoader小例子"将深入探讨这个概念,并通过一个具体的程序来演示其工作原理。下面我们...
《深入理解ClassLoader工作机制》 Java虚拟机(JVM)中的ClassLoader是负责加载类到内存中的核心组件。它不仅承担着将字节码转换为可执行对象的重任,还参与了类生命周期的各个阶段,包括加载、验证、准备、解析、...
首先,ClassLoader可以分为三种基本类型:Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader。Bootstrap ClassLoader是JVM启动时的第一个ClassLoader,负责加载JDK的`<JAVA_HOME>\lib`目录下...
《ClassLoader详解》 Java应用程序的运行离不开类的加载,而ClassLoader正是这个过程的关键角色。它负责将类的字节码加载到Java虚拟机(JVM)中并转换为可执行的Java对象。深入理解ClassLoader的工作原理对于优化...
### ClassLoader概述 在Java中,`ClassLoader`是负责加载类到JVM的重要组件之一。它不仅能够确保每个被加载的类都具有唯一的标识符,还能处理类的生命周期中的加载、连接(验证、准备和解析)及初始化等关键步骤。 ...
Java ClassLoader机制是Java运行时环境中的核心组件之一,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。理解ClassLoader的工作原理对于优化应用性能、处理类加载问题以及实现自定义加载器至关重要。 首先...
在Java编程语言中,ClassLoader是核心组件之一,它负责加载类到JVM(Java虚拟机)中。自定义ClassLoader允许开发者根据特定需求加载类,比如动态加载或更新类文件,这在某些高级应用场景中非常有用,如插件系统、热...
在Java编程语言中,ClassLoader是核心组件之一,它负责加载类到JVM(Java虚拟机)中执行。本文将深入探讨ClassLoader的工作原理和类加载机制,帮助开发者理解这个至关重要的概念。 1. 类加载机制概述 Java的类加载...
在Java编程语言中,ClassLoader是一个至关重要的组成部分,它负责加载类到JVM(Java虚拟机)中执行。这篇测试主要探讨了ClassLoader的工作原理及其在实际应用中的使用。通过阅读给出的博文链接,我们可以深入理解...
在Java编程语言中,ClassLoader是核心组件之一,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。ClassLoader原理的理解对于深入学习Java和进行系统优化至关重要。这篇博文将带你深入了解ClassLoader的工作...
在Java编程语言中,类加载器(ClassLoader)是运行时环境的核心组成部分,它负责将类的字节码从各种来源(如JAR文件、网络、内存等)加载到Java虚拟机(JVM)中,使得程序能够运行。本文将深入探讨“使用classloader...
在Java编程环境中,ClassLoader是一个至关重要的组件,它负责加载类到Java虚拟机(JVM)中。当我们需要从外部jar包动态加载类时,自定义ClassLoader就显得尤为关键。这篇博文"定义ClassLoader调用外部jar包"探讨了...
在Java编程语言中,`ClassLoader`是一个至关重要的组件,它负责加载类到JVM(Java虚拟机)中。本文将深入探讨`ClassLoader`的工作原理、加密解密应用程序以及如何防止类被反编译。 首先,让我们理解`ClassLoader`的...
Java的类加载器(ClassLoader)体系结构是JVM(Java虚拟机)中至关重要的一部分,它负责将类的字节码转换为运行时的类实例。本文将深入探讨启动类加载器、扩展类加载器、系统类加载器以及用户自定义类加载器,同时还...
### Java ClassLoader与ClassPath详解 #### 一、概述 在Java编程中,类加载机制是十分关键的一个环节。类加载器(`ClassLoader`)负责将编译后的`.class`文件加载到Java虚拟机(JVM)中执行,而类路径(`ClassPath...