Как отправить письмо с большим вложением? (OutOfMemoryError: пространство кучи Java)
Я встретил OutOfMemoryError: Java Heap Space
когда я пытался прикрепить большое вложение. Когда отправляются электронные письма с большими файлами (скажем, 50M), выдается ошибка.
Код выглядит так:
//add attaches
if (vo.getAttaches() != null) {
InputStream iStream = null;
ByteArrayDataSource bdSource = null;
String filename = null;
for (int i = 0; i < vo.getAttaches().length; i++) {
iStream = new FileInputStream(vo.getAttaches()[i]);
bdSource = new ByteArrayDataSource(iStream, null);
filename = vo.getAttachesFileName()[i];
email.attach(bdSource, MimeUtility.encodeText(filename), filename);
}
}
это bdSource = new ByteArrayDataSource(iStream, null)
бросает исключение выше. Я прочитал "не хватает памяти с помощью Java-почты", но я не понимаю. Как я могу загрузить большие вложения? Если я определю буфер как byte[1024]
тогда как кодировать email.attach()
? Должны ли все данные в буфере использовать одинаковые filename
?
Обновление: спасибо за вашу доброту. Я использую FileDataSource вместо ByteArrayDataSource, похоже, что в моей функции send() нет исключения. Но я до сих пор не могу отправлять письма с большим вложением. Апач Джеймс получил эту ошибку:
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2786)
at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:133)
at com.sun.mail.util.ASCIIUtility.getBytes(ASCIIUtility.java:261)
at javax.mail.internet.MimeMessage.parse(MimeMessage.java:338)
at org.apache.james.core.MimeMessageWrapper.parse(MimeMessageWrapper.java:477)
at org.apache.james.core.MimeMessageWrapper.loadMessage(MimeMessageWrapper.java:205)
at org.apache.james.core.MimeMessageWrapper.checkModifyHeaders(MimeMessageWrapper.java:414)
at org.apache.james.core.MimeMessageWrapper.setHeader(MimeMessageWrapper.java:426)
at org.apache.james.core.MimeMessageCopyOnWriteProxy.setHeader(MimeMessageCopyOnWriteProxy.java:652)
at org.apache.james.transport.mailets.UsersRepositoryAliasingForwarding.service(UsersRepositoryAliasingForwarding.java:101)
at org.apache.james.transport.mailets.LocalDelivery.service(LocalDelivery.java:64)
at org.apache.james.transport.LinearProcessor.service(LinearProcessor.java:424)
at org.apache.james.transport.JamesSpoolManager.process(JamesSpoolManager.java:405)
at org.apache.james.transport.JamesSpoolManager.run(JamesSpoolManager.java:309)
at java.lang.Thread.run(Thread.java:619)
03/07/12 13:08:33 ERROR spoolmanager: An error occurred processing Mail1341292071375-0 through transport
03/07/12 13:08:33 ERROR spoolmanager: Result was error
03/07/12 13:08:33 ERROR spoolmanager: Exception in processor <error>
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2786)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
at org.apache.james.core.MimeMessageUtil.copyStream(MimeMessageUtil.java:168)
at org.apache.james.core.MimeMessageWrapper.writeTo(MimeMessageWrapper.java:276)
at org.apache.james.core.MimeMessageUtil.writeTo(MimeMessageUtil.java:66)
at org.apache.james.core.MimeMessageUtil.writeTo(MimeMessageUtil.java:50)
at org.apache.james.mailrepository.MessageInputStream.writeStream(MessageInputStream.java:131)
at org.apache.james.mailrepository.MessageInputStream.<init>(MessageInputStream.java:101)
at org.apache.james.mailrepository.JDBCMailRepository.store(JDBCMailRepository.java:718)
at org.apache.james.transport.mailets.ToRepository.service(ToRepository.java:98)
at org.apache.james.transport.LinearProcessor.service(LinearProcessor.java:424)
at org.apache.james.transport.JamesSpoolManager.process(JamesSpoolManager.java:405)
at org.apache.james.transport.JamesSpoolManager.run(JamesSpoolManager.java:309)
at java.lang.Thread.run(Thread.java:619)
03/07/12 13:08:33 ERROR spoolmanager: An error occurred processing Mail1341292071375-0 through error
03/07/12 13:08:33 ERROR spoolmanager: Result was ghost
3 ответа
Проблема в том, что вы пытаетесь сохранить весь файл в памяти при составлении сообщения, что обычно не требуется. Если вы прикрепляете реальные файлы, то вам гораздо лучше использовать javax.activation.FileDataSource
вместо javax.mail.util.ByteArrayDataSource
(оба реализуют DataSource
интерфейс), поскольку это позволяет передавать данные, а не хранить их в памяти.
Для вашего обновления: Кажется, старый (?) Вариант JamesSpoolManager
Читает весь файл в памяти при преобразовании в "mail format (ascii)" в том же потоке от 30 декабря 2010 года, проблема кажется исправленной.
ByteArrayDataSource
будет читать полный ввод из предоставленного входного потока, см. javadoc:
Создайте ByteArrayDataSource с данными из указанного InputStream и с указанным типом MIME. InputStream полностью читается, а данные сохраняются в байтовом массиве.
Таким образом, если файл для чтения "больше", чем ваш размер кучи (предел JVM), он выбросит OutOfMemoryException
,
Итак, чтобы ответить на ваш вопрос, у вас есть (как минимум) два варианта:
- Использовать
FileDataSource
как в этом так ответе - Дайте вашей программе больше памяти (вероятно, не очень хорошее решение в этом случае..)
Я столкнулся с той же проблемой. Но во время нескольких электронных писем одновременно. Которые приводят к двум ошибкам в логах.
1. OutOfMemoryError: пространство кучи Java
2. Превышено максимальное количество соединений
Я изменил два параметра в файле wrapper.conf.
#wrapper.java.initmemory=16
wrapper.java.initmemory=32
#wrapper.java.maxmemory=64
wrapper.java.maxmemory=128
После перезагрузки сервера ошибка ушла, и отправка-прием почты работает.