如何发送带有大附件的电子邮件?(OutOfMemoryError: java heap space)



当我试图附加一个大附件时,我遇到了一个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

问题是您在撰写消息时尝试将整个文件存储在内存中,这实际上通常不是必需的。如果要附加真实文件,则最好使用javax.activation.FileDataSource而不是javax.mail.util.ByteArrayDataSource(两者都实现DataSource接口),因为这可以允许流式传输数据而不是保存在内存中。

对于您的更新:在日期为 30 年 12 月 10 日的同一线程中转换为"邮件格式 (ascii)"时,似乎JamesSpoolManager的旧 (?) 变体将整个文件读取到内存中,问题似乎已解决。


ByteArrayDataSource将从提供的输入流中读取完整的输入,请参阅 javadoc:

使用来自指定输入流的数据和指定的 MIME 类型创建字节阵列数据源。输入流被完全读取,数据存储在字节数组中。

因此,如果要读取的文件"大于"您的堆大小(JVM 限制),它将抛出OutOfMemoryException


因此,要回答您的问题,您(至少)有两个选择:

  1. 使用类似于此 SO 答案中的FileDataSource
  2. 给你的程序更多的内存(在这种情况下可能不是一个好的解决方案。

我遇到了同样的问题。但是,在同时发送多封电子邮件期间。 这会导致日志中出现两个错误。

1. 内存不足错误:Java 堆空间

2. 超过最大连接数

我在wrapper.conf文件中更改了两个参数。

#wrapper.java.initmemory=16
 wrapper.java.initmemory=32
#wrapper.java.maxmemory=64
wrapper.java.maxmemory=128

重新启动服务器后,错误已消失,邮件发送-接收正常工作。

相关内容

  • 没有找到相关文章

最新更新