我怀疑我使用了错误的Apache Common Email库来发送带有附件的电子邮件。 有时会出现“打开的文件太多” 错误,如果我用 lsof 检查打开的文件,我会看到附件文件被多次打开:
image1.png image2.png image1.png ...
所以我怀疑我没有正确释放文件(或没有关闭某些资源)。该软件也可能正常运行,但是如果外部SMTP服务器失败(连接异常),我的代码将不会释放某些资源。
来源:
/* Async Thread to send email */
Thread t = new Thread(){
@Override
public void run(){
try{
task(request,idNewsletter);
}
catch (Exception e){
log.error("Error " + e);
}
}
};
t.start();
[...]
任务方法:
ExecutorService executor = Executors.newFixedThreadPool(10);
[...]
List<Future<Integer>> list = new ArrayList<Future<Integer>>();
for (int i = 0; i < dests.length; i++) {
HtmlEmail htmlEmail = getHtmlMail([...]);
ArrayList<InternetAddress> dest = new ArrayList<InternetAddress>();
InternetAddress add = new InternetAddress();
add.setAddress(dests[i]);
dest.add(add);
htmlEmail.setBcc(dest);
htmlEmail.setMailSession(getEmailSession());
htmlEmail.buildMimeMessage();
Callable<Integer> worker = new EmailService(htmlEmail,i);
Future<Integer> future = executor.submit(worker);
list.add(future);
}
try {
executor.shutdown();
executor.awaitTermination(28800, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
log.error("Error=" + e);
}
finally {
if (!executor.isTerminated()) {
log.error("Task cancelled");
}
executor.shutdownNow();
}
getHtmlEmail方法
private static URL image;
static {
image= (new File("somepath").toURI().toURL());
}
private HtmlEmail getHtmlMail([...]){
HtmlEmail htmlEmail = new HtmlEmail();
htmlEmail.setCharset("UTF-8");
htmlEmail.setSubject("someSubject");
htmlEmail.setFrom(from);
htmlEmail.setSentDate(new java.util.Date());
[...]
String cidImage= htmlEmail.embed(image, "Email image");
text= text.replace("cid:image", "cid:" + cidImage);
[...] /* Other attachments */
htmlEmail.setHtmlMsg(text);
return htmlEmail;
}
getEmailSession方法
private Session getEmailSession() throws Exception{
if (mailSession != null)
return mailSession;
else {
InitialContext ic = new InitialContext();
mailSession = (Session) ic.lookup("someJNDI");
mailSession.getProperties().put("mail.smtp.connectiontimeout", 1000);
mailSession.getProperties().put("mail.smtp.timeout", 5000);
return mailSession;
}
}
以及发送电子邮件的方法
@Override
public Integer call() throws Exception {
try{
htmlEmail.sendMimeMessage();
}
catch(Exception e){
log.error("Error=" + e);
htmlEmail=null;
return new Integer(0);
}
return new Integer(1);
}
有任何提示吗?
预先感谢 安德里亚
答案 0 :(得分:1)
我相信这是问题所在
static {
image= (new File("somepath").toURI().toURL());
}
它是static
。这是您遇到的并发问题。
它总是在那里。
我认为这是正在发生的事情。假设这在名为Url
的类中,并且您有一个非静态的getUrl()
返回此值。
如果您这样做:
Url url1 = new Url();
Url url2 = new Url();
url1.getUrl();
url2.getUrl();
然后,它们各自应返回不同的url实例。但是,您正在将url
属性初始化为static
,所以实际上发生的是 所有Url实例都只有一个url。 url属性不属于每个对象,而仅属于类本身。
因此,当您尝试调用它时,他们都试图一次又一次地访问该文件,因为首先它从未被“创建”或初始化过每个实例。认为它是永远存在的东西,因为类本身拥有它,而不是实例,因此给您带来Too many open files
错误。
因此,我建议您将其从静态中删除。也许您可以执行以下操作:
class Url{
private final URL url;
public Url() {
url= (new File("somepath").toURI().toURL());
}
}
然后只需在任意位置使用该url
属性。
答案 1 :(得分:0)
更新:即使我将字段重写为非静态字段,问题仍然存在。 我想这个版本的库(Apache Common Email 1.5)有问题(错误?)