Hi all,
I want to load a very large test case (> 3GB) into JMeter. However, a
NegativeArraySizeException is thrown inside a BufferedInputStream while reading
the file.*
In this mail, I describe the cause of the error, have a guess why JMeter works
this way and suggest a patch.
Why does this occur?
1) JMeter's SaveService#readTree wraps the InputStream it receives in a
BufferedInputStream (BIS).
2) It then tells the BIS to save all read data in memory up to a size of
Integer.MAX_VALUE by calling reader.mark(Integer.MAX_VALUE).
3) XStream successfully reads in bytes from the BIS. As requested in 2), the
BIS saves all the bytes read into an array buffer.
4) As the file is large, the BIS at some point calculates a buffer size
exceeding the integer range. This integer is mapped to a negative value
(integer overflow).
5) BIS tries to allocate a byte buffer with this negative size, yielding the
error.
In my understanding of SaveService#readTree, the BIS wrapping was introduced to
fall back to the old Avalon format: In case loading the .jmx failed, the BIS
was reset to the beginning of the file and the OldSaveService tried loading the
file. So the buffer was needed because a FileInputStream normally doesn't
support marking.
Reading the JMeter 3.0 Changelist, the *.jtl import is dropped. XStream does
not depend on the InputStream being a BIS. So I guess it is safe to remove the
BIS wrapping avoiding the above bug. See the patch below for my suggestion.**
How should I proceed? Report a bug in Bugzilla?
Thanks,
Felix Draxler
*Java 8 will instead throw a OutOfMemoryError "Required array size too large"
for very similar reasons, but later in the execution. In this mail, I describe
the situation with Java 7.
**Possible patch for SaveService.java:
- if (!reader.markSupported()) {
- reader = new BufferedInputStream(reader);
- }
- reader.mark(Integer.MAX_VALUE);