Java类加载器错误:由以下原因引起:java.io.IOException:流已关闭 [英] Java class loader bug: Caused by: java.io.IOException: Stream closed
问题描述
当我将Webapp部署到Tomcat时,我遇到一个奇怪的错误,即我认为类加载器存在问题.当我使用Jetty在本地运行Webapp时,该错误没有出现.似乎我的.yml资源文件的输入流由于某些原因而被关闭,而不应这样做.当我尝试将单模块项目转换为多模块项目时,首次出现此错误.在此之前,它使用完全相同的代码在Tomcat上运行良好:
I'm getting a strange bug regarding I believe class loader issues when I deploy my webapp to Tomcat. The bug doesn't appear when I run my webapp locally using Jetty. It seems like my input streams for my .yml resource files are being closed for some reason when they shouldn't be. This bug first appeared when I tried to convert my single module project into a multi module project. Before that, it was working fine on Tomcat using the exact same code:
Caused by: org.yaml.snakeyaml.error.YAMLException: java.io.IOException: Stream closed
at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:200)
at org.yaml.snakeyaml.reader.StreamReader.<init>(StreamReader.java:60)
at org.yaml.snakeyaml.Yaml.load(Yaml.java:412)
at com.config.ConfigProvider.<init>(ConfigProvider.java:20)
... 49 more
Caused by: java.io.IOException: Stream closed
at java.io.PushbackInputStream.ensureOpen(PushbackInputStream.java:57)
at java.io.PushbackInputStream.read(PushbackInputStream.java:149)
at org.yaml.snakeyaml.reader.UnicodeReader.init(UnicodeReader.java:90)
at org.yaml.snakeyaml.reader.UnicodeReader.read(UnicodeReader.java:122)
at java.io.Reader.read(Reader.java:123)
at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:184)
... 55 more
以下是导致该错误的行:
Here's the line that causes the bug:
String s = ConfigProvider.getConfig().getString("test");
这是ConfigProvider
类.它基本上扫描正则表达式^.*\\.config\\.yml$
的所有资源文件,将其转换为Map<String, Object>
,并将所有获得的Map<String, Object>
组合为单个Map<String, Object>
:
Here's the ConfigProvider
class. It basically scans for all resource files of regex ^.*\\.config\\.yml$
, converts it into a Map<String, Object>
, and combines all the obtained Map<String, Object>
into a single Map<String, Object>
:
1 public class ConfigProvider {
2 protected static final String CONFIG_PACKAGE = ConfigProvider.class.getPackage().getName();
3 protected static final Pattern CONFIG_PATH_REGEX = Pattern.compile("^.*\\.config\\.yml$");
4
5 private static final ConfigProvider INSTANCE = new ConfigProvider();
6 private Map<String, Object> configMap;
7
8 protected ConfigProvider() {
9 configMap = new HashMap<String, Object>();
10
11 Set<String> configPaths = new Reflections(CONFIG_PACKAGE,
12 new ResourcesScanner()).getResources(CONFIG_PATH_REGEX);
13
14 if (configPaths.isEmpty()) {
15 throw new RuntimeException("no config paths found");
16 }
17
18 for (String path : configPaths) {
19 InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
20 Map<String, Object> fullConfig = new Map<String, Object>((Map) new Yaml().load(inputStream));
21
22 try {
23 inputStream.close();
24 } catch (IOException e) {
25 throw new RuntimeException("error closing stream");
26 }
27
28 MapUtils.merge(configMap, fullConfig);
29 }
30 }
31
32 public static ConfigMap getConfig() {
33 return INSTANCE.configMap;
34 }
35 }
这是我的项目结构,名为Foo:
Here's my project structure, titled Foo:
- Foo (this is a module)
- .idea
- application (this is a module)
- src
- main
- java
- resources
- application.config.yml
- webapp
- test
- pom.xml
- client (this is a module)
- src
- main
- java
- resources
- client.config.yml
- webapp
- test
- pom.xml
- pom.xml
ConfigProvider
是我从父pom文件(Foo/pom.xml
)获得的类.我从application
模块(Foo/application/target/application.war
)打包了一个WAR
文件,并与Tomcat一起部署了它.以前,我的项目是单个模块项目,只有一个Foo
模块与application
模块相同.然后,我添加了一个client
模块并将该项目转换为一个多模块项目,问题出现了.我认为这是因为多个模块使我的类加载器变得一团糟.我已经花了很多时间尝试调试它,但仍然没到任何地方.任何人都知道可能是什么原因,或者可以想到可以尝试的事情吗?
ConfigProvider
is a class I get from my parent pom file (Foo/pom.xml
). I package a WAR
file from the application
module (Foo/application/target/application.war
), and deploy it with Tomcat. Previously, my project was a single module project with just a Foo
module being identical to application
module. Then I added a client
module and converted the project into a multi module project, and the problem has showed up. I think it's because my class loader is getting messed up due to the multiple modules. I've spent a lot of time trying to debug this and still haven't gotten anywhere. Anyone know what could be the cause, or can think of possible things to try?
如果您需要更多信息,请告诉我.
Please let me know if you need more info.
推荐答案
According to this post, that exception could mean that the .yml
file is simply not found. Since you changed your project structure, it is possible that the logic used to build the configPaths
needs to be modified for the new structure. Did you try to log the content of configPaths
to see if the paths are correct for the new structure?
还请确保.war
文件中包含.yml
文件.某些构建系统对资源的处理方式与Java类文件不同.
Also make sure that the .yml
files are included in the .war
file. Some build systems handle resources differently than java class files.
这篇关于Java类加载器错误:由以下原因引起:java.io.IOException:流已关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!