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 中的电子邮件服务引发“内存不足”错误的主要内容,如果未能解决你的问题,请参考以下文章

如何永久增加java堆内存?

java:内存不足错误的一般方法

使用 R 和 XLConnect 包时出现“内存不足错误 (Java)”

一种序列化方法会产生内存不足错误,另一种则不会

使用大型数据结构时,避免 Java(eclipse) 中的“内存不足错误”?

发送连续网络摄像头图像时出现内存不足错误java