Code Bye

java heap space异常

 

我写的一段程序,实现每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的某一次调用需要的空间很大(这次的记录行数太多),结果超出。
引用 5 楼 stonefeng 的回复:

list.clear();之后再做一次垃圾回收试试看。
另外把堆空间开大些,也许内存占用会停在某个地方不再增长了,这主要是防止updateCar的某一次调用需要的空间很大(这次的记录行数太多),结果超出。

一般不是不推荐自己手动调用gc进行垃圾回收的吗?它会破坏JVM中对象之间的链路关系,影响后续JVM自己回收垃圾时对对象引用的判断么?

引用 6 楼 magi1201 的回复:
Quote: 引用 5 楼 stonefeng 的回复:

list.clear();之后再做一次垃圾回收试试看。
另外把堆空间开大些,也许内存占用会停在某个地方不再增长了,这主要是防止updateCar的某一次调用需要的空间很大(这次的记录行数太多),结果超出。

一般不是不推荐自己手动调用gc进行垃圾回收的吗?它会破坏JVM中对象之间的链路关系,影响后续JVM自己回收垃圾时对对象引用的判断么?

不会吧?哪里来的说法?官方的?如果只是调用一下gc,就影响了jvm自己对对象引用的判断,那么这个垃圾回收算法也太脆弱了吧?这样的算法就该扔掉了!手工gc只是通知一下jvm可能的情况下尽快回收一次,至于应该怎么回收,仍然由jvm说了算,又不是你自己写程序回收的。既然jvm说了算,他自己回收了一次,第二次就不行了?这个太不符合逻辑了。

引用 7 楼 stonefeng 的回复:

不会吧?哪里来的说法?官方的?如果只是调用一下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点半蹦的

实在不好找的话,就用操纵系统定时任务,每小时调用一次。而程序也每小时自动退出。这样就不会内存溢出了。
引用 13 楼 stonefeng 的回复:

实在不好找的话,就用操纵系统定时任务,每小时调用一次。而程序也每小时自动退出。这样就不会内存溢出了。

谢谢了,我还是挺想知道问题出的位置的,改成计划任务有点遗憾啊

只有这一点儿代码吗?查查其他代码。
引用 14 楼 jeff0002 的回复:
Quote: 引用 13 楼 stonefeng 的回复:

实在不好找的话,就用操纵系统定时任务,每小时调用一次。而程序也每小时自动退出。这样就不会内存溢出了。

谢谢了,我还是挺想知道问题出的位置的,改成计划任务有点遗憾啊


80分
jdk1.8有个 Java Mission Control,应该可以分析什么东西占用了大量内存,你可以在7、8个小时的时候用这个找找,应该有帮助。1.7有没有不知道。
引用 16 楼 stonefeng 的回复:

jdk1.8有个 Java Mission Control,应该可以分析什么东西占用了大量内存,你可以在7、8个小时的时候用这个找找,应该有帮助。1.7有没有不知道。

这个信息太有营养了,好好看看。

问题还是没有解决,但依然有很多收获,谢谢各位!

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明java heap space异常