2011-07-27 53 views
0

我使用while循环从Amazon SQS中获取消息。部分代码如下:java while循环内存泄漏

ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(myQueueUrl); 
while (true) { 
    List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages(); 

    if (messages.size() > 0) { 

      MemcachedClient c = new MemcachedClient(new BinaryConnectionFactory(), AddrUtil.getAddresses(memAddress)); 

      for (Message message : messages) { 

       // get message from aws sqs 
       String messageid = message.getBody(); 
       String messageRecieptHandle = message.getReceiptHandle(); 
       sqs.deleteMessage(new DeleteMessageRequest(myQueueUrl, messageRecieptHandle)); 

       // get details info from memcache 
       String result = null; 
       String key = null; 
       key = "message-"+messageid; 
       result = c.get(key); 

      } 
      c.shutdown(); 
      } 
     } 

在这种情况下会造成内存泄漏吗? 我使用“ps aux”进行检查。我发现的是RSS(驻留集大小,任务使用的非交换物理内存)正在缓慢增长。

+0

您正在循环中定义变量。将您的定义移动到循环上方并在循环中重新使用/重新分配。 –

+0

它只是增加开销,他们使用相同的指针,不是吗? –

+1

@ D.N .:这不应该有重大区别。编译器足够聪明,只需在堆栈中分配一次所需的本地数据。 –

回答

1

对不起,但我在这里看不到从消息队列中删除消息的代码。你是否清理了消息列表?如果DeleteRequest从队列中删除消息,那么你试图修改你迭代的消息列表。

此外,您现在可以使用visualvm工具获得更好的内存使用统计信息,该工具是JDK的一部分。

+0

每次迭代应删除对象的引用。所以列表大小不应该导致问题 –

+0

我不清除列表消息。我从列表中收到消息,然后从SQS中删除消息。但我不会触摸列表消息。在下一次迭代中,列表消息将获得来自SQS的新消息列表。这是个问题吗? – chnet

+0

@chnet:我想知道您的SQS是否会造成问题。消息应该是指向从SQS收到的对象的另一个参考。它应该没问题 –

2

无法简单地基于进程的RSS来评估Java应用程序是否存在内存泄漏。大多数JVM都非常贪婪,他们宁愿从操作系统中获取更多的内存,也不愿意花费大量的工作来处理垃圾收集。

这就是说你的while循环看起来好像没有任何明显的内存“泄漏”,但这取决于某些方法调用的做法(不包括上面的内容)。如果你将东西存储在静态变量中,这可能是一个值得关注的原因,但如果只有引用在循环的范围内,那么你可能没有问题。

要知道在某个代码区域是否有内存泄漏,最简单的方法是在应用程序的一次运行中严格运行该代码(可能设置的堆栈大小相对较低)。如果出现OutOfMemoryError,则可能是内存泄漏。