Java — OutOfMemoryError во время манипуляции со строкой JSON

Я пытаюсь отследить утечку памяти в коде Java, показанном ниже.

  • Этот код выдает OutOfMemoryError: heap space во время работы с максимальным размером кучи 2 ГБ после обработки лишь нескольких обновлений файлов.
  • Размер сжатых файлов на S3 не превышает нескольких сотен кБ.
  • Входная строка (переменная «поправка») не превышает 1 МБ.
  • Дамп кучи показывает размер byte[] сотен МБ - в одном случае он занимал более 50% пространства кучи. (Однако Tooling не указал, где создается этот массив).

Он использует экземпляр клиента AmazonS3 для чтения и записи объектов в удаленной корзине S3, а также использует ObjectMapper Джексона для работы со строками и преобразования их в JSON и т. д. Классы Deflater и Inflater из пакета java.util.zip используются для сжатия/распаковки.

Есть ли очевидная утечка памяти в этом коде? Есть ли очевидная ошибка, которая может привести к постоянно растущему/огромному массиву байтов в куче? Я действительно ломал голову над этим какое-то время! Спасибо.

class FileManager {
    // Constructor omitted
    private static final int BYTE_SIZE = 1024;
    private final String bucketName;
    private final AmazonS3 client;
    private final ObjectMapper objectMapper;

    public void saveFile(String key, String amendment, String updateTimeStamp) throws Exception {
        S3Object object = null;
        try {
            JsonNode amendmentJson = objectMapper.readTree(amendment);
            ObjectNode targetJson;
            if (client.doesObjectExist(bucketName, key)) {
                object = client.getObject(bucketName, key);
                InputStream objectStream = object.getObjectContent();
                targetFile = (ObjectNode) decompress(objectStream);
                objectStream.close();
                object.close();
            } else {
                targetJson = objectMapper.createObjectNode();
            }
            targetJson.set(updateTimeStamp, amendmentJson);
            byte[] contentBytes = compress(objectMapper.writeValueAsBytes(targetJson));
            try (ByteArrayInputStream contentStream = new ByteArrayInputStream(contentBytes)) {
                client.putObject(bucketName, key, contentStream);
            }
        } catch (Exception ex) {
          // Logs and rethrows ...
        }
    }

    public byte[] compress(byte[] data) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
        Deflater deflater = new Deflater();
        byte[] buffer = new byte[BYTE_SIZE];
        deflater.setInput(data);
        deflater.finish();
        while (!deflater.finished()) {
            int count = deflater.deflate(buffer);
            outputStream.write(buffer, 0, count);
        }
        outputStream.close();
        deflater.end();
        return outputStream.toByteArray();
    }

    public JsonNode decompress(InputStream objectReader) throws IOException {
        byte[] data = IOUtils.toByteArray(objectReader);
        byte[] buffer = new byte[BYTE_SIZE];
        Inflater inflater = new Inflater();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
        String outputString;
        inflater.setInput(data);
        try {
            while (!inflater.finished()) {
                int count = inflater.inflate(buffer);
                outputStream.write(buffer, 0, count);
            }
            outputString = new String(outputStream.toByteArray());
        } catch (DataFormatException e) {
            log.info("Content not zipped");
            outputString = new String(data);
        }
        outputStream.close();
        inflater.end();
        StringReader reader = new StringReader(outputString);
        JsonNode jsonNode = objectMapper.readTree(reader);
        reader.close();
        return jsonNode;
    }

}

person Boon    schedule 18.04.2020    source источник
comment
Какой метод этого класса вызывает утечку памяти??   -  person Omid.N    schedule 18.04.2020
comment
Пожалуйста, отредактируйте свой вопрос и опубликуйте всю полученную трассировку стека.   -  person Abra    schedule 18.04.2020
comment
Как отлаживать исключения Java OutOfMemory?   -  person Abra    schedule 18.04.2020