Kotlin NPE with ArrayList<Byte>.toByteArray()


#1

Hello. I have got one strange exception:

03-21 12:39:03.308 30540-30654/com.package.android.app E/LoadTask: Unexpected exception loading stream
java.lang.NullPointerException: Attempt to invoke virtual method 'byte java.lang.Number.byteValue()' on a null object reference
    at kotlin.collections.CollectionsKt___CollectionsKt.toByteArray(_Collections.kt:904)
    at com.package.android.app.record.BytesSniffer.makeNewVideoAndSave(BytesSniffer.kt:97)
    at com.package.android.app.record.BytesSniffer.onBytesRead(BytesSniffer.kt:83)
    at com.package.android.app.play.TestHttpDataSource.readInternal(TestHttpDataSource.kt:54)
    at com.package.android.app.play.DefaultHttpDataSource.read(DefaultHttpDataSource.java:258)
    at com.google.android.exoplayer2.extractor.DefaultExtractorInput.readFromDataSource(DefaultExtractorInput.java:257)
    at com.google.android.exoplayer2.extractor.DefaultExtractorInput.readFully(DefaultExtractorInput.java:70)
    at com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor.readAtomHeader(FragmentedMp4Extractor.java:301)
    at com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor.read(FragmentedMp4Extractor.java:275)
    at com.google.android.exoplayer2.source.chunk.ContainerMediaChunk.load(ContainerMediaChunk.java:112)
    at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:315)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
    at java.lang.Thread.run(Thread.java:764)

My code:

class SomeClass {

    private val audioBytes = arrayListOf<Byte>()
    private val videoBytes = arrayListOf<Byte>()

    /* some code */

    fun someAsyncFun(buffer: ByteArray) {
        // ...
        for (index in N until M) {
            if (moonPhase == LUNE_PHASE_FULL)
                audioBytes.add(buffer[index])
            else
                videoBytes.add(buffer[index])
        }
        // ...
        someAnotherFun()
    }

    fun someAnotherFun() {
        // ...
        val audio = ArrayList(audioBytes).toByteArray() // audioBytes is ArrayList<Byte>
        val video = ArrayList(videoBytes).toByteArray() // same
        audioBytes.clear()
        videoBytes.clear()
        // ...
    }
/* some code */
}

buffer came from Java as byte[] and buffer[index] can’t be null.
Why this error causes and how to fix this? Thanks.


#2

Are you sure you’re not adding null to audioBytes somewhere? Even if buffer[index] can’t be null, there must be something else adding nulls in there.


#3

There are only two usages of audioBytes and videoBytes — and them both are presented in question above.


#4

I don’t believe you, then. At very least, you haven’t shown the declaration and instantiation of them.


#5

Okay, I don’t care, if you believe me or not. My class has < 100 lines of code and I able to find usages of one field…


#6

In case if you’re manipulating videoBytes and audioBytes arraylists from different threads concurrently without a proper synchronization, you may observe an inconsistent state, for example having null elements in them.


#7

If I will use something like CopyOnWriteArrayList, the error wouldn’t occurs anymore?