Как отправить письмо с большим вложением? (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,


Итак, чтобы ответить на ваш вопрос, у вас есть (как минимум) два варианта:

  1. Использовать FileDataSource как в этом так ответе
  2. Дайте вашей программе больше памяти (вероятно, не очень хорошее решение в этом случае..)

Я столкнулся с той же проблемой. Но во время нескольких электронных писем одновременно. Которые приводят к двум ошибкам в логах.

 1. OutOfMemoryError: пространство кучи Java 

 2. Превышено максимальное количество соединений 

Я изменил два параметра в файле wrapper.conf.

#wrapper.java.initmemory=16
 wrapper.java.initmemory=32

#wrapper.java.maxmemory=64
wrapper.java.maxmemory=128

После перезагрузки сервера ошибка ушла, и отправка-прием почты работает.

Другие вопросы по тегам