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