`

ClassLoader与资源文件加载

 
阅读更多
深刻理解java的配置环境以及java的执行过程对做好开发是十分重要的。
类加载器ClassLoader 便是其中非常重要的概念。

本文简单并演示Java类加载器的一些特点,不妥之处,敬请指出。

背景:
A.java 引用 了B.jar 中的一个文件,B.jar 包中的C.class 使用了C.class.getResourceAsStream("/jdbc.xml")获取资源文件。 B.jar 做一个独立的功能的工具,使用方只要提供对应的jdbc.xml 配置文件即可在dev qa prod 各个环境使用啦。
但是问题来了,在web下和java命令行情况下,jdbc.xml 文件放置的位置大不相同,因为web 和java命令下 B.jar 中加载C.class的类加载器不同!


类加载器的分类:
1、启动类加载器(Bootstrap ClassLoader) 这个类有c++语言实现,是虚拟机的一部分。
2、所有其他类加载器。其他类加载器都继承抽象类java.lang.ClassLoader。


做为java的大部分项目,都是有以下三类类加载器加载的:
1、启动类加载器。加载的内容为:<JAVA_HOME/lib 目录中的jar包。
2、扩展类加载器。加载的内容为:java.ext.dirs 系统变量指定的路径中所有类库。实现为:sun.misc.Launcher$ExtClassLoader 实现。
3、应用类加载器。实现为:sun.misc.Launcher$AppClassLoader。负责加载用户类路径上指定的类库。

下面我们看个例子:

package org.job.user;

import org.apache.commons.lang.StringUtils;

public class Test {
	public static void main(String[] args) {
       System.out.println(Thread.currentThread().getContextClassLoader());
       System.out.println(StringUtils.class.getClassLoader());
       
       System.out.println(StringUtils.class.getResource("/"));
       System.out.println(Test.class.getResource("/"));
       
       System.out.println(StringUtils.class.getResourceAsStream("/jdbc.xml"));
       System.out.println(Test.class.getResourceAsStream("/jdbc.xml"));
	}
}



此时如果大家到Test.java 所在的目录,执行javac Test.java 会报错:


为什会报错,因为org.apache.commons.lang.StringUtils 找不到,当前AppClassLoader 找不到StringUtils 类的路径。

找到StringUtils 可以通过指定-classpath .;D:\DevPlatform\m2localRepository\commons-lang\commons-lang\2.5\commons-lang-2.5.jar 来找到。


大家注意到输出:
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$AppClassLoader@19821f
file:/E:/spring/spring-aop-aspectj/target/test-classes/
file:/E:/spring/spring-aop-aspectj/target/test-classes/
java.io.BufferedInputStream@1fb8ee3
java.io.BufferedInputStream@61de33
Test.class 和StringUtils.class 都是通过同一个类加载器(AppClassLoader)加载的。另外 通过Test.class.getResourceAsStream("/jdbc.xml") 找到了jdbc.xml 文件,jdbc.xml 文件在E:\spring\spring-aop-aspectj\src\test\java 也即是我执行java 和 javac 的位置。
这说明:AppClassLoader 的根目录在执行环境的目录。


下一步我们演示通过ExtClassLoader 加载,即通过-Djava.ext.dirs=D:\DevPlatform\m2localRepository\commons-lang\commons-lang\2.5 来加载commons-lang-2.5.jar包。



从上面的输出我们看到Test.class 和 StringUtils.class 的类加载器不同了,另外 System.out.println(StringUtils.class.getResourceAsStream("/jdbc.xml")); //没有找到对应的资源文件
       System.out.println(Test.class.getResourceAsStream("/jdbc.xml")) //找到了对应的资源文件

为什么StringUtils.class 找不到对应的资源文件了,因为getResourceAsStream 是通过委托对应的类加载器来加载的,"/jdbc.xml" 通过不同的类加载器来加载,对于的资源文件的位置是不同的。

我在commons-lang-2.5.jar 包所在目录创建com 并在其下建立jdbc.xml 文件,继续运行结果如下:



看到上面的输出,一切都不言而喻。

总结:
对于Class.getResourceAsStream("/*.*") 是通过委托给对应的ClassLoader来加载的,其对应的资源文件的根目录为:
ExtClassLoader: 为java.ext.dirs 指定的目录下的所以目录。优先使用相应jar包的路径对应的根目录。比如java.ext.dirs=/home/q/,那么其根目录为/home/q/*dir。

AppClassLoader: 执行java javac 命令的目录。

注意:AppClassLoader寻找跟资源文件优先使用java.ext.dirs 指定的资源文件,如果没有才会到 命令执行的目录下寻找。 另外java.ext.dirs 指定的资源文件 最好不要有多个重名的文件,否则将不确定使用的是哪一个。
验证留给大家吧
  • 大小: 5.5 KB
  • 大小: 5.9 KB
  • 大小: 7.4 KB
  • 大小: 5.8 KB
0
1
分享到:
评论

相关推荐

    ClassLoader动态加载dex

    `DexFile`类提供了从.dex文件加载类的方法,例如`loadDex()`。一旦类加载到内存,就可以像使用普通类一样使用它们。 在实际应用中,动态加载dex文件通常伴随着一些挑战,比如权限问题、多版本兼容、类冲突等。例如...

    java 静态代码块通过类加载器获取资源文件例子

    本案例聚焦于如何利用静态代码块结合类加载器来高效地获取资源文件,尤其是属性配置文件。下面我们将深入探讨这两个概念及其在实际开发中的作用。 首先,静态代码块是在类被加载到JVM(Java虚拟机)时执行的一段...

    classloader类加载器_基于java类的加载方式详解

    Java类加载器(ClassLoader)是Java虚拟机(JVM)中的一个重要组成部分,用于将Java类文件加载到JVM中,以便能够执行Java程序。在Java中,类加载器的设计采用了一种称为“双亲委派模式”(Parent Delegation Model)...

    Jar包中如何正确地加载资源文件博文中用到的测试项目源码

    你可以通过`Thread.currentThread().getContextClassLoader()`或`Class.getResourceAsStream()`来获取`ClassLoader`实例,然后使用`getResourceAsStream()`方法加载资源文件。例如: ```java InputStream in = ...

    java ClassLoader机制及其在OSGi中的应用

    Java ClassLoader机制是Java虚拟机(JVM)中一个至关重要的组成部分,它的主要任务是将类的.class文件加载到JVM中,使得程序能够运行。ClassLoader不仅负责类的加载,还涉及类的验证、初始化等一系列过程。理解...

    java中ClassLoader

    2. Extension ClassLoader:称为扩展类加载器,负责加载 Java 的扩展类库,默认加载 JAVA_HOME/jre/lib/ext/ 目下的所有 jar 文件,以及将 -Djava.ext.dirs 指定的目录下的 jar 文件加载进去。 3. App ClassLoader...

    java文件的加载

    无论是基于Java本身的类加载机制还是通过Spring等框架提供的便捷方式,都能够有效地实现资源文件的加载与管理。在实际开发中,理解这些机制的工作原理是非常重要的,它能够帮助我们更高效地进行开发工作。

    【IT十八掌徐培成】Java基础第25天-04.classLoader-系统资源-不可见类访问.zip

    Bootstrap ClassLoader主要负责加载JDK核心库(rt.jar)中的类,Extension ClassLoader则加载JRE的扩展目录下的jar文件,而App ClassLoader则加载用户类路径(classpath)中的类。 当一个类被引用时,ClassLoader会...

    浅析ClassLoader

    在Java世界中,ClassLoader是运行时加载类的核心机制,它负责将类的.class文件加载到JVM中,使得程序能够运行。本文将深入剖析ClassLoader的工作原理,以及其在实际开发中的应用。 一、ClassLoader基础 1. 类加载...

    class文件热加载,上传class文件实现热加载

    - 在热加载场景下,自定义类加载器通常会监听某个文件系统或网络资源的变化,一旦检测到新版本的class文件,就立即加载。 3. **热加载原理**: - 热加载的核心是替换旧的类定义,而不是重新启动应用。这需要在...

    java classloader classpath 张孝祥

    类加载器(`ClassLoader`)负责将编译后的`.class`文件加载到Java虚拟机(JVM)中执行,而类路径(`ClassPath`)则是指明了这些`.class`文件的位置。本文主要围绕Java类加载器和类路径展开讨论,以加深对Java运行时...

    classloader的简单实现

    在"my_classloader"文件中,可能包含了这个类加载器的源代码、测试用例或其他相关资源。分析这些文件可以帮助我们更好地理解C++类加载器的具体实现细节,包括它是如何处理类的加载、解析和实例化的。 总之,类加载...

    java 读取资源文件

    资源文件通常存储在项目的类路径(classpath)下,可以是.properties、.txt、.xml等形式,它们提供了与代码分离的配置选项。对于.properties文件,Java提供了一个内置的Properties类来管理和读取这些文件。 1. **...

    深入理解ClassLoader工作机制.docx

    1. **加载**:加载是ClassLoader工作的起点,它从文件系统或网络中找到类的二进制数据,然后创建一个对应的Class对象。这个过程可以通过自定义ClassLoader来实现,比如从数据库中加载类。 2. **验证**:验证是确保...

    java classloader

    `CH_05.package与import机制.pdf`可能讲解了与ClassLoader相关的包和导入机制,因为它们与类的组织和加载密切相关。 `CH_03.Java与MS Office.pdf`、`CH_04.用Visual Studio.net来操控Java虚拟机.pdf`、`CH_06.Ant....

    Android Classloader测试demo

    在Android系统中,Classloader(类加载器)是至关重要的组件,它负责查找并加载Java类到Dalvik或ART运行时环境。这个测试demo是为了帮助开发者深入理解Android中两种主要的类加载器:DexClassLoader和...

    lassLoader的关系以及如何防止ClassLoader内存泄漏

    在Java世界中,类加载器(ClassLoader)是关键的组件之一,它负责将类的字节码文件(.class)从文件系统或网络中加载到Java虚拟机(JVM)中,使得程序能够运行。本篇文章将深入探讨ClassLoader的关系网络以及如何...

    插件化:动态加载类(无法加载资源)

    3. **合并Dex和资源**:在运行时将插件的dex和资源文件合并到主程序的进程中,这样所有的类和资源都可以在同一个ClassLoader下加载。但这可能会增加内存消耗,需要权衡利弊。 4. **使用独立进程**:让插件在独立的...

    Spring中使用classpath加载配置文件浅析

    如果存在同名的配置文件,但位于不同的位置,根据Spring加载类路径资源的策略,可能会加载到一个错误的文件。为了避免这种情况,开发者需要仔细设计自己的目录结构,并确保配置文件的命名和位置唯一,以避免冲突。 ...

    Understanding the Java ClassLoader

    ### Java ClassLoader理解详解 ...自定义ClassLoader不仅能够扩展JVM的功能,还能够在实际项目中解决特定问题,如动态加载远程资源、加密类文件等。希望这篇教程能为你提供足够的背景知识,以便在实践中应用这些技术。

Global site tag (gtag.js) - Google Analytics