Why does InputStreamReader throw an NPE when reading from a jar?

I am trying to iterate over class files in a known directory using streams. The ultimate goal is to get the class names for all classes that exist in a particular package, and then load the classes at runtime and use reflection to get the names and values โ€‹โ€‹of all static constants. This works when I run the program from the source on my machine, but when I run it as a jar, the BufferedReader throws the NPE from ready() and readLine() . Here's the code (with error handling and 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 ); } } 

Stacktrace element 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) 

Stacktrace element 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) 

The execution execution shows the following InputStream implementations:

  • From source: java.io.ByteArrayInputStream
  • From jar: sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream

Looking further at the JarURLInputStream , I found that the inherited field (from FilterInputStream ) of InputStream in is null , which results in an NPE result.

Unfortunately, this is so deep that I was able to get into the debugger.

Any ideas on how to do this correctly? What am I missing or is something wrong? Thanks!

+6
source share
1 answer

Folders do not return an InputStream with some list of all files or anything like that. Use JarInputStream to retrieve the JAR programmatically. Here you can find an example here . For reference, here is a small 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; } 
+2
source

Source: https://habr.com/ru/post/888256/


All Articles