|
我写的一段程序,实现每10s将远程数据库的信息写入到本地的数据库,这个程序能够运行正常,但超过10个小时左右就会报出java heap space异常,具体请看代码: public class sy_car implements Runnable,remoteDB{
static Connection dbConn=null;
ArrayList<TreeMap> list=new ArrayList<TreeMap>();
locServer l=new locServer();
static DataBaseConnection d=new DataBaseConnection();
Statement stmt=null;
public sy_car(JTextArea t){
try{
Class.forName(driverName);
dbConn = DriverManager.getConnection(dbURL, userName, userPwd);
t.append(utils.CommonFun.getCurrentTime()+":已经建立同GPS数据的同步\r\n");
}catch(Exception e){
//e.printStackTrace();
t.append(utils.CommonFun.getCurrentTime()+":"+"访问远程主机失败"+"\r\n");
}
}
/**
* @param args
*/
public void updateCar(){
list.clear();
ResultSet rs=null;
try {
stmt=dbConn.createStatement();
String sql="select a.ClientID,b.isOpen,b.LocDate,b.Latitude,b.Longitude,b.Direction from ClientInfo a " +
"left join CarMark b on a.ClientID=b.ClientID where CompanyID=""1241""";
rs=stmt.executeQuery(sql);
int i=0;
while(rs.next()){
TreeMap t=new TreeMap();
t.put("ClientID", rs.getString("ClientID"));
t.put("LocDate", rs.getString("LocDate"));
t.put("Latitude", rs.getString("Latitude"));
t.put("Longitude", rs.getString("Longitude"));
t.put("Direction", rs.getString("Direction"));
t.put("isOpen", rs.getString("isOpen"));//此处报出错误信息
list.add(t);
}
} catch (Exception e) {
}finally{
try {
rs.close();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
for(int i=0,n=list.size();i<n;i++){
TreeMap t=list.get(i);
l.updateCar(String.valueOf(t.get("ClientID")),
String.valueOf(t.get("LocDate")),
String.valueOf(t.get("Longitude")),
String.valueOf(t.get("Latitude")),
String.valueOf(t.get("Direction")),
String.valueOf(t.get("isOpen")),
d);
}
}
public static void close(){
try {
dbConn.close();
d.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void run() {
while(true){
try {
updateCar();
Thread.sleep(10000);
} catch (Exception e) {}
}
}
}
请指点如何改正,高分求解,谢谢。 |
|
![]() 10分 |
jvm虚拟机默认Heap大小64M,通过设置其大和小值来实现
参考 Java heap space |
![]() |
这个功能我要一直使用,即便开的更大,那也会有出问题的时候,所以我想还是从代码角度解决这个问题,毕竟几小时内饰没有问题的
|
![]() |
你要及时清理不用的对象引用,以防止内存泄漏,使内存使用始终保持在某个范围内。
|
![]() |
是啊,这个也是我关心的问题,在这个程序里我感觉该释放的都释放了,问题的原因是哪句呢,请指教
|
![]() |
list.clear();之后再做一次垃圾回收试试看。
另外把堆空间开大些,也许内存占用会停在某个地方不再增长了,这主要是防止updateCar的某一次调用需要的空间很大(这次的记录行数太多),结果超出。 |
![]() |
一般不是不推荐自己手动调用gc进行垃圾回收的吗?它会破坏JVM中对象之间的链路关系,影响后续JVM自己回收垃圾时对对象引用的判断么? |
![]() |
不会吧?哪里来的说法?官方的?如果只是调用一下gc,就影响了jvm自己对对象引用的判断,那么这个垃圾回收算法也太脆弱了吧?这样的算法就该扔掉了!手工gc只是通知一下jvm可能的情况下尽快回收一次,至于应该怎么回收,仍然由jvm说了算,又不是你自己写程序回收的。既然jvm说了算,他自己回收了一次,第二次就不行了?这个太不符合逻辑了。 |
![]() |
大牛 刚去看了下,gc 也只是告诉jvm该回收垃圾了,具体何时回收那还是JVM说了算 记错了,不推荐使用的是finalize() 方法。 |
![]() |
哦,我每次获得的记录数量都是一致的,不会有增加,因此堆空间应该足够,后一种方法我试试看,谢大神指教
|
![]() |
遇到过这个问题,jsp的,把tomcat重新换个目录,如d盘根目录。
|
![]() 10分 |
你每次都这么巧在这里报错吗?t.put(“isOpen”, rs.getString(“isOpen”));//此处报出错误信息
大概看了一下你这段代码没发现什么能造成明显内存泄露的地方,你检查过你的其他代码吗? |
![]() |
感谢大家昨天的回复,我试了一下,今天错误的位置报告在方法里
public boolean updateCar(String imei,String locdate,String jd,String wd,String fx,String isOpen,DataBaseConnection d){
System.gc();
boolean ret=false;
StringBuffer sb=new StringBuffer();
sb.append("update cheliang set")
.append(" jd=").append(jd).append(",")
.append(" wd=").append(wd).append(",")
.append(" fx=").append(fx).append(",")
.append(" locdate=").append("""").append(locdate).append("""");
if("0".equals(isOpen)){
sb.append(" ,state=""6""");
}
sb.append(" where imei=").append("""").append(imei).append("""");
//System.out.println(sb.toString());
d.executeUpdate(sb.toString());//此处报错
ret=true;
return ret;
}
错误信息依旧,实在看不出有哪里内存泄露了,昨天晚上11点开的服务,今天早上7点半蹦的 |
![]() |
实在不好找的话,就用操纵系统定时任务,每小时调用一次。而程序也每小时自动退出。这样就不会内存溢出了。
|
![]() |
谢谢了,我还是挺想知道问题出的位置的,改成计划任务有点遗憾啊 |
![]() |
只有这一点儿代码吗?查查其他代码。
|
![]() 80分 |
jdk1.8有个 Java Mission Control,应该可以分析什么东西占用了大量内存,你可以在7、8个小时的时候用这个找找,应该有帮助。1.7有没有不知道。
|
![]() |
这个信息太有营养了,好好看看。 |
![]() |
问题还是没有解决,但依然有很多收获,谢谢各位!
|

