一、解决方案

换成XXX.class.getClassLoader().getResourceAsStream("a.txt")即可。

二、场景复现

src/main/resource下存在文件a.txt,项目类中static 方法中读取该文件。ClassLoader.getSystemResourceAsStream("a.txt")获取不到资源文件

三、原因剖析

getResourceAsStream会先使用本类的类加载器去加载,本类没有类加载器,才会使用系统类加载器。也就是说getResourceAsStream功能覆盖了getSystemResourceAsStream,所以推荐直接使用getResourceAsStream就完事了。都不需要知道具体两者有啥区别。

下面我们来细看有啥区别....

3.1 java类加载器

  • 1.启动类加载器(Bootstrap ClassLoader):顶层的类加载器,没有父类加载器。负责加载 /lib 目录下的,或被 -Xbootclasspath 参数所指定路径中的,并被 JVM 识别的(仅按文件名识别,如 rt.jar,名字不符合的类库即使放在 lib 目录也不会被加载)类库加载到虚拟机内存中。所有被 Bootstrap classloader 加载的类,它的 Class.getClassLoader 方法返回的都是 null,所以也称作 NULL ClassLoader。
  • 2.扩展类加载器(Extension CLassLoader):由 sun.misc.Launcher$ExtClassLoader 实现,负责加载 <JAVA_HOME>/lib/ext 目录下,或被 java.ext.dirs 系统变量所指定的目录下的所有类库;
  • 3.应用程序类加载器(Application/System ClassLoader):由 sun.misc.Launcher$AppClassLoader 实现。它是 ClassLoader.getSystemClassLoader() 方法的默认返回值,所以也称为系统类加载器(System ClassLoader)。它负责加载 classpath 下所指定的类库,如果应用程序没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

3.2 tomcat容器下类加载器

Tomcat官方说明:Class Loader HOW-TO

跟普通的java程序相比,类加载大体顺序相同。

  • 1.Bootstrap 启动类加载器: 加载JVM启动所需的类+系统扩展目录($JAVA_HOME/jre/lib/ext)里 JAR 文件中的类。
  • 2.System 系统类加载器:从 CLASSPATH 系统变量指定的目录中加载类库。该加载器加载的类对 tomcat 本身和 web 应用都可见。但是,标准的 tomcat 启动脚本($CATALINA_HOME/bin/catalina.sh or %CATALINA_HOME%\bin\catalina.bat)都会忽略系统变量 CLASSPATH 的值,而会使用如下的类库来创建 System 类加载器:

      $CATALINA_HOME/bin/bootstrap.jar

    $CATALINA_BASE/bin/tomcat-juli.jar 或 $CATALINA_HOME/bin/tomcat-juli.jar

    $CATALINA_HOME/bin/commons-daemon.jar

  • 3.Common 通用类加载器:通过该类加载器加载的类库可被 Tomcat 和所有应用共享。该类加载器的搜索位置是通过 $CATALINA_BASE/conf/catalina.properties 文件中的 common.loader 属性指定的,默认包括如下位置:

    $CATALINA_BASE/lib 下未打包的类和资源;

     $CATALINA_BASE/lib 下的 jar 包;

    $CATALINA_HOME/lib 下未打包的类和资源;

    $CATALINA_HOME/lib 下的 jar 包。

  • 4.WebappX 应用类加载器:每个 Web 应用创建一个自己的类加载器,加载自己项目下的数据: /WEB-INF/classes 和 /WEB-INF/lib 下的类和资源。并且不使用双亲委派机制,先自己加载,加载不到才使用父类加载器。

