ADDITIONAL SYSTEM INFORMATION :
Oracle java 1.8
Oracle java9
Oracle jdk 10
openjdk11
openjdk12
openjdk13
openjdk14-early-access
NAME="Ubuntu"
VERSION="19.04 (Disco Dingo)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 19.04"
VERSION_ID="19.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=disco
UBUNTU_CODENAME=disco
Also happens on Linux 18.04 and our embedded 32bit linux Arms products
A DESCRIPTION OF THE PROBLEM :
File.newInputStream cannot be used with linux character device files
We have for years been using FileInputStream for reading from actual uart devices in linux. Recently as directed by static analysis tools we changed to use Files.newInputStream, which seemed fine initially. But during further testing it was revealed that the implementation of the inputstream returned from the Files.newInputStream uses IO calls that causes Illegal seek IOExceptions under some circumstances when reading from the stream.
class sun.nio.ch.ChannelInputStream
Exception in thread "main" java.io.IOException: Illegal seek
at java.base/sun.nio.ch.FileDispatcherImpl.seek0(Native Method)
at java.base/sun.nio.ch.FileDispatcherImpl.seek(FileDispatcherImpl.java:78)
at java.base/sun.nio.ch.FileChannelImpl.position(FileChannelImpl.java:339)
at java.base/sun.nio.ch.ChannelInputStream.available(ChannelInputStream.java:114)
at com.mycompany.mavenproject6.NewClass.main(NewClass.java:25)
It can be recreated with the using socat virtual pairs and the following java code (howeever isavailable() not being used in production code but looks like internal java code uses it in class returned by Files.newInputStream)
https://justcheckingonall.wordpress.com/2009/06/09/howto-vsp-socat/
final File f = new File("/dev/pts/3");
final InputStream in = Files.newInputStream(f.toPath());
//final InputStream in = new FileInputStream(f);
in.available();
For now the workaround is to revert back to FileInputStream, but it doesn't appear documented that you cannot use Files.newInputStream with character device files and findbugs/spotbugs are actively reporting an error if you use FileInputStream rather than the new apis.
Proposed solutions:
1) Document that only "normal-files" should be used, and link to FileInputStream
2) Internally check if file is not a normal file and not execute code that causes the issue
Oracle java 1.8
Oracle java9
Oracle jdk 10
openjdk11
openjdk12
openjdk13
openjdk14-early-access
NAME="Ubuntu"
VERSION="19.04 (Disco Dingo)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 19.04"
VERSION_ID="19.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=disco
UBUNTU_CODENAME=disco
Also happens on Linux 18.04 and our embedded 32bit linux Arms products
A DESCRIPTION OF THE PROBLEM :
File.newInputStream cannot be used with linux character device files
We have for years been using FileInputStream for reading from actual uart devices in linux. Recently as directed by static analysis tools we changed to use Files.newInputStream, which seemed fine initially. But during further testing it was revealed that the implementation of the inputstream returned from the Files.newInputStream uses IO calls that causes Illegal seek IOExceptions under some circumstances when reading from the stream.
class sun.nio.ch.ChannelInputStream
Exception in thread "main" java.io.IOException: Illegal seek
at java.base/sun.nio.ch.FileDispatcherImpl.seek0(Native Method)
at java.base/sun.nio.ch.FileDispatcherImpl.seek(FileDispatcherImpl.java:78)
at java.base/sun.nio.ch.FileChannelImpl.position(FileChannelImpl.java:339)
at java.base/sun.nio.ch.ChannelInputStream.available(ChannelInputStream.java:114)
at com.mycompany.mavenproject6.NewClass.main(NewClass.java:25)
It can be recreated with the using socat virtual pairs and the following java code (howeever isavailable() not being used in production code but looks like internal java code uses it in class returned by Files.newInputStream)
https://justcheckingonall.wordpress.com/2009/06/09/howto-vsp-socat/
final File f = new File("/dev/pts/3");
final InputStream in = Files.newInputStream(f.toPath());
//final InputStream in = new FileInputStream(f);
in.available();
For now the workaround is to revert back to FileInputStream, but it doesn't appear documented that you cannot use Files.newInputStream with character device files and findbugs/spotbugs are actively reporting an error if you use FileInputStream rather than the new apis.
Proposed solutions:
1) Document that only "normal-files" should be used, and link to FileInputStream
2) Internally check if file is not a normal file and not execute code that causes the issue
- relates to
-
JDK-8341666 FileInputStream doesn't support readAllBytes() or readNBytes(int) on pseudo devices
-
- Closed
-
- links to
-
Commit(master) openjdk/jdk/de92fe37
-
Review(master) openjdk/jdk/21508