diff --git a/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorOutputStream.java b/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorOutputStream.java index 7371ad5a35a..bc35e670883 100644 --- a/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorOutputStream.java +++ b/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorOutputStream.java @@ -321,6 +321,7 @@ private static void hbMakeCodeLengths(final byte[] len, final int[] freq, * All memory intensive stuff. */ private Data data; + private BlockSort blockSorter; private OutputStream out; @@ -480,6 +481,7 @@ public void finish() throws IOException { } finally { this.out = null; this.data = null; + this.blockSorter = null; } } } @@ -512,6 +514,7 @@ private void init() throws IOException { bsPutUByte('Z'); this.data = new Data(this.blockSize100k); + this.blockSorter = new BlockSort(this.data); // huffmanised magic bytes bsPutUByte('h'); @@ -1147,7 +1150,7 @@ private void moveToFrontCodeAndSend() throws IOException { } private boolean blockSort() { - return new BlockSort().blockSort(data, last); + return blockSorter.blockSort(data, last); } private void generateMTFValues() { @@ -1274,19 +1277,10 @@ static final class Data extends Object { final byte[] sendMTFValues2_pos = new byte[N_GROUPS]; // 6 byte final boolean[] sentMTFValues4_inUse16 = new boolean[16]; // 16 byte - final int[] stack_ll = new int[BlockSort.QSORT_STACK_SIZE]; // 4000 byte - final int[] stack_hh = new int[BlockSort.QSORT_STACK_SIZE]; // 4000 byte - final int[] stack_dd = new int[BlockSort.QSORT_STACK_SIZE]; // 4000 byte - - final int[] mainSort_runningOrder = new int[256]; // 1024 byte - final int[] mainSort_copy = new int[256]; // 1024 byte - final boolean[] mainSort_bigDone = new boolean[256]; // 256 byte - final int[] heap = new int[MAX_ALPHA_SIZE + 2]; // 1040 byte final int[] weight = new int[MAX_ALPHA_SIZE * 2]; // 2064 byte final int[] parent = new int[MAX_ALPHA_SIZE * 2]; // 2064 byte - final int[] ftab = new int[65537]; // 262148 byte // ------------ // 333408 byte @@ -1297,13 +1291,6 @@ static final class Data extends Object { // 8433529 byte // ============ - /** - * Array instance identical to sfmap, both are used only - * temporarily and indepently, so we do not need to allocate - * additional memory. - */ - final char[] quadrant; - /** * Index in fmap[] of original string after sorting. */ @@ -1316,7 +1303,6 @@ static final class Data extends Object { this.block = new byte[(n + 1 + NUM_OVERSHOOT_BYTES)]; this.fmap = new int[n]; this.sfmap = new char[2 * n]; - this.quadrant = this.sfmap; } } diff --git a/src/main/java/org/apache/commons/compress/compressors/bzip2/BlockSort.java b/src/main/java/org/apache/commons/compress/compressors/bzip2/BlockSort.java index 8c05998a944..6357494a89e 100644 --- a/src/main/java/org/apache/commons/compress/compressors/bzip2/BlockSort.java +++ b/src/main/java/org/apache/commons/compress/compressors/bzip2/BlockSort.java @@ -37,7 +37,7 @@ class BlockSort { * try again. In practice I have never seen the stack go above 27 * elems, so the following limit seems very generous.

*/ - static final int QSORT_STACK_SIZE = 1000; + private static final int QSORT_STACK_SIZE = 1000; /** * Knuth's increments seem to work better than Incerpi-Sedgewick here. @@ -58,6 +58,27 @@ class BlockSort { private int workLimit; private boolean firstAttempt; + private final int[] stack_ll = new int[QSORT_STACK_SIZE]; // 4000 byte + private final int[] stack_hh = new int[QSORT_STACK_SIZE]; // 4000 byte + private final int[] stack_dd = new int[QSORT_STACK_SIZE]; // 4000 byte + + private final int[] mainSort_runningOrder = new int[256]; // 1024 byte + private final int[] mainSort_copy = new int[256]; // 1024 byte + private final boolean[] mainSort_bigDone = new boolean[256]; // 256 byte + + private final int[] ftab = new int[65537]; // 262148 byte + + /** + * Array instance identical to Data's sfmap, both are used only + * temporarily and indepently, so we do not need to allocate + * additional memory. + */ + private final char[] quadrant; + + BlockSort(final BZip2CompressorOutputStream.Data data) { + this.quadrant = data.sfmap; + } + /** * This is the most hammered method of this class. * @@ -82,7 +103,7 @@ private boolean mainSimpleSort(final BZip2CompressorOutputStream.Data dataShadow } final int[] fmap = dataShadow.fmap; - final char[] quadrant = dataShadow.quadrant; + final char[] quadrant = this.quadrant; final byte[] block = dataShadow.block; final int lastPlus1 = lastShadow + 1; final boolean firstAttemptShadow = this.firstAttempt; @@ -299,9 +320,9 @@ boolean blockSort(final BZip2CompressorOutputStream.Data data, final int last) { private void mainQSort3(final BZip2CompressorOutputStream.Data dataShadow, final int loSt, final int hiSt, final int dSt, final int last) { - final int[] stack_ll = dataShadow.stack_ll; - final int[] stack_hh = dataShadow.stack_hh; - final int[] stack_dd = dataShadow.stack_dd; + final int[] stack_ll = this.stack_ll; + final int[] stack_hh = this.stack_hh; + final int[] stack_dd = this.stack_dd; final int[] fmap = dataShadow.fmap; final byte[] block = dataShadow.block; @@ -403,13 +424,13 @@ private void mainQSort3(final BZip2CompressorOutputStream.Data dataShadow, private void mainSort(final BZip2CompressorOutputStream.Data dataShadow, final int lastShadow) { - final int[] runningOrder = dataShadow.mainSort_runningOrder; - final int[] copy = dataShadow.mainSort_copy; - final boolean[] bigDone = dataShadow.mainSort_bigDone; - final int[] ftab = dataShadow.ftab; + final int[] runningOrder = this.mainSort_runningOrder; + final int[] copy = this.mainSort_copy; + final boolean[] bigDone = this.mainSort_bigDone; + final int[] ftab = this.ftab; final byte[] block = dataShadow.block; final int[] fmap = dataShadow.fmap; - final char[] quadrant = dataShadow.quadrant; + final char[] quadrant = this.quadrant; final int workLimitShadow = this.workLimit; final boolean firstAttemptShadow = this.firstAttempt;