Skip to content

Large hprof trigger NegativeArraySizeException when being analyzed #2777

@phoenixuprising

Description

@phoenixuprising

Description

When analyzing a very large jvm hprof (the triggering hprof was 55gb from a web service), the shark-cli can throw a NegativeArraySizeException due to an int rollover when allocating a ByteArray if there are too many classes, instances, objects, or primitives.

====================================                                                     
STACKTRACE

java.lang.NegativeArraySizeException: -346802823
        at shark.internal.UnsortedByteEntries.append(UnsortedByteEntries.kt:32)
        at shark.internal.HprofInMemoryIndex$Builder.onHprofRecord(HprofInMemoryIndex.kt:592)
        at shark.StreamingHprofReader.readRecords(StreamingHprofReader.kt:246)
        at shark.internal.HprofInMemoryIndex$Companion.indexHprof(HprofInMemoryIndex.kt:777)
        at shark.HprofIndex$Companion.indexRecordsOf(HprofIndex.kt:34)
        at shark.HprofHeapGraph$Companion.openHeapGraph(HprofHeapGraph.kt:428)
        at shark.HprofHeapGraph$Companion.openHeapGraph$default(HprofHeapGraph.kt:425)
        at shark.HeapAnalyzer.analyze(HeapAnalyzer.kt:103)
        at shark.AnalyzeCommand$Companion.analyze(AnalyzeCommand.kt:36)
        at shark.AnalyzeCommand.run(AnalyzeCommand.kt:16)
        at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:139)
        at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:14)
        at com.github.ajalt.clikt.core.CliktCommand.parse(CliktCommand.kt:215)
        at com.github.ajalt.clikt.core.CliktCommand.parse$default(CliktCommand.kt:212)
        at com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:230)
        at com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:253)
        at shark.MainKt.main(Main.kt:13)
====================================
METADATA

Build.VERSION.SDK_INT: -1
Build.MANUFACTURER: Unknown
LeakCanary version: Unknown
Analysis duration: 0 ms
Heap dump file path: /Users/chayes/Development/temp/heap.hprof
Heap dump timestamp: 1760128375120
====================================

I added some print debugging and found the following:

EF_debug: classCount: 17570
EF_debug: instanceCount: 918610159
EF_debug: objectArrayCount: 16675920
EF_debug: primitiveArrayCount: 94124315

EF_debug: UnsortedByteEntries: entries = ByteArray( size = (currentCapacity=17570 * bytesPerEntry=30))
EF_debug: UnsortedByteEntries: entries = ByteArray( size = (currentCapacity=16675920 * bytesPerEntry=25))
EF_debug: UnsortedByteEntries: entries = ByteArray( size = (currentCapacity=918610159 * bytesPerEntry=23))

===================================================================================

Exception in thread "main" java.lang.NegativeArraySizeException: -346802823
        at shark.internal.UnsortedByteEntries.append(UnsortedByteEntries.kt:33)
        at shark.internal.HprofInMemoryIndex$Builder.onHprofRecord(HprofInMemoryIndex.kt:594)
        at shark.StreamingHprofReader.readRecords(StreamingHprofReader.kt:254)
        at shark.internal.HprofInMemoryIndex$Companion.indexHprof(HprofInMemoryIndex.kt:790)
        at shark.HprofIndex$Companion.indexRecordsOf(HprofIndex.kt:34)
        at shark.HprofHeapGraph$Companion.openHeapGraph(HprofHeapGraph.kt:423)
        at shark.HprofHeapGraph$Companion.openHeapGraph(HprofHeapGraph.kt:403)
        at shark.HprofHeapGraph$Companion.openHeapGraph$default(HprofHeapGraph.kt:399)
        at shark.InteractiveCommand.openHprof(InteractiveCommand.kt:135)
        at shark.InteractiveCommand.run(InteractiveCommand.kt:115)
        at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:139)
        at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:14)
        at com.github.ajalt.clikt.core.CliktCommand.parse(CliktCommand.kt:215)
        at com.github.ajalt.clikt.core.CliktCommand.parse$default(CliktCommand.kt:212)
        at com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:230)
        at com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:253)
        at shark.MainKt.main(Main.kt:14)

It appears to be trying to allocate a ~22gb ByteArray.

Steps to Reproduce

I don't have a sample hprof I can upload, both due to privacy/security as well as not being able to upload a 55gb file.

Version Information

  • LeakCanary version: 22bef70ba5abdba5f65935c1a37227d01be598d3 commit sha
  • Android OS version: N/A
  • Gradle version:
------------------------------------------------------------
Gradle 8.0
------------------------------------------------------------

Build time:   2023-02-13 13:15:21 UTC
Revision:     62ab9b7c7f884426cf79fbedcf07658b2dbe9e97

Kotlin:       1.8.10
Groovy:       3.0.13
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          24.0.1 (Oracle Corporation 24.0.1+9-30)
OS:           Mac OS X 26.0.1 aarch64

Additional Information

N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions