Когда мой класс структурирован таким образом, я получаю ошибку OutOfMemory.
DataHandler вызывается фиксированным пулом из 8 потоков (управление внешним пулом потоков отсутствует. Создан фиксированный пулодин раз, выполняется один раз, и если поток умирает, новый поток не создается).В то же время несколько потоков вызывают DataHandler, но поскольку byteArrayOutputStreamBuffer имеет значение threadLocal, каждый из них будет иметь свой собственный локальный буфер.Каждый поток получает данные, вызывает HandleData () и, после завершения, повторяет цикл.
Размер передаваемых данных составляет 2 ГБ.Таким образом, общая ожидаемая память будет не более (2 ГБ + размер байтового массива потока) * количество потоков.Максимальный размер потока массива должен составлять 4 ГБ (удвоение данных из-за изменения размера в памяти).Таким образом, ожидаемая общая куча будет 6 * 8 = 48 ГБ.Куча настроена для обработки гораздо больше (я пробовал до 300 ГБ), и все же эта проблема сохраняется.
public class DataHandler {
private static ThreadLocal<ByteArrayOutputStream> byteArrayOutputStreamBuffer =
new ByteArrayOutputStream();
void HandleData(byte[] data) {
ByteArrayOutputStream byteArrayOutputStream = byteArrayOutputStreamBuffer.get();
File tempFile = new File(getFileName());
try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) {
byteArrayOutputStream.write(data);
fileOutputStream.write(byteArrayOutputStream.toByteArray());
} finally {
byteArrayOutputStream.reset();
}
}
}
Если я удаляю промежуточный ByteArrayOutputStream, то OOM не существует.Я пытаюсь найти объяснение, почему ByteArrayOutputStream вызывает OOM.
РЕДАКТИРОВАТЬ: я вижу, что toByteArray () также добавит еще 2 ГБ, поэтому общий объем будет 64 ГБ.