Details
-
Type: Bug
-
Status: Closed (View Workflow)
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 1.6.1
-
Component/s: o.c.common.compress
-
Labels:None
-
Environment:
Android
Description
Android devices have very little memory and developers have to be very careful to avoid OutOfMemoryError. When I started using JSword on Android I often had OutOfMemoryErrors but they almost disappeared after this change.
Current JSword code in Zip.java uncompress(..)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedOutputStream out = new BufferedOutputStream(bos, expectedLength);
There are 2 possible improvements here:
1. the ByteArrayOutputStream constructor can be passed an expectedLength parameter to avoid up to 2 times the required amount of memory being allocated (it doubles the buffer size when it runs out).
2. Both the ByteArrayOutputStream and BufferedOutputStream use similar data structures to cache data (buf = new byte[size] and so it seems that the buffer is buffering a buffer so there is redundant buffering which would use twice the required amount of memory.
So the suggested replacement for the above is:
ByteArrayOutputStream out = new ByteArrayOutputStream(expectedLength);
which would require possibly one third of the memory of that required by the current JSword code.
The complete code that And Bible is currently using is here (only the first line in the method is modified):
public ByteArrayOutputStream uncompress(int expectedLength) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(expectedLength);
InflaterInputStream in = new InflaterInputStream(input, new Inflater(), expectedLength);
byte[] buf = new byte[expectedLength];
for (int count = in.read(buf); count != -1; count = in.read(buf))
{ out.write(buf, 0, count); } in.close();
out.flush();
out.close();
return out;
}
I have raised this as a Major bug because it is for Android but I realise it would be Minor for most other environments.