BufferedInputStream на Android - ошибка недопустимого аргумента - PullRequest
0 голосов
/ 27 мая 2020

Я сейчас работаю над проектом, который использует 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.

Вопросы:

  1. Есть ли пробел в моем понимании, где оборачивать BufferedInputStream через FileDescriptor вообще невозможно? Я не пробовал того же на JVM.
  2. Или это Android уточняющий c нюанс? В таком случае, как преодолеть это и обеспечить буферизованное чтение.

Любая помощь приветствуется!

...