Java SQL 内存泄漏
Java SQL memory leak
我遇到一个问题,我在服务器上有一个 java 应用程序 运行,它在内存中开始增长,直到最终服务器无法再处理它。
这是某种内存泄漏/资源泄漏问题,我认为由于垃圾收集,这种情况在 Java 中极为罕见。我猜有些东西被引用但从未使用过,所以垃圾收集器不会收集它。
问题是内存中的大小增长得太慢,以至于我无法正确调试它(可能需要两周时间才能使服务器无法使用)。
我正在使用 java + mysql-connector,我确定内存泄漏是由与数据库连接相关的问题引起的。
这是我连接到数据库的方式:
private static Connection connect(){
try {
Connection conn = null;
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/database","client","password");
return conn;
}catch(SQLException ex){
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
return null;
}
}
public static Connection getConnection(){
try {
if (connection == null || connection.isClosed()) connection = connect();
return connection;
}catch (SQLException exception){
System.out.println("exception trying to connect to the database");
return null;
}
}
我在这里找不到任何可能的问题,但谁知道呢!
以下是我从数据库中检索信息的方法:
public void addPoints(long userId,int cantidad){
try {
if(DatabaseConnector.getConnection()!=null) {
PreparedStatement stm = DatabaseConnector.getConnection().prepareStatement("UPDATE users SET points = points + ? WHERE id = ? ");
stm.setLong(2, userId);
stm.setInt(1, cantidad);
if(stm.executeUpdate()==0){ //user doesn't have any point records in the database yet
PreparedStatement stm2 = DatabaseConnector.getConnection().prepareStatement("INSERT INTO users (id,points) VALUES (?,?)");
stm2.setLong(1, userId);
stm2.setInt(2, cantidad);
stm2.executeUpdate();
}
}
}catch (SQLException exception){
System.out.println("error recording points");
}
}
public ArrayList<CustomCommand> getCommands(long chatId) throws SQLException{
ArrayList<CustomCommand> commands = new ArrayList<>();
if(DatabaseConnector.getConnection() != null) {
PreparedStatement stm = DatabaseConnector.getConnection().prepareStatement("SELECT text,fileID,commandText,type,probability FROM customcommands WHERE chatid = ?");
stm.setLong(1, chatId);
ResultSet results = stm.executeQuery();
if(!results.isBeforeFirst()) return null;
while (results.next()){
commands.add(new CustomCommand(results.getString(1),results.getString(2),results.getString(3), CustomCommand.Type.valueOf(results.getString(4)),results.getInt(5)));
}
return commands;
}
return null;
}
也许问题与异常捕获和语句未正确执行有关?也许与结果集有关?
这让我疯狂。谢谢你帮助我!
在 return 之前,您没有清理 ResultSet
和 Statement
。这是个坏主意。您应该在 finally
块中的单个 try/catch 块中关闭每个块。
A ResultSet
是一个对象,表示数据库上的数据库游标。你应该关闭它,这样你就不会 运行 没有游标了。
我不会有一个静态 Connection
。我希望有一个 thread-safe 托管连接池。
我不会 return null。您不清楚用户应该用它做什么。最好抛出异常。
我遇到一个问题,我在服务器上有一个 java 应用程序 运行,它在内存中开始增长,直到最终服务器无法再处理它。
这是某种内存泄漏/资源泄漏问题,我认为由于垃圾收集,这种情况在 Java 中极为罕见。我猜有些东西被引用但从未使用过,所以垃圾收集器不会收集它。
问题是内存中的大小增长得太慢,以至于我无法正确调试它(可能需要两周时间才能使服务器无法使用)。 我正在使用 java + mysql-connector,我确定内存泄漏是由与数据库连接相关的问题引起的。
这是我连接到数据库的方式:
private static Connection connect(){
try {
Connection conn = null;
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/database","client","password");
return conn;
}catch(SQLException ex){
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
return null;
}
}
public static Connection getConnection(){
try {
if (connection == null || connection.isClosed()) connection = connect();
return connection;
}catch (SQLException exception){
System.out.println("exception trying to connect to the database");
return null;
}
}
我在这里找不到任何可能的问题,但谁知道呢!
以下是我从数据库中检索信息的方法:
public void addPoints(long userId,int cantidad){
try {
if(DatabaseConnector.getConnection()!=null) {
PreparedStatement stm = DatabaseConnector.getConnection().prepareStatement("UPDATE users SET points = points + ? WHERE id = ? ");
stm.setLong(2, userId);
stm.setInt(1, cantidad);
if(stm.executeUpdate()==0){ //user doesn't have any point records in the database yet
PreparedStatement stm2 = DatabaseConnector.getConnection().prepareStatement("INSERT INTO users (id,points) VALUES (?,?)");
stm2.setLong(1, userId);
stm2.setInt(2, cantidad);
stm2.executeUpdate();
}
}
}catch (SQLException exception){
System.out.println("error recording points");
}
}
public ArrayList<CustomCommand> getCommands(long chatId) throws SQLException{
ArrayList<CustomCommand> commands = new ArrayList<>();
if(DatabaseConnector.getConnection() != null) {
PreparedStatement stm = DatabaseConnector.getConnection().prepareStatement("SELECT text,fileID,commandText,type,probability FROM customcommands WHERE chatid = ?");
stm.setLong(1, chatId);
ResultSet results = stm.executeQuery();
if(!results.isBeforeFirst()) return null;
while (results.next()){
commands.add(new CustomCommand(results.getString(1),results.getString(2),results.getString(3), CustomCommand.Type.valueOf(results.getString(4)),results.getInt(5)));
}
return commands;
}
return null;
}
也许问题与异常捕获和语句未正确执行有关?也许与结果集有关? 这让我疯狂。谢谢你帮助我!
在 return 之前,您没有清理 ResultSet
和 Statement
。这是个坏主意。您应该在 finally
块中的单个 try/catch 块中关闭每个块。
A ResultSet
是一个对象,表示数据库上的数据库游标。你应该关闭它,这样你就不会 运行 没有游标了。
我不会有一个静态 Connection
。我希望有一个 thread-safe 托管连接池。
我不会 return null。您不清楚用户应该用它做什么。最好抛出异常。