带有 JDBC 的 Java SQLException - SQLITE_MISUSE

Posted

技术标签:

【中文标题】带有 JDBC 的 Java SQLException - SQLITE_MISUSE【英文标题】:Java SQLException with JDBC - SQLITE_MISUSE 【发布时间】:2016-03-14 19:52:25 【问题描述】:

我在我的 Java 应用程序中使用 SQlite。如果我运行我的程序,它会在某个时候出错。

有时这是一个简单的异常,有时 JVM 出现致命错误。

java.sql.SQLException: [SQLITE_MISUSE] 库使用不正确(内存不足)


Java 运行时环境检测到致命错误:

在 pc=0x000000006d587ab0, pid=7036, tid=6364 处的 EXCEPTION_ACCESS_VIOLATION (0xc0000005)

JRE 版本:Java(TM) SE 运行时环境 (8.0_73-b02) (build 1.8.0_73-b02) Java VM:Java HotSpot(TM) 64 位服务器 VM(25.73-b02 混合模式 windows-amd64 压缩 oops) 有问题的框架: C [sqlite-3.8.11.2-6df82281-eaf0-4204-a962-ce1e48ddd89f-sqlitejdbc.dll+0x7ab0]

无法写入核心转储。默认情况下,在 Windows 的客户端版本上不启用小型转储

包含更多信息的错误报告文件保存为: C:\Users\UltraMouse\workspace\co.windall.twitter\hs_err_pid7036.log

如果您想提交错误报告,请访问: http://bugreport.java.com/bugreport/crash.jsp 崩溃发生在 Java 虚拟机之外的本地代码中。 请参阅有问题的框架以了解报告错误的位置。

导致这种情况的代码行是

ResultSet rs = stmt.executeQuery("SELECT * FROM User WHERE id=" + id.toString() + ";");

这是不一致的,它每次都发生在不同的点(此代码处于循环中)但它总是发生。

这是我的完整源文件: http://pastebin.com/RKKVdNZ8 http://pastebin.com/fVaa93Rk

我每次都干净地运行它(我删除了数据库文件)。它目前在 file1 的第 102 行失败。

我不知道该怎么办:(

是的,这些 twitter 密钥现在可以使用,但仅限于读取访问权限,我将它们留在那里,以便您也可以在需要时试用该应用程序。

【问题讨论】:

因为解决您的问题的尝试似乎没有奏效,我建议您进行异常处理。不要只捕获异常,而是分别知道它的子类。这应该可以帮助您本地化错误代码。有了它,您可以自己解决或发布另一个问题。 【参考方案1】:

很难看出到底出了什么问题,但您绝对应该在每次操作后关闭您的语句和ResultSets。

这很可能导致您看到的内存泄漏:

Statement stmt = connection.createStatement();

应该在每个新操作之前调用

stmt.close();

应该在每次操作后调用。所以总而言之,你的主循环应该是这样的:

for (Long id : ids) 
    Statement stmt;
    ResultSet rs;
    try 
        st = connection.createStatement();
        rs = stmt.executeQuery("...");

        if (rs.next()) 
            Long ft = rs.getLong("followedThem");
            rs.close();
            st.close();

            st = connection.createStatement();
            String sql = "...";

            if (ft != null && ft == -1) 
                sql = x;
             else 
                sql = y;
            

            st.executeUpdate(sql);
            st.close();
         catch (SQLException e) 
    

【讨论】:

我确实是这样开始的,那段代码是在我搞砸了一点之后。循环中的语句没有区别。 我现在在同一个地方测试了它的错误:java.sql.SQLException: statement is not execution 现在有什么异常? @leumas95 您仍在使用您的语句对象来获取两个不同的结果集。我在回答中描述了这个问题。尝试对每个 ResultSet 使用新语句。 @epoch java.sql.SQLException: 语句未执行【参考方案2】:

根据statement documentation

每个 Statement 对象只能同时打开一个 ResultSet 对象 时间

因此,您的语句的重用应该是问题,因为它隐式关闭了您的其他 ResultSet

Statement 接口中的所有执行方法都会隐式关闭一个 语句的当前 ResultSet 对象(如果存在打开的对象)。

但在某些情况下,循环可能需要再次关闭已经关闭的 ResultSet,因此会导致异常。


更新:

    我会将两个语句的两个异常处理分开 我会使用两个语句对象

    在我的代码中,我总是在尝试关闭 ResultSet 或 Statements 之前检查它们是否为 != null。

    for (Long id : ids) 
        Statement st, st2;
        ResultSet rs;
        Long ft = 0;
        try 
            st = connection.createStatement();
            rs = st.executeQuery("SELECT * FROM User WHERE id=" + id.toString() + ";");
    
            if (rs.next()) 
                ft = rs.getLong("followedThem");
                if (rs != null)
                    rs.close();
                if (st != null)
                    st.close();
            
         catch (SQLException e) 
            System.err.println(e.getClass().getName() + ": " + e.getMessage());
            e.printStackTrace();
            System.err.println(id);
            System.exit(0);
        
    
        if (ft != 0) 
            try 
                st2 = connection.createStatement();
                String sql = "";
    
                if (ft != null && ft == -1) 
                    sql="UPDATE User SET followedThem=" + String.valueOf(Instant.now().getEpochSecond()) + " WHERE id=" + id.toString() + ";";
                 else 
                    sql=String.format("INSERT INTO User (id,followedMe,followedThem,unfollowedMe,unfollowedThem,status) " +
                        "VALUES (%d, %d, %d, %d, %d, %d);", id, -1, Instant.now().getEpochSecond(), -1, -1, 0);
                
    
                st2.executeUpdate(sql);
                if (st2 != null)
                    st2.close();
    
             catch (SQLException e) 
                System.err.println(e.getClass().getName() + ": " + e.getMessage());
                e.printStackTrace();
                System.err.println(id);
                System.exit(0);
            
        
    
    

【讨论】:

以上是关于带有 JDBC 的 Java SQLException - SQLITE_MISUSE的主要内容,如果未能解决你的问题,请参考以下文章

jdbc连接mysql

Spring对JDBC的最佳实践--上

JDBC之增删改查的代码实现

带有 JDBC 的 Java SQLException - SQLITE_MISUSE

带有 sql 语句的 Java JDBC exec 过程

带有 maven 的 mysql 连接器:java.lang.NoClassDefFoundError: com/mysql/jdbc/Driver