我写的一段程序,实现每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有没有不知道。
|
这个信息太有营养了,好好看看。 |
|
问题还是没有解决,但依然有很多收获,谢谢各位!
|