ClassLoader.getSystemResourceAsStream("a.txt")获取不到资源文件
一、解决方案
换成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")获取不到资源文件的更多相关文章
- Assembly.GetManifestResourceNames()获取不到资源文件
Assembly.GetManifestResourceNames()获取到的是嵌入的资源文件 右键资源文件属性 将生成操作改为嵌入的资源就OK咯
- Linux 获取设备树源文件(DTS)里描述的资源
Linux 获取设备树源文件(DTS)里的资源 韩大卫@吉林师范大学 在linux使用platform_driver_register() 注册 platform_driver 时, 需要在 plat ...
- ClassLoader.getSystemResourceAsStream()
一: 要加载的文件和.class文件在同一目录下,例如:com.x.y 下有类Test.class ,同时有资源文件config.properties 那么,应该有如下代码: //前面没有" ...
- Xamarin.iOS模拟器调试找不到资源文件
Xamarin.iOS模拟器调试找不到资源文件 在Visual Studio 2015中,运行Xamarin.iOS项目,出现找不到资源文件的错误.错误信息:System.IO.FileNotFoun ...
- Android 4.1源码编译找不到资源文件解决办法
我们在Android framework中修改资源文件时,在Android 4.0之前,都是直接在sourcecode/frameworks/base/core/res/res下面添加对应的资源文件, ...
- className.class.getResourceAsStream与ClassLoader.getSystemResourceAsStream区别
className.class.getResourceAsStream : 一: 要加载的文件和.class文件在同一目录下,例如:com.x.y 下有类Test.class ,同时有资源文件conf ...
- java 路径、className.class.getResourceAsStream()、ClassLoader.getSystemResourceAsStream() 、FileInputStream
className.class.getResourceAsStream 用法: 第一: 要加载的文件和.class文件在同一目录下,例如:com.x.y 下有类Test.class ,同时有资源文件c ...
- Linux 获取设备树源文件(DTS)里的资源【转】
本文转载自:http://blog.csdn.net/keleming1/article/details/51036000 http://www.cnblogs.com/dyllove98/archi ...
- web页面找不到资源文件,报404,但是资源文件存在且路径没错
如题 , 今天遇到这个问题,maven项目导入本地myeclipse,正常跑起来之后,在web端存在部分页面资源加载不进来. 但是项目资源确实存在,一开始以为是myeclipse开发环境搭建错误导致, ...
随机推荐
- POJ3974Palindrome(Manacher)
传送门 题目大意:求最长回文串 题解:Manacher 代码: #include<cstdio> #include<cstring> #include<iostream& ...
- COM 编程基础
DirectX 采用了 COM 标准.而 DirectShow 是一套完全基于 COM 的应用系统.要想深入学习 DirectShow,掌握一些 COM 编程的基础知识是必不可少的. 一.COM 是什 ...
- 正确使用Spring Data JPA规范
在优锐课的学习分享中探讨了关于,Spring Data JPA的创建主要是为了通过按方法名称生成查询来轻松创建查询. 但是,有时我们需要创建复杂的查询,而无法利用查询生成器.码了很多知识笔记分享给大家 ...
- JVM基础详解
JVM基础解析(一) Java里面有 JDK ,JRE, JVM ,这三者的关系是怎么样的呢? JDK是编译时环境: 整个Java的核心,包括了Java运行环境JRE.Java工具和Java基础类库 ...
- 15-scrapy-redis两种形式分布式爬虫
什么叫做分布式爬虫? 分布式爬虫,就是多台机器共用一个scrapy—redis程序高效爬取数据, 为啥要用分布式爬虫? 其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器 ...
- oracle多表关联update
日常的开发中一般都是写的单表update语句,很少写多表关联的update. 不同于SQL Server,在Oracle中,update的多表连接更新和select的多表连接查询在使用的方法上存在较大 ...
- 自定义Visual Studio调试器中的对象显示方式
你有没有盯着调试器窗口中的对象,并希望你可以通过其他类型的东西来查看这些对象?我当然有!扩展项目以确定每个人的身份可能会非常快速.理想情况下,通过特定的属性值快速定位它们会很棒.对我们来说幸运的是,V ...
- Docker是什么、为什么是一种趋势
Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来.并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响.那么我就不需要专门运送水果的船和专门运 ...
- centos 7 搭建vsftp
一.FTP简介 1.ftp 概述 FTP:(file transfer protocol文件传输协议) ...
- mysql 是否走索引问题
问题探讨 : 当一列包含null 值时, is null 和 is not null 查询是否走索引 当用 != 时是否走索引 当用in时是否走索引 结论:当 查询范围比较小时, 以上枚举的都走索 ...