本来顺序是1234,但是WebappX不使用委派机制而是先自己加载,加载不了才使用父类,所以真实的顺序是:

  • Bootstrap classes of your JVM
  • /WEB-INF/classes of your web application
  • /WEB-INF/lib/*.jar of your web application
  • System class loader classes (described above)
  • Common class loader classes (described above)

tomcat8支持委托:配置允许委派:<Loader delegate="true"/>,顺序变为:

  • Bootstrap classes of your JVM
  • System class loader classes (described above)
  • Common class loader classes (described above)
  • /WEB-INF/classes of your web application
  • /WEB-INF/lib/*.jar of your web application

3.3 问题回归

tomcat容器中运行的java程序,使用系统类加载器是不能获取到资源的,必须使用WebappClassLoader。使用getResourceAsStream获取当前类的类加载器,也就是WebappClassLoader,自然可以获取到资源了。


=======参考=========

https://blog.csdn.net/w1196726224/article/details/54428493

ClassLoader.getSystemResourceAsStream("a.txt")获取不到资源文件的更多相关文章

  1. Assembly.GetManifestResourceNames()获取不到资源文件

    Assembly.GetManifestResourceNames()获取到的是嵌入的资源文件 右键资源文件属性 将生成操作改为嵌入的资源就OK咯

  2. Linux 获取设备树源文件(DTS)里描述的资源

    Linux 获取设备树源文件(DTS)里的资源 韩大卫@吉林师范大学 在linux使用platform_driver_register() 注册 platform_driver 时, 需要在 plat ...

  3. ClassLoader.getSystemResourceAsStream()

    一: 要加载的文件和.class文件在同一目录下,例如:com.x.y 下有类Test.class ,同时有资源文件config.properties 那么,应该有如下代码: //前面没有" ...

  4. Xamarin.iOS模拟器调试找不到资源文件

    Xamarin.iOS模拟器调试找不到资源文件 在Visual Studio 2015中,运行Xamarin.iOS项目,出现找不到资源文件的错误.错误信息:System.IO.FileNotFoun ...

  5. Android 4.1源码编译找不到资源文件解决办法

    我们在Android framework中修改资源文件时,在Android 4.0之前,都是直接在sourcecode/frameworks/base/core/res/res下面添加对应的资源文件, ...

  6. className.class.getResourceAsStream与ClassLoader.getSystemResourceAsStream区别

    className.class.getResourceAsStream : 一: 要加载的文件和.class文件在同一目录下,例如:com.x.y 下有类Test.class ,同时有资源文件conf ...

  7. java 路径、className.class.getResourceAsStream()、ClassLoader.getSystemResourceAsStream() 、FileInputStream

    className.class.getResourceAsStream 用法: 第一: 要加载的文件和.class文件在同一目录下,例如:com.x.y 下有类Test.class ,同时有资源文件c ...

  8. Linux 获取设备树源文件(DTS)里的资源【转】

    本文转载自:http://blog.csdn.net/keleming1/article/details/51036000 http://www.cnblogs.com/dyllove98/archi ...

  9. web页面找不到资源文件,报404,但是资源文件存在且路径没错

    如题 , 今天遇到这个问题,maven项目导入本地myeclipse,正常跑起来之后,在web端存在部分页面资源加载不进来. 但是项目资源确实存在,一开始以为是myeclipse开发环境搭建错误导致, ...

随机推荐

  1. POJ3974Palindrome(Manacher)

    传送门 题目大意:求最长回文串 题解:Manacher 代码: #include<cstdio> #include<cstring> #include<iostream& ...

  2. COM 编程基础

    DirectX 采用了 COM 标准.而 DirectShow 是一套完全基于 COM 的应用系统.要想深入学习 DirectShow,掌握一些 COM 编程的基础知识是必不可少的. 一.COM 是什 ...

  3. 正确使用Spring Data JPA规范

    在优锐课的学习分享中探讨了关于,Spring Data JPA的创建主要是为了通过按方法名称生成查询来轻松创建查询. 但是,有时我们需要创建复杂的查询,而无法利用查询生成器.码了很多知识笔记分享给大家 ...

  4. JVM基础详解

    JVM基础解析(一) Java里面有 JDK ,JRE, JVM ,这三者的关系是怎么样的呢? JDK是编译时环境: 整个Java的核心,包括了Java运行环境JRE.Java工具和Java基础类库 ...

  5. 15-scrapy-redis两种形式分布式爬虫

    什么叫做分布式爬虫? 分布式爬虫,就是多台机器共用一个scrapy—redis程序高效爬取数据, 为啥要用分布式爬虫? 其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器 ...

  6. oracle多表关联update

    日常的开发中一般都是写的单表update语句,很少写多表关联的update. 不同于SQL Server,在Oracle中,update的多表连接更新和select的多表连接查询在使用的方法上存在较大 ...

  7. 自定义Visual Studio调试器中的对象显示方式

    你有没有盯着调试器窗口中的对象,并希望你可以通过其他类型的东西来查看这些对象?我当然有!扩展项目以确定每个人的身份可能会非常快速.理想情况下,通过特定的属性值快速定位它们会很棒.对我们来说幸运的是,V ...

  8. Docker是什么、为什么是一种趋势

    Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来.并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响.那么我就不需要专门运送水果的船和专门运 ...

  9. centos 7 搭建vsftp

    一.FTP简介 1.ftp 概述                                                FTP:(file  transfer  protocol文件传输协议) ...

  10. mysql 是否走索引问题

    问题探讨 : 当一列包含null 值时, is null  和 is not null  查询是否走索引 当用 != 时是否走索引 当用in时是否走索引 结论:当 查询范围比较小时, 以上枚举的都走索 ...