If javac encounters a class file on the classpath that is empty, it generates a "bad class file" as expected but then goes on to claim the "class file contains wrong class: java.lang.AutoCloseable".
There are several problems with the utility classes used by the compiler, and this error is a symptom of one of them.
The problems identified are:
*** ArrayUtils.java ***
1. There is no protection from integer overflows, which can occur in several places. We should add a few basic checks so at least we fail fast with IllegalArgumentException instead of fail slow with ArrayIndexOutOfBoundsException.
2. If ensureCapacity() were ever invoked on an array of length zero, an infinite loop would result.
*** ByteBuffer.java ***
1. The methods getInt(), getLong(), etc. do not check for data underflow (this is the root cause of the weird error above).
2. The appendStream() method only reads input.available() bytes from the InputStream, which is totally broken. To quote the Javadoc from InputStream.available(): "Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream." That's exactly what this method does. So this could easily break when retrieving class files from non-standard sources.
*** ClassReader.java, ModuleNameReader.java, PoolReader.java ***
It's not clear that these classes have systematic protection against truncated class files. Truncated files generate various different warnings, including:
- index 25926 is not within pool size 13
- bad constant pool tag: 0 at 28317
- unexpected constant pool tag: 10 at 11
- class file is invalid for class Empty
- class file contains wrong class: java.lang.AutoCloseable
All of the above errors were triggered by simply truncating the class file at various points. It would be better if a "truncated class file" error were generated whenever a truncated class file is encountered (i.e., whenever the compiler tries to read past the end of a class file).
There are several problems with the utility classes used by the compiler, and this error is a symptom of one of them.
The problems identified are:
*** ArrayUtils.java ***
1. There is no protection from integer overflows, which can occur in several places. We should add a few basic checks so at least we fail fast with IllegalArgumentException instead of fail slow with ArrayIndexOutOfBoundsException.
2. If ensureCapacity() were ever invoked on an array of length zero, an infinite loop would result.
*** ByteBuffer.java ***
1. The methods getInt(), getLong(), etc. do not check for data underflow (this is the root cause of the weird error above).
2. The appendStream() method only reads input.available() bytes from the InputStream, which is totally broken. To quote the Javadoc from InputStream.available(): "Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream." That's exactly what this method does. So this could easily break when retrieving class files from non-standard sources.
*** ClassReader.java, ModuleNameReader.java, PoolReader.java ***
It's not clear that these classes have systematic protection against truncated class files. Truncated files generate various different warnings, including:
- index 25926 is not within pool size 13
- bad constant pool tag: 0 at 28317
- unexpected constant pool tag: 10 at 11
- class file is invalid for class Empty
- class file contains wrong class: java.lang.AutoCloseable
All of the above errors were triggered by simply truncating the class file at various points. It would be better if a "truncated class file" error were generated whenever a truncated class file is encountered (i.e., whenever the compiler tries to read past the end of a class file).