学习ClassLoader有几个关注点:
From: http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html
1. java.lang.ClassLoader
中的关键方法
方法
说明
getParent()
|
返回该类加载器的父类加载器。
|
loadClass(String name)
|
加载名称为 name 的类,返回的结果是 java.lang.Class 类的实例。
|
findClass(String name)
|
查找名称为 name 的类,返回的结果是 java.lang.Class 类的实例。
|
findLoadedClass(String name)
|
查找名称为 name 的已经被加载过的类,返回的结果是 java.lang.Class 类的实例。
|
defineClass(String name, byte[] b, int off, int len)
|
把字节数组 b 中的内容转换成 Java 类,返回的结果是 java.lang.Class 类的实例。这个方法被声明为 final 的。
|
resolveClass(Class<?> c)
|
链接指定的 Java 类。
|
2. 类加载器的Delegate
除了引导类加载器之外,所有的类加载器都有一个父类加载器。类加载器在尝试自己去查找某个类的字节代码并定义它时,会先代理给其父类加载器,由父类加载器先去尝试加载这个类,依次类推。通过代理模式,对于 Java 核心库的类的加载工作由引导类加载器来统一完成,保证了 Java 应用所使用的都是同一个版本的 Java 核心库的类,是互相兼容的。比如java.lang.Object
3. 类的定义加载器与初始加载器
真正完成类的加载工作的类加载器和启动这个加载过程的类加载器,有可能不是同一个。真正完成类的加载工作是通过调用 defineClass
来实现的;而启动类的加载过程是通过调用 loadClass
来实现的。前者称为一个类的定义加载器(defining loader),后者称为初始加载器(initiating loader)。在 Java 虚拟机判断两个类是否相同的时候,使用的是类的定义加载器。也就是说,哪个类加载器启动类的加载过程并不重要,重要的是最终定义这个类的加载器。两种类加载器的关联之处在于:一个类的定义加载器是它引用的其它类的初始加载器。如类 com.example.Outer
引用了类 com.example.Inner
,则由类 com.example.Outer
的定义加载器负责启动类 com.example.Inner
的加载过程。
4. 线程上下文类加载器
java.lang.Thread getContextClassLoader() / setContextClassLoader(ClassLoader cl)
如果没有通过 setContextClassLoader(ClassLoader cl)
方法进行设置的话,线程将继承其父线程的上下文类加载器。Java 应用运行的初始线程的上下文类加载器是系统类加载器。在线程中运行的代码可以通过此类加载器来加载类和资源。
这通常发生在JVM核心代码必须动态加载由应用程序动态提供的资源时。拿JNDI为例,它的核心是由JRE核心类(rt.jar)实现的。但这些核心JNDI类必须能加载由第三方厂商提供的JNDI实现。这种情况下调用父类加载器(原初类加载器)来加载只有其子类加载器可见的类,这种代理机制就会失效。解决办法就是让核心JNDI类使用线程上下文类加载器,从而有效的打通类加载器层次结构,逆着代理机制的方向使用类加载器。
常见的 SPI 有 JDBC、JCE、JNDI、JAXP 和 JBI 等。这些 SPI 的接口由 Java 核心库来提供。这些 SPI 的实现代码很可能是作为 Java 应用所依赖的 jar 包被包含进来,可以通过类路径(CLASSPATH)来找到,如实现了 JAXP SPI 的 Apache Xerces 所包含的 jar 包。线程上下文类加载器正好解决了这个问题。如果不做任何的设置,Java 应用的线程的上下文类加载器默认就是系统上下文类加载器。在 SPI 接口的代码中使用线程上下文类加载器,就可以成功的加载到 SPI 实现的类。线程上下文类加载器在很多 SPI 的实现中都会用到
5. 来自网络的类加载器实现需要注意的
类 NetworkClassLoader
负责通过网络下载 Java 类字节代码并定义出 Java 类。在通过 NetworkClassLoader
加载了某个版本的类之后,一般有两种做法来使用它。第一种做法是使用 Java 反射 API。另外一种做法是使用接口。需要注意的是,并不能直接在客户端代码中引用从服务器上下载的类,因为客户端代码的类加载器找不到这些类。使用 Java 反射 API 可以直接调用 Java 类的方法。而使用接口的做法则是把接口的类放在客户端中,从服务器上加载实现此接口的不同版本的类。在客户端通过相同的接口来使用这些实现类。
6. Web/Java EE 应用类加载器 delegate的例外
以 Apache Tomcat 来说,每个 Web 应用都有一个对应的类加载器实例。该类加载器也使用代理模式,所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的。这是 Java Servlet 规范中的推荐做法,其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类。这种代理模式的一个例外是:Java 核心库的类是不在查找范围之内的。这也是为了保证 Java 核心库的类型安全。
分享到:
相关推荐
System.out.println("parent class loader: " + cl.getParent()); cl = cl.getParent(); } ``` 这段代码会打印出当前的类加载器以及它们的父加载器。通常,你会看到AppClassLoader(系统类加载器)、...
最后,我们可以参考博客文章《Ejb class loader》(链接:https://sbiigu.iteye.com/blog/323180)来获取更具体的实现细节和技术讨论。该博客可能包含了作者在实际工作中遇到的问题、解决方案以及对EJB类加载器的...
创建自定义类加载器通常需要继承`java.lang.ClassLoader`,重写`findClass()`或`loadClass()`方法,从而控制类的查找和加载过程。这使得开发者能够在运行时根据需要加载特定的类,比如从网络、数据库或其他非传统...
### 动态类加载在Java虚拟机中的应用 #### 概述 动态类加载是Java虚拟机(JVM)的一项核心特性,它为Java平台带来了强大的功能:即能够在运行时安装软件组件。这一机制不仅提高了系统的灵活性,还优化了资源管理。...
遇到类冲突、类找不到等问题时,可通过设置JVM参数`-verbose:class`来查看类加载的详细信息,或者使用JDK的`jmap -histo`命令分析内存中的类加载情况。 8. **线程安全** 类加载过程中的某些步骤,如加载和初始化...
应用服务器类加载器 共享库 类加载器问题诊断 资源及参考资料
- **System Class Loader**:也称为应用程序类加载器,加载classpath环境变量指定的类或jar包,通常用于加载用户的应用程序类。 类加载器遵循以下原则: - **代理原则**:类加载器在尝试加载类时,首先会委托其父...
【JCL(Jar Class Loader)】是一个开源项目,它的核心功能是允许程序在运行时动态地从Jar文件或其他数据源加载Java类。JCL的设计理念是可配置、动态且可扩展,这使得开发者可以根据需求定制类加载的行为,适应不同...
WAS 中类加载器是一个具有父子关系的分层结构,包括 JVM Class loader、WebSphere Extensions Class loader、WebSphere lib/app Class loader、WebSphere "server" Class loader 和 Application Module Class Loader...
概述 JCL是可配置,动态和可扩展的自定义类加载器,可直接从Jar文件和其他来源加载Java类。 这样做的动机是创建隔离的类加载器,该类加载器可以轻松地与IoC框架(如Spring)和Web应用程序集成。...
Class Loader 是一个可视化的基本 .net 2.0 软件。 使用类加载器,您可以在没有命令提示符的情况下执行 .class 文件。 只需打开类文件!
通常,`Class Loader`有两种类型:`Boot Class Loader`和`Path Class Loader`。`Boot Class Loader`用于加载系统框架类,而`Path Class Loader`则用于加载应用程序自身的类文件。 **1.2 FART的工作机制** - **获取...
在C++编程中,动态类加载(Dynamic Class Loading)是一种高级技术,允许程序在运行时加载未知或在编译时不可用的类。这通常用于实现插件系统、模块化设计或者灵活的软件架构。开源的C++动态类加载机制为开发者提供...
如果类还未加载,它会通过当前线程的上下文类加载器(Context Class Loader)来加载。 2. **类初始化**:除了加载类,`forName`还会执行类的初始化。这意味着静态块会被执行,静态变量会被初始化。 然而,`...
例如,我们可以使用 WebSphere Extensions Class loader 来加载 WebSphere 的一些 runtime 类,而使用 Application Module Class Loader 来加载 J2EE 应用程序。 * 使用 OSGi 框架:OSGi 框架提供了一种方式来解决 ...
// from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); ... }...
### Java自定义类加载器(Class Loader)详解 #### 一、引言 在Java语言中,类加载机制是其动态特性的核心之一。通过类加载器(Class Loader),Java程序能够在运行时根据需要加载所需的类,从而实现高度的灵活性...