为什么 InputStreamReader 从 jar 读取时会抛出 NPE?
我正在尝试使用流迭代已知目录中的类文件。最终目标是获取特定包中存在的所有类的类名,然后在运行时加载这些类并使用反射来获取名称和类名。所有静态常量的值。当我在机器上从源代码运行该程序时,这是有效的,但是当我将其作为 jar 运行时,BufferedReader 会从 ready() 和 readLine 中抛出 NPE ()。下面是代码(为简洁起见,省略了错误处理和最佳实践):
private void printClassNamesInPackage(final String strPackage) throws Exception {
// The returned implementation of InputStream seems to be at fault
final InputStream packageStream = getClass().getClassLoader().getResourceAsStream( strPackage );
final InputStreamReader streamReader = new InputStreamReader( packageStream );
final BufferedReader reader = new BufferedReader( streamReader );
// Throws NPE from inside ready() - SEE STACKTRACE BELOW
// reader.ready()
String strLine;
// Throws NPE from inside readLine() - SEE STACKTRACE BELOW
while ( null != (strLine = reader.readLine()) ) {
System.out.println( strLine );
}
}
来自 reader.ready() 的堆栈跟踪
:
java.lang.NullPointerException
at java.io.FilterInputStream.available(FilterInputStream.java:142)
at sun.nio.cs.StreamDecoder.inReady(StreamDecoder.java:343)
at sun.nio.cs.StreamDecoder.implReady(StreamDecoder.java:351)
at sun.nio.cs.StreamDecoder.ready(StreamDecoder.java:165)
at java.io.InputStreamReader.ready(InputStreamReader.java:178)
at java.io.BufferedReader.ready(BufferedReader.java:436)
来自 reader 的堆栈跟踪。 readLine()
:
java.lang.NullPointerException
at java.io.FilterInputStream.read(FilterInputStream.java:116)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
单步执行会显示以下 InputStream
实现:
- 来自源代码:
java.io.ByteArrayInputStream
- 来自 jar:
sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream
进一步查看 JarURLInputStream
我发现继承的(来自 FilterInputStream
)字段 InputStream in
为 null
,这会导致生成的 NPE。
不幸的是,这已经是我在调试器中所能达到的深度了。
关于如何正确执行此操作有什么想法吗?我错过了什么或做错了什么?谢谢你!
I'm trying to iterate over the class files in a known directory using streams. The ultimate goal is to obtain the class names for all classes that exist in a particular package, then load the classes at runtime and use reflection to obtain the names & values of all the static constants. This works when I run the program from source on my machine, but when I run it as a jar the BufferedReader
throws a NPE from both ready()
and readLine()
. Here's the code (with error handling & best practices omitted for brevity):
private void printClassNamesInPackage(final String strPackage) throws Exception {
// The returned implementation of InputStream seems to be at fault
final InputStream packageStream = getClass().getClassLoader().getResourceAsStream( strPackage );
final InputStreamReader streamReader = new InputStreamReader( packageStream );
final BufferedReader reader = new BufferedReader( streamReader );
// Throws NPE from inside ready() - SEE STACKTRACE BELOW
// reader.ready()
String strLine;
// Throws NPE from inside readLine() - SEE STACKTRACE BELOW
while ( null != (strLine = reader.readLine()) ) {
System.out.println( strLine );
}
}
The stacktrace from reader.ready()
:
java.lang.NullPointerException
at java.io.FilterInputStream.available(FilterInputStream.java:142)
at sun.nio.cs.StreamDecoder.inReady(StreamDecoder.java:343)
at sun.nio.cs.StreamDecoder.implReady(StreamDecoder.java:351)
at sun.nio.cs.StreamDecoder.ready(StreamDecoder.java:165)
at java.io.InputStreamReader.ready(InputStreamReader.java:178)
at java.io.BufferedReader.ready(BufferedReader.java:436)
The stacktrace from reader.readLine()
:
java.lang.NullPointerException
at java.io.FilterInputStream.read(FilterInputStream.java:116)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
Stepping through the execution reveals the following InputStream
implementations:
- From source:
java.io.ByteArrayInputStream
- From jar:
sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream
Looking further into JarURLInputStream
I find that the inherited (from FilterInputStream
) field InputStream in
is null
, which leads to the resulting NPE.
Unfortunately, that's as deep as I was able to get in the debugger.
Any ideas on how to properly do this? What am I missing or doing wrong? Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
文件夹不会返回包含所有文件或其他内容的某些列表的
InputStream
。使用JarInputStream
以编程方式提取 JAR。您可以在此处找到示例。作为参考,这里有一个稍微修改过的相关摘录:Folders don't return an
InputStream
with some list of all files or something. UseJarInputStream
to extract the JAR programmatically. You can find an example here. For reference, here's a slight modified extract of relevance: