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}