【问题标题】:Problem with static variables in javajava中的静态变量问题
【发布时间】:2011-08-30 07:24:28
【问题描述】:

我在我的应用程序中大量使用静态变量。现在,在应用程序状态完成后,我面临着垃圾收集的问题。声明为静态的变量永远不会被垃圾回收,我的内存很快就会耗尽。

具体问题出在mysql连接上。我将连接变量存储在静态变量中,因此每次运行查询时都不必打开连接。这导致每次我使用连接变量执行查询时都会出现使用所有内存的问题,并且使用的内存没有被释放。将连接变量存储在静态变量中是个好主意吗?当我每次尝试在没有静态变量的情况下打开和关闭连接时,我解决了内存管​​理问题,但应用程序的响应速度减慢了 10 到 20 倍。

您需要更多信息来理解这个问题吗?如果是,请在不投反对票的情况下问我。谢谢!

编辑 这是我的连接器类

import java.sql.*;

public class connect {

    public Connection conn = null;

    public connect() {
        try {
            if (conn == null) {
                String userName = "root";
                String password = "password";               
                String url = "jdbc:mysql://localhost/pos?zeroDateTimeBehavior=convertToNull";                
                Class.forName("com.mysql.jdbc.Driver").newInstance();
                conn = DriverManager.getConnection(url, userName, password);               
                System.out.println("Database connection established");               
            }
        } catch (Exception e) {
            System.err.println("Cannot connect to database server");           
        }
    }
}

这是我存储连接的班级

public class variables {
    public static connect con = new connect();
}

我使用这个方法来执行查询

public class mysql_query {
public static ResultSet execute_mysql(Connection con, String sqlStatement) {
        try {
            //ResultSet result = null;
            java.sql.Statement cs = con.createStatement();
            ResultSet result = cs.executeQuery(sqlStatement);
            return result;
        } catch (SQLException ex) {
            Logger.getLogger(mysql_query.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }

    }

 public static void main(String args[]){
     String sql = "SELECT * FROM pos_user_login WHERE moderator='1' AND "
                    + "company_id='1'";

     ResultSet rs = execute_mysql(variables.con.conn, sql);
  }
}

【问题讨论】:

  • 澄清一下:您是否使用同一个连接对象来执行应用程序中的所有查询?您使用的是什么特定的连接类?
  • 很难说。你能描述一下你的应用吗?是批处理作业吗?一个摇摆应用程序?一个网络应用程序?可以使用套接字连接到的独立服务器?等等……
  • @Lukas Eder:它是一个摇摆应用程序
  • 当你说“每次都打开连接”时,你的意思是“每次都做一个新的连接对象”?
  • 从您发布的代码中,您似乎很清楚您没有正确关闭您的资源...在我的回答中查看如何执行此操作的示例...

标签: java mysql static connection


【解决方案1】:

只是一个想法:您可能没有正确关闭 ResultSetStatement 对象。如果您不这样做,MySQL JDBC 驱动程序可能会保留许多您不再需要的资源。尤其是ResultSet 可能会非常痛苦,因为数据库游标的某些部分仍在内存中。

给你一个想法的例子是这样的:

PreparedStatement stmt = null;
ResultSet rs = null;

try {
    stmt = connection.prepareStatement(...);
    rs = stmt.executeQuery();
}

// Close your resources in a finally block! Because the finally block
// is executed even if you have exceptions in the try block.
// If you do this a lot of times, write utility methods...
finally {
    try {
        if (rs != null) {
            rs.close();
        }
    } catch (SQLException ignore) {}

    try {
        if (stmt != null) {
            stmt.close();
        }
    } catch (SQLException ignore) {}
}

【讨论】:

  • 所以看看你的例子和我添加的编辑可能是原因!我说的对吗??
  • 我很确定它是。不关闭这些资源是非常常见的内存泄漏
  • 所以我还必须使用连接池来解决问题吗??
  • 正如迈克尔所说,使用连接池,您不会使用更少的内存。当您有大量线程访问数据库时(例如在 Web 服务器中),处理连接的生命周期会更容易。但在您的情况下,连接池可能不是必需的。至少不是为了手头的内存问题
【解决方案2】:

也许使用连接池而不是静态变量会更好...连接池维护一堆打开的连接并在需要时提供它们。应该可以解决您的性能问题和内存问题。

【讨论】:

  • 那么这是否意味着我应该摆脱静态变量并使用连接池??
  • 如果是一个 Swing 应用程序,只有一个线程访问数据库,一个连接就足够了。拥有多个连接不会比只有一个连接使用更少的内存。但我看不出单个连接对象如何使用整个内存。
  • @JB Nizet:实际上每次我执行查询时都会创建对象。我不知道为什么会发生。我已经添加了代码,如果你可以看看并告诉我它是什么,我会很高兴。
  • @Deepak:看看 Lukas Eder 的回答。
【解决方案3】:

静态变量不会被垃圾收集,但如果您只是存储一些连接数据,那应该不是问题。你到底在存储什么?

马特奥

【讨论】:

    【解决方案4】:

    好吧,从你所说的来看,你有一个对象(我们称之为 Obj)类,它包含带有连接的静态变量。由于您每次都创建一个新的 Obj 并且您在那一刻存储它,我认为您正在做大量的连接副本,因为它们是静态的,JVM 无法清理它们。

    您可以考虑将此类信息存储在 Model 类中的可能性,或者删除静态标记以让 JVM 正确收集这些对象。

    【讨论】:

    • 你能指出我每次都在哪里创建新对象吗!!我迷路了!谢谢!!
    • 好吧,当你创建一个新的变量对象时,你就创建了一个新的连接。如果您在此构造函数的所有执行中调用一次,我的答案就失去了重要性,但如果您每次都调用它,那么,这里就是您创建大量连接对象的地方。这不一定是坏事,但如果你这样做,你必须关闭资源(就像@Lukas Eder 在他的代码中所做的那样)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多