java - java应用程序中无限循环的内存不足和stackoverflow异常

标签 java loops jdbc stack-overflow out-of-memory

我有一个简单的应用程序,用于监听 UDP 消息。该应用程序需要无限期运行。它通过实例化我创建的 MySQLConnect 对象来实例化单个 jdbc 数据库连接它看起来像这样:

 public MySQLConnect() {
    this.instantiateConnection();
}

//Open the database connection.  Done iniitally in 
//the main class and only called again if the connection 
//is closed due to an error in processing a message
public Connection instantiateConnection() {

    try {

        Class.forName("com.mysql.jdbc.Driver");

        connection = DriverManager
                .getConnection("jdbc:mysql://localhost:3306/mydb?"
                        + "user=user&password=pwd");
    } catch (Exception e) {
        e.printStackTrace();
    }

    return connection;
}

一旦应用程序启动,就会从 UDPReceiver 类调用 MySQLConnect 类构造函数。只有在处理错误并且数据库连接关闭时才会再次调用它。这个类看起来像:

 public class UDPReceiver {

private static int port = 2140;
private static int byteSize = 1024;
private static int timeOut = 5000;
@SuppressWarnings("unused")
private static int count;
static MySQLConnect dbConnect;


   public static void main(String[] args) {

    recvUDPMessage();
}

public static String recvUDPMessage() {
    DataTransferService dts = new DataTransferServiceImp();
    dbConnect = new MySQLConnect();

    try {

        DatagramSocket dsocket = null;
        if (dsocket == null) {
            dsocket = new DatagramSocket(port);
            dsocket.setBroadcast(true);
            dsocket.setReuseAddress(false);
        }
        byte[] inbuf = new byte[byteSize];
        byte[] rcvMsg;
        InetAddress fromIP;

        DatagramPacket receivepacket = new DatagramPacket(inbuf,
                inbuf.length);
        dsocket.setSoTimeout(timeOut);

        //Infinitely loop and listen for UDP messages

        count = 0;
        boolean loopRecv = true;
        while (loopRecv) {
            try {
                count++;
                dsocket.receive(receivepacket);
                // temp = receivepacket.getAddress().toString();
                fromIP = receivepacket.getAddress();
                String fromIPString = fromIP.toString();
                rcvMsg = receivepacket.getData();
                String rcvString = new String(rcvMsg, 0, rcvMsg.length);
                String rcvMessage = "Message Received from:  "
                        + fromIPString + " Message:  " + rcvString + "\n";
                System.out.println(rcvMessage);



                ArrayList<String> al = getMessageElements(rcvString);



                //Send array of message elements to service layer
                dts.saveUDPMessage(dbConnect, al, Utils.getTimeStamp());

                loopRecv = true;
            } catch (IOException e) {
                System.out.println("Listening . . .");



                loopRecv = true;
            }
        }
    } catch (SocketException e) {
        System.err.println("Sockets Exception: " + e.getMessage());
    } catch (Exception e) {
        System.err.println(" Exception: " + e.getMessage());

    } finally {
        System.out.println(". . . Close DB");
        dts.closeDBConnection(dbConnect);


                    // I added the creation MySQLConnect object after I was getting an error that the database was closed when trying to insert.
        dbConnect = new MySQLConnect();
    }
    return "end of routine";
}

//Extract comma delimited message elements into an array
private static ArrayList<String> getMessageElements(String rcvString) {
    StringTokenizer st = new StringTokenizer(rcvString, ",");

    ArrayList<String> al = new ArrayList<String>();

    while (st.hasMoreElements()) {
        String messageElement = (String) st.nextElement();
        al.add(messageElement);

    }



    return al;
}

}

这运行了大约 8 小时,然后我收到以下错误:

主线程 java.lang.stackoverflowerror 中出现异常

异常:从主线程中的 uncaughtExceptionhandler 抛出 java.lang.outofmemoryerror

以前,我在数据库关闭后没有重新实例化 MySQLConnect 对象。问题是我收到数据库连接已关闭的错误,但我的程序仍在尝试执行 jdbc 插入。 jdbc insert 首先检查是否有实例化的连接,如果没有则实例化它。 MySQLConnect 类中的这段代码如下所示:

 PreparedStatement prep = null;

    if (connection == null) {
        connection = this.instantiateConnection();
    }

    try {

        prep = connection
                .prepareStatement("insert into MyTable (UDPMessage)"
                        + "values (?);");

        prep.setString(1, udpMessage);




        prep.addBatch();

        prep.executeBatch();

如何构建此流程以正确处理无限期传入的 UDP 消息并写入数据库,即使发生错误也是如此?

另外,当处理数据出现异常时,如何解决重新实例化 MySQLConnect 类时出现内存不足错误的问题?

如果异常后实例化该类不正确,如何重新实例化与数据库的连接以继续处理数据?

感谢您的帮助!

最佳答案

您没有在代码中的任何位置将 boolean 值 loopRecv 设置为 false,这会导致无限循环(而条件始终解析为 true )。无限/递归循环保留在填充堆栈上,但不会删除任何堆栈帧并导致 StackOVerflowError

关于java - java应用程序中无限循环的内存不足和stackoverflow异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11906819/

相关文章:

java - Java 中的返回字符串在编译器中不执行任何操作

javascript - 循环遍历字幕并对超过一定字符长度的所有字幕执行一些操作jquery

c++ - 删除 C++ 中的尾随逗号

hibernate - 使用 Hibernate 或 JDBC 将用户从 Java 中的用户 session 传递到 Firebird 触发器

java - MySQL 没有正确存储一些 UTF8 字符

java - hibernate 程序不终止

java - 如何使SearchView与RecyclerView相同?

java - 使用 HashMap 问题映射超过 5908 条数据线

java - 从另一个文件导入 Ant 类补丁

java - java调度器还有其他方法比Quartz更容易理解吗?