001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 The ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.lib.commons.system; 018 019import java.util.Timer; 020import java.util.TimerTask; 021 022/** 023 * A simple class for monitoring memory usage of an application. A second thread 024 * is started which periodically polls the memory status. <br/> 025 * <br/> 026 * <b>Note: </b> Due to performance reasons the method 027 * <code>getMaximumMemoryUsage()</code> and <code>reset()</code> are <b>not </b> 028 * synchronized, so calling these methods while the memory monitor is still 029 * running might lead to undesired results. Therefore it is recommended stop the 030 * memory befor calling <code>getMaximumMemoryUsage()</code> or 031 * <code>reset()</code>. 032 * 033 * @author Florian Deissenboeck 034 */ 035public class MemoryMonitor { 036 /** Default polling period [ms]. */ 037 private static final int DEFAULT_PERIOD = 50; 038 039 /** The timer for controlling the periodical call. */ 040 private Timer timer; 041 042 /** Period between polls [ms]. */ 043 private final int period; 044 045 /** The task gathering the memory information. */ 046 private final MemoryMonitorTask monitorTask; 047 048 /** 049 * Construct a new <code>MemoryMonitor</code> with the default monitoring 050 * interval. 051 * 052 */ 053 public MemoryMonitor() { 054 this(DEFAULT_PERIOD); 055 } 056 057 /** 058 * Construct a new <code>MemoryMonitor</code>. 059 * 060 * @param period 061 * time between subsequent polls to obtain memory status 062 * @see #start() 063 */ 064 public MemoryMonitor(int period) { 065 monitorTask = new MemoryMonitorTask(); 066 this.period = period; 067 068 // start as daemon thread 069 timer = new Timer(true); 070 } 071 072 /** 073 * Start the memory monitor. 074 * 075 * @see #stop() 076 */ 077 public void start() { 078 timer.schedule(monitorTask, 0, period); 079 } 080 081 /** 082 * Stop the memory monitor. Memory monitor can be restarted safely after 083 * stopping without loosing the current maximum value. 084 * 085 * @see #start() 086 * @see #reset() 087 */ 088 public void stop() { 089 timer.cancel(); 090 timer = new Timer(true); 091 } 092 093 /** 094 * Reset the maximum memory usage value. Use this method only when monitor 095 * is stopped. 096 * 097 * @see #stop() 098 */ 099 public void reset() { 100 monitorTask.reset(); 101 } 102 103 /** 104 * Obtain maximum amount of memory used since the monitor was started or 105 * reset.Use this method only when monitor is stopped. 106 * 107 * @see #stop() 108 * 109 * @return maximum memory usage [byte] 110 */ 111 public long getMaximumMemoryUsage() { 112 return monitorTask.getMaximumMemoryUsage(); 113 } 114 115 /** 116 * A simple timer task for monitor memory status. <br/> 117 * <br/> 118 * <b>Note: </b> Due to performance reasons the method 119 * <code>getMaximumMemoryUsage()</code> and <code>reset()</code> are <b>not 120 * </b> synchronized, so calling these methods while the memory monitor is 121 * still running might lead to undesired results. 122 */ 123 private static class MemoryMonitorTask extends TimerTask { 124 125 /** Runtime object for accessing the VM's memory status. */ 126 private final Runtime runtime; 127 128 /** Maximum amount of memory used . */ 129 private long maxMemory = 0; 130 131 /** 132 * Set up a new monitor task. 133 * 134 */ 135 public MemoryMonitorTask() { 136 runtime = Runtime.getRuntime(); 137 } 138 139 /** 140 * Retrieve currently used memory from runtime object and update maximum 141 * memory usage if necessary. 142 */ 143 @Override 144 public void run() { 145 long usedMemory = runtime.totalMemory(); 146 if (usedMemory > maxMemory) { 147 maxMemory = usedMemory; 148 } 149 } 150 151 /** 152 * Obtain maximum amount of memory used since the monitor was started or 153 * reset.Use this method only when monitor is stopped. 154 * 155 * @return maximum memory usage [byte] 156 */ 157 public long getMaximumMemoryUsage() { 158 return maxMemory; 159 } 160 161 /** 162 * Reset the maximum memory usage value. Use this method only when 163 * monitor is stopped. 164 * 165 */ 166 public void reset() { 167 maxMemory = 0; 168 } 169 170 } 171}