0

I encountered a problem when I deploy a war to a cloud server(PasS,128Mb), and then I have two timers in my application.

  1. Timer1 will be executing a task to log my memory(as well as a Map described in #2) every one hour.
  2. Every time I create a Room object, I put this room into a Map, so I have a Timer2 to create a task when I initiate a Roomto remove that object from a map.

I happen to know that that I should not use a timer.

But the problem is that I check the log logged by Timer1, my freeMemory is going down every hour and the total memory is the same.

I have read What are Runtime.getRuntime().totalMemory() and freeMemory()?, so I know what the total memory and freeMemory means. And according to the log, my used memory is going up!

PS: I do NOT use any new Runnable or Thread to handle any long-running logic.

Logs are like:

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

I am logging every time when this sevlet receive a request, so I am sure that no requests is handed,but why free memory going down.

1.This is how Timer1 works:

@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.This is how Timer2 works.

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;
}
Community
  • 1
  • 1
JaskeyLam
  • 15,405
  • 21
  • 114
  • 149

1 Answers1

0

There isn't necessarily a real problem here at all.

As the Javadoc for freeMemory() states:

Returns the amount of free memory in the Java Virtual Machine. Calling the gc method may result in increasing the value returned by freeMemory.

In fact, what typically happens in a Java program is that as you allocate new objects, the amount of free memory decreases by the same amount. When the amount of free memory hits a threshold (determined by the JVM), the GC runs behinds the scenes, and reclaims a bunch of garbage. That causes the free memory to go back up again.

You only have a problem (e.g. a memory leak) if the amount of free memory immediately after garbage collection is continually trending downwards.


In your specific case, the reason that freeMemory() is trending downwards is that objects are being allocated. (Timer2 seems to be one possible source of new objects, but it could also be something the web container code.)

This is only a problem if those objects don't get garbage collected ... eventually.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thank you very much. As you state,calling the gc method may result in increasing the value returned by freeMemory. So you think that I am allocating objects even though I do not handle any request?But I do not handle any requests and i do not have defined any background thread except for the timmer. Also, for timmer 2, only one task for one room, and as you can see, there are no rooms at all. And the task should be collected after it executed. The total memory is the same, so, the usedmemory=total-free is going up and up! Do you think it is really not a problem? – JaskeyLam Jul 22 '14 at 04:18
  • *"So you think that I am allocating objects even though I do not handle any request?"* Yes. *"Do you think it is really not a problem?"* **I didn't say that!!** I said it is *not necessarily* a problem. Or, to put it another way, this is not real evidence of a problem. Or yet another way, you *might* have a memory leak ... anyway. – Stephen C Jul 22 '14 at 11:57
  • "I am allocating objects even though I do not handle any request?", what do you think will be the cause? I have no background thread in my application except these two timmer, the timer is not creating object in the "run()" method, one of who is logging, the other is removing an object from the map. That is very confusing me. Every 1 hour, 2-3 MB is allocated. – JaskeyLam Jul 22 '14 at 13:17
  • Like I said before. It could be something in the web container code. If you really want to go, use a memory profiler to find out. – Stephen C Jul 22 '14 at 13:44