MimeMessage.saveChanges 真的很慢
MimeMessage.saveChanges is really slow
由于包含 m.saveChanges()
.
,执行以下测试大约需要 5 秒
import org.junit.Before;
import org.junit.Test;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@Test
public void test1() throws MessagingException, IOException {
Session s = Session.getDefaultInstance(new Properties());
MimeMessage m = new MimeMessage(s);
m.setContent("<b>Hello</b>", "text/html; charset=utf-8");
m.saveChanges();
assertEquals(m.getContent(), "<b>Hello</b>");
assertEquals(m.getContentType(), "text/html; charset=utf-8");
}
我也用 mockito 模拟了 Session,但没有用:
Session s = mock(Session.class);
when(s.getProperties()).thenReturn(new Properties());
这里有什么问题?我可以模拟什么来加快速度?
首先修复代码中的 most common mistakes people make when using JavaMail。
DNS lookup can hurt performance on some machines. For the JDK you can change the security properties for caching DNS lookup networkaddress.cache.ttl
and networkaddress.cache.negative.ttl
or set the system properties sun.net.inetaddr.ttl
and sun.net.inetaddr.negative.ttl
。 JDK 7 及更高版本中的默认行为可以很好地缓存,因此您不必更改这些设置。
最好,您可以使用会话属性来避免这些查找。
- 为
mail.from
or mail.host
(not the protocol versions) as that will prevent the name lookup on InternetAddress.getLocalAddress(Session)
. Calling MimeMessage.saveChanges()
, MimeMessage.updateHeaders()
, MimeMessage.updateMessageID()
, or MimeMessage.setFrom()
设置会话属性将触发获取本地地址的调用。如果未设置上述属性,则此方法将尝试查询主机名。通过设置属性,此方法将从会话中提取主机名字符串,而不是尝试进行昂贵的 DNS 查找。
- 为
mail.smtp.localhost
or mail.smtps.localhost
设置会话 属性 以防止在 HELO 命令上查找名称。
- 为
mail.smtp.from
or mail.smtps.from
设置会话 属性 以防止查找 EHLO 命令。
- 或者,您可以设置系统 属性
mail.mime.address.usecanonicalhostname
to false
if your code is relying on the setFrom()
但如果您应用点 #1,这将得到处理。
- 对于 IMAP,您可以尝试将
mail.imap.sasl.usecanonicalhostname
or mail.imaps.sasl.usecanonicalhostname
设置为默认值 false
。
由于您没有传输消息,请将代码更改为应用规则 #1:
@Test
public void test1() throws MessagingException, IOException {
Properties props = new Properties();
props.put("mail.host", "localhost"); //Or use IP.
Session s = Session.getInstance(props);
MimeMessage m = new MimeMessage(s);
m.setContent("<b>Hello</b>", "text/html; charset=utf-8");
m.saveChanges();
assertEquals(m.getContent(), "<b>Hello</b>");
assertEquals(m.getContentType(), "text/html; charset=utf-8");
}
如果您要传输消息,请结合规则 #1、#2 和 #3,这将阻止访问主机系统进行名称查找。如果您想在传输过程中阻止所有 DNS 查找,则必须使用 IP 地址。
由于包含 m.saveChanges()
.
import org.junit.Before;
import org.junit.Test;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@Test
public void test1() throws MessagingException, IOException {
Session s = Session.getDefaultInstance(new Properties());
MimeMessage m = new MimeMessage(s);
m.setContent("<b>Hello</b>", "text/html; charset=utf-8");
m.saveChanges();
assertEquals(m.getContent(), "<b>Hello</b>");
assertEquals(m.getContentType(), "text/html; charset=utf-8");
}
我也用 mockito 模拟了 Session,但没有用:
Session s = mock(Session.class);
when(s.getProperties()).thenReturn(new Properties());
这里有什么问题?我可以模拟什么来加快速度?
首先修复代码中的 most common mistakes people make when using JavaMail。
DNS lookup can hurt performance on some machines. For the JDK you can change the security properties for caching DNS lookup networkaddress.cache.ttl
and networkaddress.cache.negative.ttl
or set the system properties sun.net.inetaddr.ttl
and sun.net.inetaddr.negative.ttl
。 JDK 7 及更高版本中的默认行为可以很好地缓存,因此您不必更改这些设置。
最好,您可以使用会话属性来避免这些查找。
- 为
mail.from
ormail.host
(not the protocol versions) as that will prevent the name lookup onInternetAddress.getLocalAddress(Session)
. CallingMimeMessage.saveChanges()
,MimeMessage.updateHeaders()
,MimeMessage.updateMessageID()
, orMimeMessage.setFrom()
设置会话属性将触发获取本地地址的调用。如果未设置上述属性,则此方法将尝试查询主机名。通过设置属性,此方法将从会话中提取主机名字符串,而不是尝试进行昂贵的 DNS 查找。 - 为
mail.smtp.localhost
ormail.smtps.localhost
设置会话 属性 以防止在 HELO 命令上查找名称。 - 为
mail.smtp.from
ormail.smtps.from
设置会话 属性 以防止查找 EHLO 命令。 - 或者,您可以设置系统 属性
mail.mime.address.usecanonicalhostname
tofalse
if your code is relying on thesetFrom()
但如果您应用点 #1,这将得到处理。 - 对于 IMAP,您可以尝试将
mail.imap.sasl.usecanonicalhostname
ormail.imaps.sasl.usecanonicalhostname
设置为默认值false
。
由于您没有传输消息,请将代码更改为应用规则 #1:
@Test
public void test1() throws MessagingException, IOException {
Properties props = new Properties();
props.put("mail.host", "localhost"); //Or use IP.
Session s = Session.getInstance(props);
MimeMessage m = new MimeMessage(s);
m.setContent("<b>Hello</b>", "text/html; charset=utf-8");
m.saveChanges();
assertEquals(m.getContent(), "<b>Hello</b>");
assertEquals(m.getContentType(), "text/html; charset=utf-8");
}
如果您要传输消息,请结合规则 #1、#2 和 #3,这将阻止访问主机系统进行名称查找。如果您想在传输过程中阻止所有 DNS 查找,则必须使用 IP 地址。