如何解决java.lang.StackOverflowError错误

3
这是我第一次收到这个错误。 这段代码基本上获取了特定日期销售的每个商品的总数。 有解决这个问题的任何提示吗?谢谢。
       Statement statement = connection.createStatement();
       String query = "SELECT itemcode, SUM(quantity) AS 'Total Sales Per Day' "
               + "FROM sales "
               + "WHERE real_pur_date = '" + date + "' "
               + "GROUP BY itemcode ";
       ResultSet rs = statement.executeQuery( query ); // this line gets the error / exception
       while( rs.next() ){
           Vector row = new Vector();
           row.add( rs.getString( "itemcode" ) );
           row.add( rs.getInt( "Total Sales Per Day" ) );
           dailyData.add( row );
       }
       statement.close();
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at com.mysql.jdbc.Util.handleNewInstance(Util.java:431)
at com.mysql.jdbc.ResultSetImpl.getInstance(ResultSetImpl.java:383)
at com.mysql.jdbc.MysqlIO.buildResultSetWithRows(MysqlIO.java:3140)
at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:491)
at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3118)
at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2288)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2709)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2677)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2627)
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1556)
at posinventory.Controller.StatisticEngine.getDailyData(StatisticEngine.java:20)
at posinventory.Statistic.refreshTableDailyStat(Statistic.java:36)
at posinventory.Statistic.refreshTableDailyStat(Statistic.java:37)
at posinventory.Statistic.refreshTableDailyStat(Statistic.java:37)
at posinventory.Statistic.refreshTableDailyStat(Statistic.java:37)

3
首先,永远不要使用 Vector。改用 ArrayList 替代。 - Alexis Dufrenoy
1
你没有粘贴足够的堆栈跟踪信息来看到循环。StackOverflowError(SOE)几乎总是无限递归的结果。万一这里不是这种情况,解决方法非常简单:向JVM传递一个增加堆栈大小的参数。 - Marko Topolnik
1
@Traroth,如果你需要在多线程环境下使用动态调整大小的数组,请使用Vector - Alex Lockwood
2
请记住,由于您拥有SOE,因此抛出错误的那一行绝对没有问题。它只是压垮骆驼的最后一根稻草。 - Marko Topolnik
2
@AlexLockwood Vector是同步的,但仅凭这一点并不能使其线程安全。这就是反对Vector的论点的关键:它在提供很少或没有好处的同时浪费了锁定时间。 - Marko Topolnik
显示剩余18条评论
3个回答

5

我认为你提供的代码片段不是问题所在。查看堆栈跟踪底部,我发现Statistic.java:37 明显多次调用自身。递归调用是允许的,但如果没有受到控制就会导致堆栈溢出。看起来你有一个循环...


4

您真的应该发布来自posinventory.Statistic.refreshTableDailyStat的代码,但我猜测:在该方法中,第36行调用StatisticEngine.getDailyData;第37行递归调用refreshTableDailyStat - 所以问题出在这里,Statistic.java,第37行。


2

去掉查询中的 :: 和字符串拼接符 '+',因为 JVM 使用字符串池,对于每种类型的字符串,它都会调用一个服务来检查该字符串是否存在。

使用 String Builder 代替。

删除 Vector 并将其替换为 ArrayList,正如 Steve 上面提到的,检查您的代码片段是否发生了未知递归。


1
在这种情况下,使用StringBuilder并没有什么区别。 - Roger Lindsjö
字符串查询 = "SELECT itemcode, SUM(quantity) AS '每日总销售额' " + "FROM sales " + "WHERE real_pur_date = '" + date + "' " + "GROUP BY itemcode ";可以用 StringBuilder 替换。 - Sashi Kant
你们两个都错了。即使使用StringBuilder,那种类型的代码也会导致SQL注入攻击。相反,你应该使用PreparedStatement。PreparedStatement - Luiggi Mendoza
@SashiKant 在问题中添加字符串是可以的,使用StringBuilder也无法改进它。 - Roger Lindsjö
@LuiggiMendoza 当然应该使用PreparedStatement来执行查询,我是在指String连接和StringBuilder之间的区别。 - Roger Lindsjö
@RogerLindsjö,当您想要改进答案时,请尝试提供更好的指导,而不是将其变成长时间讨论或仅检查基本情况的机会。 - Luiggi Mendoza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接