为什么 InputStreamReader 从 jar 读取时会抛出 NPE?

发布于 2024-11-07 18:29:04 字数 2481 浏览 3 评论 0原文

我正在尝试使用流迭代已知目录中的类文件。最终目标是获取特定包中存在的所有类的类名,然后在运行时加载这些类并使用反射来获取名称和类名。所有静态常量的值。当我在机器上从源代码运行该程序时,这是有效的,但是当我将其作为 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 innull,这会导致生成的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

苦行僧 2024-11-14 18:29:04

文件夹不会返回包含所有文件或其他内容的某些列表的 InputStream 。使用 JarInputStream 以编程方式提取 JAR。您可以在此处找到示例。作为参考,这里有一个稍微修改过的相关摘录:

public static List<String> getClassNamesInPackage(String jarName, String packageName) throws IOException {
    JarInputStream jarFile = new JarInputStream(new FileInputStream(jarName));
    packageName = packageName.replace(".", "/");
    List<String> classes = new ArrayList<String>();

    try {
        for (JarEntry jarEntry; (jarEntry = jarFile.getNextJarEntry()) != null;) {
            if ((jarEntry.getName().startsWith(packageName)) && (jarEntry.getName().endsWith(".class"))) {
                classes.add(jarEntry.getName().replace("/", "."));
            }
        }
    } finally {
        jarFile.close();
    }

    return classes;
}

Folders don't return an InputStream with some list of all files or something. Use JarInputStream to extract the JAR programmatically. You can find an example here. For reference, here's a slight modified extract of relevance:

public static List<String> getClassNamesInPackage(String jarName, String packageName) throws IOException {
    JarInputStream jarFile = new JarInputStream(new FileInputStream(jarName));
    packageName = packageName.replace(".", "/");
    List<String> classes = new ArrayList<String>();

    try {
        for (JarEntry jarEntry; (jarEntry = jarFile.getNextJarEntry()) != null;) {
            if ((jarEntry.getName().startsWith(packageName)) && (jarEntry.getName().endsWith(".class"))) {
                classes.add(jarEntry.getName().replace("/", "."));
            }
        }
    } finally {
        jarFile.close();
    }

    return classes;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文