package com.plectix.simulator.util; import java.io.PrintStream; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.util.Timer; import java.util.TimerTask; public final class MemoryUtil { private static PeakMemoryUsage peakMemoryUsage = null; /** * Turns on monitoring of peak memory usage. This method is not thread-safe and it is * designed to be called when the application is just launched. The information * must be retrieved with {@link #getPeakMemoryUsage()} method. * * @param period time in milliseconds between successive memory monitoring operations * @return <true> if monitoring is turned on with this call, <false> if it was already turned on * @see #getPeakMemoryUsage() */ public static final boolean monitorPeakMemoryUsage(long period) { if (peakMemoryUsage != null) { // monitoring already turned on! return false; } peakMemoryUsage = new PeakMemoryUsage(period); return true; } /** * Turns off monitoring of peak memory usage and returns the usage information. * Monitoring must be turned on before calling this method * using {@link #monitorPeakMemoryUsage(long)}. * * This method is not thread-safe and it is designed to be called just before * the application quits (as opposed to monitoring the usage continuously). * * @return the peak memory usage since {@link #monitorPeakMemoryUsage(long)} is called, * or <code>null</code> if the monitoring is not already turned on * @see #monitorPeakMemoryUsage(long) */ public static final PeakMemoryUsage getPeakMemoryUsage() { if (peakMemoryUsage == null) { // monitoring is off! return null; } final PeakMemoryUsage ret = peakMemoryUsage; peakMemoryUsage.stopTimer(); peakMemoryUsage = null; return ret; } public static final void dumpUsedMemoryInfoPeriodically(final PrintStream printStream, long period) { TimerTask timerTask = new TimerTask() { @Override public void run() { dumpUsedMemory(printStream); } }; Timer timer = new Timer(); timer.scheduleAtFixedRate(timerTask, 0, period); } private static void dumpUsedMemory(PrintStream printStream) { printStream.println(getUsedMemory()); } private static String getUsedMemory() { MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); return "Memory: " + mbean.getNonHeapMemoryUsage().getUsed() + " " + mbean.getHeapMemoryUsage().getUsed(); } public static final class PeakMemoryUsage { private long heap = 0; private long nonHeap = 0; private long total = 0; private MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); private Timer peakMemoryTimer = new Timer(); PeakMemoryUsage(long period) { super(); peakMemoryTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (peakMemoryUsage != null) { peakMemoryUsage.update(); } } }, 0, period); } final boolean stopTimer() { if (peakMemoryTimer == null) { return false; } peakMemoryTimer.cancel(); peakMemoryTimer = null; update(); return true; } public final void update() { long currentHeap = mbean.getHeapMemoryUsage().getUsed(); long currentNonHeap = mbean.getNonHeapMemoryUsage().getUsed(); synchronized (this) { heap = Math.max(heap, currentHeap); nonHeap = Math.max(nonHeap, currentNonHeap); total = Math.max(total, currentHeap + currentNonHeap); } } @Override public final String toString() { return "Heap= " + heap + " NonHeap= " + nonHeap + " Total= " + total; } public final long getHeap() { return heap; } public final long getNonHeap() { return nonHeap; } public final long getTotal() { return total; } } }