diff --git a/actuator/src/main/java/org/tron/core/vm/VMUtils.java b/actuator/src/main/java/org/tron/core/vm/VMUtils.java index 2f469e0579a..4a8412c5f54 100644 --- a/actuator/src/main/java/org/tron/core/vm/VMUtils.java +++ b/actuator/src/main/java/org/tron/core/vm/VMUtils.java @@ -111,13 +111,19 @@ private static void write(InputStream in, OutputStream out, int bufSize) throws public static byte[] compress(byte[] bytes) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Deflater deflater = new Deflater(); - ByteArrayInputStream in = new ByteArrayInputStream(bytes); - DeflaterOutputStream out = new DeflaterOutputStream(baos, new Deflater(), BUF_SIZE); + try { + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + DeflaterOutputStream out = new DeflaterOutputStream(baos, deflater, BUF_SIZE); - write(in, out, BUF_SIZE); + write(in, out, BUF_SIZE); - return baos.toByteArray(); + return baos.toByteArray(); + } finally { + // DeflaterOutputStream only ends Deflaters it creates itself. + deflater.end(); + } } public static byte[] compress(String content) throws IOException { diff --git a/actuator/src/test/java/org/tron/core/vm/VMUtilsTest.java b/actuator/src/test/java/org/tron/core/vm/VMUtilsTest.java new file mode 100644 index 00000000000..d6b1192379c --- /dev/null +++ b/actuator/src/test/java/org/tron/core/vm/VMUtilsTest.java @@ -0,0 +1,34 @@ +package org.tron.core.vm; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mockConstruction; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.nio.charset.StandardCharsets; +import java.util.zip.Deflater; +import org.junit.Test; +import org.mockito.MockedConstruction; +import org.tron.common.utils.ByteUtil; + +public class VMUtilsTest { + + @Test + public void compressShouldReleaseDeflater() throws Exception { + try (MockedConstruction deflaters = mockConstruction(Deflater.class, + (deflater, context) -> when(deflater.finished()).thenReturn(true))) { + VMUtils.compress(new byte[0]); + + assertEquals(1, deflaters.constructed().size()); + verify(deflaters.constructed().get(0)).end(); + } + } + + @Test + public void compressShouldPreserveContent() throws Exception { + byte[] content = "VM trace compression".getBytes(StandardCharsets.UTF_8); + + assertArrayEquals(content, ByteUtil.decompress(VMUtils.compress(content))); + } +}