当我向云服务器(PasS,128Mb)部署战争时遇到问题,然后在我的应用程序中有两个计时器。


Timer1将每小时执行一次任务以记录我的内存(以及#2中描述的Map)。
每次创建“房间”对象时,都会将此房间放入地图中,因此当我启动“房间”以从地图中删除该对象时,我就有一个Timer2来创建任务。


我碰巧知道我不应该使用计时器。

但是问题是我检查了Timer1记录的日志,我的freeMemory每小时下降一次,总内存是相同的。

我已经读过What are Runtime.getRuntime().totalMemory() and freeMemory()?,所以我知道总内存和freeMemory意味着什么。并且根据日志,我的已用内存正在增加!

PS:我不使用任何新的Runnable或Thread来处理任何长时间运行的逻辑。

日志就像:

2014-07-22 04:39:27  [ Timer-10:44100005 ] - [ INFO ]
maxMemory()=128
totalMemory() = 75
freeMemory()= 44
2014-07-22 04:39:27  [ Timer-10:44100005 ] - [ INFO ]  Now there are Existing Room of : 0

2014-07-22 05:39:27  [ Timer-10:47700005 ] - [ INFO ]
maxMemory()=128
totalMemory() = 75
freeMemory()= 41
2014-07-22 05:39:27  [ Timer-10:47700005 ] - [ INFO ]  Now there are Existing Room of : 0

2014-07-22 06:39:27  [ Timer-10:51300006 ] - [ INFO ]
maxMemory()=128
totalMemory() = 75
freeMemory()= 39


每当此sevlet收到请求时,我都会记录日志,因此我确定不会处理任何请求,但是为什么可用内存减少了。

1. Timer1的工作方式如下:

@Override
public void init() throws ServletException {
    super.init();
    LogUtil.info("CoreServlet inits");
    memoryTimer=new Timer(true);
    //check the memory every 1 hour,first time will be delayed to 15 mins later
    memoryTimer.schedule(new checkMemoryTask(),TimeConstant.FIFTHTEEN_MINUTES_MILISECONDS,TimeConstant.ONE_HOUR_MILISECONDS);
    commandService = CommandService.getInstance();
}


2.这就是Timer2的工作方式。

public Room newRoom() {
    Integer randomNumObject;

    LogUtil.debug("Trying to new a room with the random number");
    //generate a random number util the number is not a existing room number
    do {
        randomNumObject=generateRandom(4);//4 digits room number
    } while (roomMap.containsKey(randomNumObject));//roomNum is existing, continue to find

    Room newRoom=new Room(randomNumObject);//use this number to create a new room

    roomMap.put(randomNumObject, newRoom);
    //abandon the room after 15 MINTES
    roomClearTimer.schedule(new abandonRoomTask(randomNumObject.intValue()), TimeConstant.FIFTHTEEN_MINUTES_MILISECONDS);
    LogUtil.info(newRoom+" is scheduled to be abandoned 15 MINUTES later");
    return newRoom;
}

最佳答案

这里根本没有真正的问题。

正如freeMemory()的Javadoc所述:


  返回Java虚拟机中的可用内存量。调用gc方法可能会增加freeMemory返回的值。


实际上,在Java程序中通常发生的情况是,当您分配新对象时,可用内存量减少了相同的数量。当可用内存量达到阈值(由JVM确定)时,GC将在后台运行,并回收大量垃圾。这将导致可用内存再次备份。

只有在垃圾回收后立即的可用内存量持续下降的情况下,您才有问题(例如内存泄漏)。



在您的特定情况下,freeMemory()呈下降趋势的原因是正在分配对象。 (Timer2似乎是新对象的一种可能来源,但也可能是Web容器代码。)

如果这些对象最终没有得到垃圾回收,这只是一个问题。

08-07 14:25