Java 中的电子邮件服务引发“内存不足”错误
Posted
技术标签:
【中文标题】Java 中的电子邮件服务引发“内存不足”错误【英文标题】:Email service in Java throws an "out of memory" error 【发布时间】:2019-04-18 06:43:58 【问题描述】:我正在后台运行电子邮件服务(在命令提示符下),它旨在继续运行并获取队列表中的记录以进行处理。
这是我的 Email.java:
public class Email
mysqlConnect con=new MySqlConnect();
public PreparedStatement preparedStatement = null;
public Connection con1 = con.connect();
public Email() throws Exception
//pick up queue and send email
public void email() throws Exception
try
while(true)
String sql = "SELECT id,subject,recipient,content FROM emailqueue WHERE status='Pending' ";
PreparedStatement statement = con1.prepareStatement(sql);
ResultSet rs = statement.executeQuery();
while (rs.next())
String subject = rs.getString("subject");
String recipient = rs.getString("recipient");
String content = rs.getString("content");
String id = rs.getString("id");
sendEmail(recipient, subject, content, id);
catch(Exception e)
e.printStackTrace();
con1.close();
Thread.sleep(2000);
//Schedule a service for picking email
public void schedule()
Thread service;
service = new Thread(new Runnable()
public void run()
try
System.out.println("Email service is ready");
email();
catch (Exception e)
e.printStackTrace();
);
service.start();
public void sendEmail(String recipient, String subject, String content,String id)
try
//final String fromEmail = "lordjesus0371@gmail.com"; //requires valid gmail id
// final String password = "htasia123"; // correct password for gmail id
// InitialContext ctx = new InitialContext();
String host = get_attributevalue("MAIL_SERVER");
String port = get_attributevalue("MAIL_PORT");
final String senderaddress = get_attributevalue("SENDER_ADDRESS");
final String password = get_attributevalue("MAIL_PASSWORD");
System.out.println("Please Wait, sending email...");
/*Setup mail server */
Properties props = new Properties();
props.put("mail.smtp.host", host); //SMTP Host
props.put("mail.smtp.port", port); //TLS Port
props.put("mail.smtp.auth", "true"); //enable authentication
props.put("mail.smtp.starttls.enable", "true"); //enable STARTTLS
//create Authenticator object to pass in Session.getInstance argument
Authenticator auth = new Authenticator()
//override the getPasswordAuthentication method
protected PasswordAuthentication getPasswordAuthentication()
return new PasswordAuthentication(senderaddress, password);
;
Session session = Session.getInstance(props, auth);
session.setDebug(true);
// Define message
MimeMessage message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress(senderaddress));
message.addRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
// Set Subject: header field
message.setSubject(subject);
// Now set the actual message
message.setText(content);
Transport.send(message);
delivered(id);
System.out.print("Email sent");
catch (Exception e)
System.out.println(e.getMessage());
try
error(id);
catch (SQLException e1)
e1.printStackTrace();
在我的 Main 方法中:
public static void main(String[] args) throws Exception
Email runEmailService=new Email();
runEmailService.schedule();
它能够提取记录并很好地处理电子邮件,但一段时间后它会抛出:
Exception in thread "Thread-1" java.lang.OutOfMemoryError: Java heap space
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "Thread-1"
然后程序停止运行。
有没有办法防止这种情况发生,让我的程序继续运行?
【问题讨论】:
完成后尝试关闭结果集和语句。 但是我已经关闭了连接,应该没问题吧? 如果Session
可以分享,请不要每次都新建一个
“内存不足”错误可能来自while(true)
循环,循环后关闭连接不会有太大作用。
现在可以使用了。怎么会呢?另外,请发布您的答案,以便我标记它
【参考方案1】:
语句和结果集资源可能尚未释放,并且由于您没有关闭它们而保留在内存中。
考虑在while(rs.next())
循环之后关闭它们:
rs.close();
statement.close();
请注意,您可以使用“try with reousrces”来让事情自行关闭:
try (PreparedStatement statement = con1.prepareStatement(sql); ResultSet rs = statement.executeQuery())
参见。 Java 7 Automatic Resource Management JDBC (try-with-resources statement)
public void email() throws Exception
String sql = "SELECT id,subject,recipient,content FROM emailqueue WHERE status='Pending' ";
while (true)
try (PreparedStatement statement = con1.prepareStatement(sql); ResultSet rs = statement.executeQuery())
while (rs.next())
String subject = rs.getString("subject");
String recipient = rs.getString("recipient");
String content = rs.getString("content");
String id = rs.getString("id");
sendEmail(recipient, subject, content, id);
catch (Exception e)
e.printStackTrace();
con1.close();
Thread.sleep(2000);
【讨论】:
见上面这段代码,这里它们不在
块内,它们是try
块的“参数”()
。不过,您必须在 try
之前声明您的 sql
字符串才能使其正常工作。
我明白你的意思,但是如果外部 try 块可以处理,为什么还要再试一次呢?
因为这样它们会自动关闭,您甚至不必在它们上调用close()
。由于块的位置不清楚,我只是用整个方法更新了答案。
我明白了。但是 try 处理的 send email 方法也对吗?
是的,如果邮件发送崩溃,你会进入catch
块,资源仍然会被关闭。注意,资源关闭部分完全独立于catch
,如果try
块中没有引发错误,它们仍然会自动关闭。以上是关于Java 中的电子邮件服务引发“内存不足”错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 R 和 XLConnect 包时出现“内存不足错误 (Java)”