Я сейчас работаю над проектом, который использует VpnService
Android. Во время тестирования производительности я обнаружил, что чтение выполняется медленно из FileInputStream
, созданного мной с помощью FileDescriptor
, возвращенного методом establish()
. Мой рабочий фрагмент кода для того же самого показан ниже.
private val vpnIf0 = FileInputStream(fd)
suspend fun readVpnIf0(): IPDatagram = withContext(Dispatchers.IO) {
val bytes = ByteArray(BUFFER_SIZE)
val count = vpnIf0.read(bytes)
return@withContext IPMarshaller.marshal(bytes, count)
}
Пытаясь оптимизировать код, я заключил FileInputStream
в BufferedInputStream
следующим образом, сохранив все остальное без изменений.
private val vpnIf0 = BufferedInputStream(FileInputStream(fd))
Но теперь мой метод чтения перестал работать, и я получаю сообщение об ошибке.
Caught java.io.IOException: Invalid argument
at java.io.FileInputStream.available0(Native Method)
at java.io.FileInputStream.available(FileInputStream.java:389)
at java.io.BufferedInputStream.read(BufferedInputStream.java:355)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
Чтобы убедиться, что я не делаю ничего неправильного, я попробовал то же самое читать подход с файлом .txt
и BufferedInputStream
, и он работал как шарм. После дальнейшего изучения реализации FileInputStream
я вижу некоторые комментарии рядом с методом available()
, как показано ниже. Мне кажется, что Android использует немного измененную версию, чем стандартный JDK.
// BEGIN Android-changed: available() implementation changed from bare native.
public int available() throws IOException {
// Android-added: close() check before I/O.
if (closed) {
throw new IOException("Stream Closed");
}
return available0();
}
private native int available0() throws IOException;
// END Android-changed: available() implementation changed from bare native.
Примечание: У меня есть вариант использования BufferedInputStream
вместо FileInputStream
по FileDescriptor
в мире Android. Здесь FileDescriptor
- это виртуальный сетевой интерфейс /dev/tun0
.
Вопросы:
- Есть ли пробел в моем понимании, где оборачивать
BufferedInputStream
через FileDescriptor
вообще невозможно? Я не пробовал того же на JVM. - Или это Android уточняющий c нюанс? В таком случае, как преодолеть это и обеспечить буферизованное чтение.
Любая помощь приветствуется!