Почему InputStreamReader выбрасывает NPE при чтении из банки? - PullRequest
6 голосов
/ 17 мая 2011

Я пытаюсь перебрать файлы классов в известном каталоге, используя потоки. Конечная цель - получить имена классов для всех классов, которые существуют в конкретном пакете, затем загрузить классы во время выполнения и использовать отражение, чтобы получить имена и значения всех статических констант. Это работает, когда я запускаю программу из источника на моей машине, но когда я запускаю ее как jar, BufferedReader выбрасывает NPE из ready() и readLine(). Вот код (с кратким описанием обработки ошибок и передового опыта):

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
  • Из банки: sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream

Заглядывая дальше в JarURLInputStream, я обнаружил, что унаследованное (от FilterInputStream) поле InputStream in равно null, что приводит к полученному NPE.

К сожалению, это настолько глубоко, насколько я смог получить в отладчике.

Есть идеи, как правильно это сделать? Что я пропускаю или делаю неправильно? Спасибо!

1 Ответ

2 голосов
/ 17 мая 2011

Папки не возвращают 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;
}
...