当我试图附加一个大附件时,我遇到了一个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
。
因此,要回答您的问题,您(至少)有两个选择:
- 使用类似于此 SO 答案中的
FileDataSource
- 给你的程序更多的内存(在这种情况下可能不是一个好的解决方案。
我遇到了同样的问题。但是,在同时发送多封电子邮件期间。 这会导致日志中出现两个错误。
1. 内存不足错误:Java 堆空间
2. 超过最大连接数
我在wrapper.conf文件中更改了两个参数。
#wrapper.java.initmemory=16
wrapper.java.initmemory=32
#wrapper.java.maxmemory=64
wrapper.java.maxmemory=128
重新启动服务器后,错误已消失,邮件发送-接收正常工作。