为什么我的Java应用程序(没有内存泄漏)会随着时间的推移变得越来越慢
因此,基本上我有一个java应用程序,即使我重置JVM,它也会随着时间的推移变得越来越慢。也没有检测到内存泄漏。在我将VM选项设置为-Xmx1024m后,GC工作正常 不管怎样,我试着做的是运行一个for循环,里面有一些代码超过40000次,但是速度越来越慢 循环是这样的,我必须删除针对版权问题的SQL查询:为什么我的Java应用程序(没有内存泄漏)会随着时间的推移变得越来越慢,java,performance,memory-leaks,garbage-collection,Java,Performance,Memory Leaks,Garbage Collection,因此,基本上我有一个java应用程序,即使我重置JVM,它也会随着时间的推移变得越来越慢。也没有检测到内存泄漏。在我将VM选项设置为-Xmx1024m后,GC工作正常 不管怎样,我试着做的是运行一个for循环,里面有一些代码超过40000次,但是速度越来越慢 循环是这样的,我必须删除针对版权问题的SQL查询: for (int ab = m;ab<=(duration);ab+=600){ jLabel_current.setText(String.valueOf(ab/600))
for (int ab = m;ab<=(duration);ab+=600){
jLabel_current.setText(String.valueOf(ab/600));
System.out.println(String.valueOf(ab/600));
System.out.println(String.valueOf(loop));
try{
con = datasource.getConnection();
for (int i=1;i<=4;i++){
String sql=" Some query ";
stmt = con.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
System.out.println(sql);
stmt = con.createStatement();
rs=stmt.executeQuery(sql);
while(rs.next()){
int a =rs.getInt("columnName");
sql="Some query";
pst1=con.prepareStatement(sql);
rs1=pst1.executeQuery();
if(rs1.next()){
x=rs1.getInt("columnName");
for(int b=0;b<x;b++){
if (loop!=max){
int task_id=parseWithDefault((jTable_task_main.getModel().getValueAt(loop, 1).toString()),0);
int jobb_id=parseWithDefault((jTable_task_main.getModel().getValueAt(loop, 4).toString()),0);
int idk=Integer.parseInt(String.valueOf(curTimeinner));
sql="insert into ";
pst2=con.prepareStatement(sql);
pst2.setInt(1, a);
pst2.setInt(2, rs1.getInt("columnName"));
pst2.setInt(3, rs1.getInt("columnName"));
pst2.setInt(4, rs1.getInt("columnName"));
pst2.setInt(5, rs1.getInt("columnName"));
pst2.setDouble(6, rs1.getDouble("columnName"));
pst2.setDouble(7, rs1.getDouble("columnName"));
pst2.setInt(8, rs1.getInt("columnName"));
pst2.setInt(9, rs1.getInt("columnName"));
pst2.setInt(10,n);
pst2.setInt(11,m);
pst2.setInt(12, g);
if(rs1.getLong("columnName")<=curTime){
currDuration=endTask-curTimeinner;
pst2.setLong(13, endTask);
pst2.setLong(14,currDuration );
if(rs.getLong("columnName")>endTask){
currTaskOut="successful";
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
}else{
currTaskOut="unsuccessful";
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
}
}else {
endTask2=rs1.getLong("columnName")+120;
pst2.setLong(13, endTask2);
pst2.setLong(14, currDuration);
if(rs.getLong("columnName")>endTask2){
currTaskOut="successful";
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
}else{
currTaskOut="unsuccessful";
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
}
}
pst2.execute();
loop+=1;
if(loop%4==0){
curTimeinner+=600;
String outcome=null;
String out1 = null;
String out2 = null;
String out3 = null;
String out4 = null;
ResultSet rs3=null;
for (int bv = 1; bv <= 4; bv++) {
outcome = "unsuccessful";
String sql1 = "select statment";
pst1 = con.prepareStatement(sql);
rs3 = pst1.executeQuery(sql1);
while (rs3.next()) {
if ("successful".equals(rs3.getString("task_outcome"))) {
outcome = "successful";
}
}
if (bv == 1) {
out1 = outcome;
} else if (bv == 2) {
out2 = outcome;
} else if (bv == 3) {
out3 = outcome;
} else {
out4 = outcome;
sql = "SELECT AUTO_INCREMENT";
pst1 = con.prepareStatement(sql);
rs3 = pst1.executeQuery(sql);
if (rs3.next()) {
res_id = rs3.getInt("AUTO_INCREMENT");
}
if ("successful".equals(out1) && "successful".equals(out2) && "successful".equals(out3) && "successful".equals(out4)) {
sql = "update statment";
pst1 = con.prepareStatement(sql);
pst1.execute();
} else {
sql = "update statment";
pst1 = con.prepareStatement(sql);
pst1.execute();
}
}
}
}
}
}
sql="update statment";
pst=con.prepareStatement(sql);
pst.execute();
}
}
}
curTime += 600;
endTask += 600;
ab+=600;
max+=4;
String sql="update statment";
pst=con.prepareStatement(sql);
pst.execute();
ab-=600;
}
catch (SQLException e ) {
JOptionPane.showMessageDialog(null, e);
} finally {
try { if (rs != null) rs.close(); } catch(Exception e) { }
try { if (stmt != null) stmt.close(); } catch(Exception e) { }
try { if (con != null) con.close(); } catch(Exception e) { }
try { if (pst != null) pst.close(); } catch(Exception e) { }
try { if (rs1 != null) rs1.close(); } catch(Exception e) { }
try { if (pst1 != null) pst1.close(); } catch(Exception e) { }
try { if (rs2 != null) rs2.close(); } catch(Exception e) { }
try { if (pst2 != null) pst2.close(); } catch(Exception e) { }
}
}
它充满了资源泄漏,主要是因为为另一个对象实例重用了一个变量,因此没有关闭先前的实例 将变量声明为接近其第一次使用,并使用try with资源: 这就解决了并发性问题,当两个插入同时发生时,新生成的密钥被获取:
1. A inserts
2. B inserts
3. B asks generated key
4. A asks generated key
请允许我指出两个最佳做法:
代码太长,像rs1/rs2/rs3这样的编号会使代码混淆。尝试介绍函数。给出有意义的全名
相同的防御性编码:不要在if语句中设置第i列:
int endTask = 0;
int currDuration = 0;
String currTaskOut = "";
if (rs1.getLong("columnName") <= curTime) {
//if (rs.getLong("columnName") > ...) {
endTask = ...;
currDuration = ...;
} else {
//...
}
pst2.setLong(13, endTask);
pst2.setLong(14, currDuration);
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
stmt.setFetchSizeInteger.MIN_VALUE?@BrianAgnew实际上这就是MySQL可能还有其他人要求您设置的,以便获得“不要预取所有内容”行为。@MarkoTopolnik非常有趣。谢谢你的建议,来点礼貌的格式化怎么样?你让我们在两个维度上滚动,同时试图理解它。@Brian Agnew Yep“尝试使用资源”就是答案。非常感谢,尽管您忘记在PreparedStation中请求生成的密钥。
String sql1 = "INSERT INTO table(col2, col3) VALUES(?, ?)";
try (PreparedStatement pst1 = con.prepareStatement(sql1, Statement.RETURN_GENERATED_KEYS))) {
int updateCount = pst1.executeUpdate();
if (updateCount != 0) { // Records inserted?
int res_id = 0; // Key
try (ResultSet generatedKeysRS = pst1.getGeneratedKeys()) {
if (generatedKeysRS.next()) {
res_id = generatedKeysRS.getInt(1);
}
}
}
}
1. A inserts
2. B inserts
3. B asks generated key
4. A asks generated key
int endTask = 0;
int currDuration = 0;
String currTaskOut = "";
if (rs1.getLong("columnName") <= curTime) {
//if (rs.getLong("columnName") > ...) {
endTask = ...;
currDuration = ...;
} else {
//...
}
pst2.setLong(13, endTask);
pst2.setLong(14, currDuration);
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);