我的java程序在测试性能时遇到内存泄漏的问题。
大概情况是这样的,我用udp发送数据,一条数据长度为8192byte,在外部的循环中发送10000次。
jvm的参数是-Xms256M -Xmx256M。
在测试过程中经常出现内存不足的问题,一般发送4800条左右就报内存不足的exception了。
经过调查大概有两处地方导致。
一处是在发送数据前我对数据处理调用过System.arraycopy的方法,这里我改为for循环来拷贝数组就通过了。
另一处是socket.send(packet);这处只要我注释掉这条语句10000条就可以通过,20000或30000都没有问题,但是只要一打开这条语句就会报内存不足。这处我绕不过去了,很是着急。下面是一点代码片段,这个片段就是循环中发送数据的代码,是在一个线程的run方法中被调用的
String strMessage = sendIterator.next();
byte[] buf = message.getMessageContent(strMessage);
DatagramPacket packet = new DatagramPacket(
buf,
buf.length,
address,
message.getNetInfo().GetPort());
socket.send(packet);
另外,在message.getMessageContent中调用了System.arraycopy。
public synchronized byte[] getMessageContent(String data) {
byte[] temp; if(netInfo.GetAddLen()) {
data = (TrxSimUtil.getHexFormat(data.length() / 2) + data);
} if(netInfo.GetDataMode() == TrxSimConstant.BINARY) {
temp = transferAsciiToBinary(data);
} /* end of if */
else {
temp = data.getBytes();
} /* end of else */ int length = temp.length; if(netInfo.GetAddBit()) {
length += 2;
} /* end of if */ int start = 0;
byte[] content = new byte[length];
if(netInfo.GetAddBit()) {
start = 1;
content[0] = 2;
content[length - 1] = 3;
} /* end of if */ //System.arraycopy(temp, 0, content, start, temp.length);
for( int i=0; i<temp.length ; i++ ){
content[start+i] = temp[i];
}
return content;
} /* end of function */
大概情况是这样的,我用udp发送数据,一条数据长度为8192byte,在外部的循环中发送10000次。
jvm的参数是-Xms256M -Xmx256M。
在测试过程中经常出现内存不足的问题,一般发送4800条左右就报内存不足的exception了。
经过调查大概有两处地方导致。
一处是在发送数据前我对数据处理调用过System.arraycopy的方法,这里我改为for循环来拷贝数组就通过了。
另一处是socket.send(packet);这处只要我注释掉这条语句10000条就可以通过,20000或30000都没有问题,但是只要一打开这条语句就会报内存不足。这处我绕不过去了,很是着急。下面是一点代码片段,这个片段就是循环中发送数据的代码,是在一个线程的run方法中被调用的
String strMessage = sendIterator.next();
byte[] buf = message.getMessageContent(strMessage);
DatagramPacket packet = new DatagramPacket(
buf,
buf.length,
address,
message.getNetInfo().GetPort());
socket.send(packet);
另外,在message.getMessageContent中调用了System.arraycopy。
public synchronized byte[] getMessageContent(String data) {
byte[] temp; if(netInfo.GetAddLen()) {
data = (TrxSimUtil.getHexFormat(data.length() / 2) + data);
} if(netInfo.GetDataMode() == TrxSimConstant.BINARY) {
temp = transferAsciiToBinary(data);
} /* end of if */
else {
temp = data.getBytes();
} /* end of else */ int length = temp.length; if(netInfo.GetAddBit()) {
length += 2;
} /* end of if */ int start = 0;
byte[] content = new byte[length];
if(netInfo.GetAddBit()) {
start = 1;
content[0] = 2;
content[length - 1] = 3;
} /* end of if */ //System.arraycopy(temp, 0, content, start, temp.length);
for( int i=0; i<temp.length ; i++ ){
content[start+i] = temp[i];
}
return content;
} /* end of function */
解决方案 »
- 紧急求救,unix下的编译命令转换成xp下的
- 初学JAVA,package怎么使用
- Listenert和Adapter区别是什么?
- 编译时提示:包不存在! 快帮忙看一下吧,做不完,年就过不好了,要提前来加班做呀............................
- 画图每次自动刷屏,怎么回事?前辈请指点!急急,在线等待!!
- 在Eclipse中如何将现有的java文件加入到工程中
- 初学者的一个问题,请大家指教!
- 我的收收藏我资料全部不见了
- Dos下在运行java MyTest 报错,在线等待,救!
- 好消息!!!!!关于?JB7补丁的!!!!!不得不看!!!!!
- socket通信出现乱码。帮帮忙
- JDK or JVM 的bin、Lib?
则10000次可以通过,但是美中不足的是会抛几条exception(在10000次中),
虽然感觉这exception对数据发送似乎没有什么影响,因为单独发一条是可以确认发出去的。代码片段如下:
String strMessage = sendIterator.next();
byte[] buf = message.getMessageContent(strMessage);
DatagramPacket packet = new DatagramPacket(
buf,
buf.length,
address,
message.getNetInfo().GetPort());
socket.send(packet);
packet.setData(null);
记得在使用数据库连接池的时候如果循环后没有关掉,则小容量数据时没有问题,一到大批量数据的时候就报错,检查的时候真是出汗:怎么会犯这种错误...
byte[] buf = message.getMessageContent(strMessage);
DatagramPacket packet = new DatagramPacket(
buf,
buf.length,
address,
message.getNetInfo().GetPort());
socket.send(packet);
packet = null ;
解决的要点是:
待发送的数据,是String型,会先调一个函数处理一下,其中使用了StringBuilder,
然后会对这个StringBuilder调toString取得内容继续使用。
现在改为,不用StringBuilder而用String类型,就通过了。旧代码片断:
(1)
StringBuilder validData = new StringBuilder();
checkDataLengthCorrect(netInfo, data, validData);
data = validData.toString();
(2)
public static boolean checkDataLengthCorrect(
NetInfo netInfo,
String data,
StringBuilder validData) {
int length = data.length() / 2; if(length > TrxSimConstant.COMM_MAX_BUFFER) {
validData.append(data.substring(
0,
TrxSimConstant.COMM_MAX_BUFFER * 2));
return true;
}
else {
validData.append(data);
return false;
}
}新代码片断:
(1)
StringBuilder validData = new StringBuilder();
data = checkDataLengthCorrect(netInfo, data, validData);
(2)
public static String checkDataLengthCorrect(
NetInfo netInfo,
String data,
StringBuilder validData) {
int length = data.length() / 2; if(length > TrxSimConstant.COMM_MAX_BUFFER) {
validData.append(data.substring(
0,
TrxSimConstant.COMM_MAX_BUFFER * 2));
data = data.substring(
0,
TrxSimConstant.COMM_MAX_BUFFER * 2);
//return true;
}
else {
validData.append(data);
//return false;
}
return data;
}说明:
代码(1)是在一个用于往待send的数据集合添加待send数据的函数中被调用的。
然后另外有一个线程从这个数据集合中取数据一条条实际send出去。