001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2006, University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA
018: */
019:
020: package edu.umd.cs.findbugs;
021:
022: import java.lang.management.GarbageCollectorMXBean;
023: import java.lang.management.ManagementFactory;
024: import java.lang.management.MemoryPoolMXBean;
025: import java.util.List;
026:
027: /**
028: * Class to maintain a snapshot of a processes's time and memory usage.
029: *
030: * This uses some JDK 1.5 APIs so must be careful that it doesn't cause
031: * any harm when run from 1.4.
032: *
033: * @see FindBugs
034: * @author Brian Cole
035: */
036: public class Footprint {
037:
038: private long cpuTime = -1; // in nanoseconds
039: private long clockTime = -1; // in milliseconds
040: private long peakMem = -1; // in bytes
041: private long collectionTime = -1; // in milliseconds
042:
043: public Footprint() {
044: pullData();
045: }
046:
047: /** uses deltas from base for cpuTime and clockTime (but not peakMemory) */
048: public Footprint(Footprint base) {
049: pullData();
050: if (cpuTime >= 0) {
051: cpuTime = (base.cpuTime >= 0) ? cpuTime - base.cpuTime
052: : base.cpuTime;
053: }
054: if (clockTime >= 0) {
055: clockTime = (base.clockTime >= 0) ? clockTime
056: - base.clockTime : base.clockTime;
057: }
058: // leave peakMem alone
059: if (collectionTime >= 0) {
060: collectionTime = (base.collectionTime >= 0) ? collectionTime
061: - base.collectionTime
062: : base.collectionTime;
063: }
064: }
065:
066: private void pullData() {
067:
068: try {
069: cpuTime = new OperatingSystemBeanWrapper()
070: .getProcessCpuTime();
071: } catch (NoClassDefFoundError ncdfe) {
072: cpuTime = -9;
073: } catch (ClassCastException cce) {
074: cpuTime = -8;
075: } catch (Error error) {
076: cpuTime = -7;
077: } // catch possible Error thrown when complied by the Eclipse compiler
078:
079: clockTime = System.currentTimeMillis(); // or new java.util.Date().getTime() ;
080:
081: try {
082: peakMem = new MemoryBeanWrapper().getPeakUsage();
083: } catch (NoClassDefFoundError ncdfe) {
084: peakMem = -9;
085: }
086:
087: try {
088: collectionTime = new CollectionBeanWrapper()
089: .getCollectionTime();
090: } catch (NoClassDefFoundError ncdfe) {
091: collectionTime = -9;
092: }
093: }
094:
095: public long getCpuTime() {
096: return cpuTime;
097: }
098:
099: public long getClockTime() {
100: return clockTime;
101: }
102:
103: public long getPeakMemory() {
104: return peakMem;
105: }
106:
107: public long getCollectionTime() {
108: return collectionTime;
109: }
110:
111: @Override
112: public String toString() {
113: return "cpuTime=" + cpuTime + ", clockTime=" + clockTime
114: + ", peakMemory=" + peakMem;
115: }
116:
117: public static void main(String[] argv) {
118: System.out.println(new Footprint());
119: }
120:
121: // -------- begin static inner classes --------
122:
123: /** Wrapper so that possbile NoClassDefFoundError can be caught. Instantiating
124: * this class will throw a NoClassDefFoundError on JDK 1.4 and earlier. */
125: public static class MemoryBeanWrapper {
126: List<MemoryPoolMXBean> mlist = ManagementFactory
127: .getMemoryPoolMXBeans();
128:
129: //java.lang.management.MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
130: //java.lang.management.MemoryUsage memUsage = memBean.getHeapMemoryUsage();
131:
132: public long getPeakUsage() {
133: long sum = 0;
134: // problem: sum of the peaks is not necessarily the peak of the sum.
135: // For example, objects migrate from the 'eden' to the 'survivor' area.
136: for (MemoryPoolMXBean mpBean : mlist) {
137: java.lang.management.MemoryUsage memUsage = mpBean
138: .getPeakUsage();
139: if (memUsage != null)
140: sum += memUsage.getUsed(); // or getCommitted()
141: // System.out.println(mpBean.getType()+", "+mpBean.getName()+", "+memUsage.getUsed());
142: //System.out.println("Memory type="+mpBean.getType()+", Pool name="+mpBean.getName()+", Memory usage="+mpBean.getPeakUsage());
143: }
144: // System.out.println();
145: return sum;
146: }
147: }
148:
149: /** Wrapper so that possbile NoClassDefFoundError can be caught. Instantiating this
150: * class will throw a NoClassDefFoundError on JDK 1.4 and earlier, or will throw a
151: * ClassCastException on a 1.5-compliant non-sun JRE where the osBean is not a sunBean.
152: * (If compiled by Eclipse, instantiating it will throw an unsubclassed java.lang.Error.) */
153: public static class OperatingSystemBeanWrapper {
154: java.lang.management.OperatingSystemMXBean osBean = ManagementFactory
155: .getOperatingSystemMXBean();
156: // next line compiles fine with sun JDK 1.5 but the eclipse compiler may complain "The type
157: // OperatingSystemMXBean is not accessible due to restriction on required library classes.jar"
158: // depending on the contents of the .classpath file.
159: com.sun.management.OperatingSystemMXBean sunBean = (com.sun.management.OperatingSystemMXBean) osBean;
160:
161: public long getProcessCpuTime() {
162: return sunBean.getProcessCpuTime();
163: }
164: }
165:
166: /** Wrapper so that possbile NoClassDefFoundError can be caught. Instantiating
167: * this class will throw a NoClassDefFoundError on JDK 1.4 and earlier. */
168: public static class CollectionBeanWrapper {
169: List<GarbageCollectorMXBean> clist = ManagementFactory
170: .getGarbageCollectorMXBeans();
171:
172: public long getCollectionTime() {
173: long sum = 0;
174: for (GarbageCollectorMXBean gcBean : clist) {
175: sum += gcBean.getCollectionTime();
176: }
177: return sum;
178: }
179: }
180:
181: }
|