001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: /*
043: * MemoryMeasurement.java
044: *
045: * Created on August 7, 2003, 4:53 PM
046: */
047:
048: package org.netbeans.junit;
049:
050: import java.io.*;
051:
052: /** Class with static methods for measuring memory footprint of a process. Since
053: * this class required platform dependent code, there have to be a dll library
054: * called 'lib.memory-measurement.win32.dll' present in a home directory of
055: * NbJUnit (set by nbjunit.home property in either junit.properties file or
056: * present as a system property).
057: *
058: * Please note, methods available in this class return a system specific values for
059: * each supported platforms. The meanings of values are:
060: *
061: * On Solaris: resident memory size
062: * On Linux: VmSize (virtual memory size)
063: * On Windows: pagefile usage
064: * @author mb115822
065: */
066: public class MemoryMeasurement {
067:
068: /** only static methods **/
069: private MemoryMeasurement() {
070: }
071:
072: /** Name of the system property, which contains PID of running IDE. This property
073: * is set by ide executor of XTest framework.
074: */
075: public static final String IDE_PID_SYSTEM_PROPERTY = "netbeans.pid";
076:
077: /** Gets memory footprint of NetBeans IDE. This methods requires system property
078: * 'netbeans.pid' to contain PID of the IDE process.
079: * @throws MemoryMeasurementFailedException When measurement cannot be performed
080: * @return memory size value
081: */
082: public static long getIdeMemoryFootPrint()
083: throws MemoryMeasurementFailedException {
084: // pid should be stored as netbeans.pid system variabl
085: String idePidString = System
086: .getProperty(IDE_PID_SYSTEM_PROPERTY);
087: if (idePidString != null) {
088: try {
089: //System.out.println("Got idePidString = "+idePidString);
090: long idePid = Long.parseLong(idePidString);
091: //System.out.println("Got idePId = "+idePid);
092: return getProcessMemoryFootPrint(idePid);
093: } catch (NumberFormatException nfe) {
094: // this should not happen -
095: }
096: }
097: // unsuccessfull - throw MemoryMeasurementFailedException
098: throw new MemoryMeasurementFailedException(
099: "Cannot get IDE PID - obtained value: " + idePidString);
100: }
101:
102: /** Gets memory footprint of a process identified by PID. On each platform this
103: * methods returns a platform specific value.
104: * @param pid process identification for the process, which size is to be measured
105: * @throws MemoryMeasurementFailedException When measurement cannot be performed
106: * @return memory size value
107: */
108: public static long getProcessMemoryFootPrint(long pid)
109: throws MemoryMeasurementFailedException {
110: String platform = getPlatform();
111: //System.out.println("PLATFORM = "+getPlatform());
112: if (platform.equals(SOLARIS) | platform.equals(LINUX)) {
113: // call unix method
114: return getProcessMemoryFootPrintOnUnix(pid);
115: } else if (platform.equals(WINDOWS)) {
116: // call windows method
117: return getProcessMemoryFootPrintOnWindows(pid);
118: }
119: // unsupported platform - cannot measure memory
120: throw new MemoryMeasurementFailedException(
121: "Cannot measure memory on unsupported platform "
122: + platform);
123: }
124:
125: /** */
126: private static final long UNKNOWN_VALUE = -1;
127:
128: private static final String SOLARIS = "solaris";
129: private static final String LINUX = "linux";
130: private static final String WINDOWS = "win32";
131: private static final String UNKNOWN = "unknown";
132:
133: private static final String[][] SUPPORTED_PLATFORMS = {
134: { "SunOS", SOLARIS }, { "Linux", LINUX },
135: { "Windows NT", WINDOWS }, { "Windows 2000", WINDOWS },
136: { "Windows XP", WINDOWS } };
137:
138: private static String getPlatform()
139: throws MemoryMeasurementFailedException {
140: String osName = System.getProperty("os.name");
141: for (int i = 0; i < SUPPORTED_PLATFORMS.length; i++) {
142: if (SUPPORTED_PLATFORMS[i][0].equalsIgnoreCase(osName)) {
143: return SUPPORTED_PLATFORMS[i][1];
144: }
145: }
146: throw new MemoryMeasurementFailedException(
147: "MemoryMeasurement does not support this operating system: "
148: + osName);
149: }
150:
151: private static long getProcessMemoryFootPrintOnUnix(long pid)
152: throws MemoryMeasurementFailedException {
153: try {
154: File script = new File(Manager.getNbJUnitHome(),
155: "memory-measurement.unix.sh");
156: if (!script.exists()) {
157: throw new MemoryMeasurementFailedException(
158: "Cannot locate script '"
159: + script.getName()
160: + "', please make sure it is available in nbjunit.home");
161: }
162: String command = "/bin/sh " + script.getAbsolutePath()
163: + " " + pid;
164: //System.out.println("Running command "+command);
165: Process process = Runtime.getRuntime().exec(command);
166: long obtainedValue = getOutputValue(process);
167:
168: //OutputReader outputReader = new MemoryMeasurement.OutputReader(process.getInputStream());
169: //System.out.println("Starting thread reader");
170: //Thread readerThread = new Thread(outputReader);
171: //readerThread.start();
172: //process.getOutputStream().close();
173:
174: process.waitFor();
175:
176: //long obtainedValue = outputReader.getReadValue();
177:
178: if (obtainedValue == UNKNOWN_VALUE) {
179: // had problem reading value - why
180: //throw new MemoryMeasurementFailedException("Memory measurement call failed",outputReader.getCaughtException());
181: throw new MemoryMeasurementFailedException(
182: "Memory measurement call failed "
183: + obtainedValue);
184: } else {
185: // everything seem to be correct
186: return obtainedValue;
187: }
188: } catch (IOException ioe) {
189: throw new MemoryMeasurementFailedException(
190: "MemoryMeasurement failed, reason:"
191: + ioe.getMessage(), ioe);
192: } catch (InterruptedException ie) {
193: throw new MemoryMeasurementFailedException(
194: "MemoryMeasurement failed, reason:"
195: + ie.getMessage(), ie);
196: }
197: }
198:
199: // os depednent implementations - not used -> on unix we use the universal script supplied with XTest
200: // linux
201: //private static long getProcessMemoryFootPrintOnLinux(long pid) throws MemoryMeasurementFailedException {
202: //String command="/bin/sh -c \"cat /proc/"+pid+"status | grep VmSize | sed -e 's/VmSize: *\\t* *//' | sed -e 's/ .*//'\"";
203: /*
204: try {
205: Process process = Runtime.getRuntime().exec(command);
206: //return getOutputValue(process);
207: return UNKNOWN_VALUE;
208: } catch (IOException ioe) {
209: throw new MemoryMeasurementFailedException("MemoryMeasurement failed, reason:"+ioe.getMessage(),ioe);
210: }
211: }
212: */
213: // solaris
214: //private static long getProcessMemoryFootPrintOnSolaris(long pid) throws MemoryMeasurementFailedException {
215: //String command="/bin/sh -c \"pmap -x "+pid+" | grep \\^total | sed -e 's/.*Kb *//' | sed -e 's/ .*//'\"";
216: //String command="\"pmap -x "+pid+" | grep \\^total | sed -e 's/.*Kb *//' | sed -e 's/ .*//'\"";
217: //String command="/bin/short -c \"ls -al\"";
218: /*
219: try {
220: System.out.println("Running command "+command);
221: Process process = Runtime.getRuntime().exec(command);
222: //long obtainedValue = getOutputValue(process);
223: OutputReader outputReader = new MemoryMeasurement.OutputReader(process.getInputStream());
224: System.out.println("Starting thread reader");
225: Thread readerThread = new Thread(outputReader);
226: readerThread.start();
227: //process.getOutputStream().close();
228: //process.waitFor();
229: long obtainedValue = outputReader.getReadValue();
230: if (obtainedValue == UNKNOWN_VALUE) {
231: // had problem reading value - why
232: //throw new MemoryMeasurementFailedException("Memory measurement call failed",outputReader.getCaughtException());
233: throw new MemoryMeasurementFailedException("Memory measurement call failed 1welnewgb");
234: } else {
235: // everything seem to be correct
236: return obtainedValue;
237: }
238: } catch (IOException ioe) {
239: throw new MemoryMeasurementFailedException("MemoryMeasurement failed, reason:"+ioe.getMessage(),ioe);
240: } catch (InterruptedException ie) {
241: throw new MemoryMeasurementFailedException("MemoryMeasurement failed, reason:"+ie.getMessage(),ie);
242: }
243: }
244: */
245:
246: // woknous
247: private static long getProcessMemoryFootPrintOnWindows(long pid)
248: throws MemoryMeasurementFailedException {
249: loadMemoryMeasurementLibrary();
250: long value = getProcessMemoryFootPrintNative(pid);
251: if (value == UNKNOWN_VALUE) {
252: // there was some problem when measuring the foot print
253: throw new MemoryMeasurementFailedException(
254: "Memory measurement call to native library failed - could not measure memory of process with pid "
255: + pid + ".");
256: } else {
257: // everything seems to be ok
258: return value;
259: }
260: }
261:
262: private static native long getProcessMemoryFootPrintNative(long pid);
263:
264: private static long getOutputValue(Process process)
265: throws IOException {
266: BufferedReader br = null;
267: try {
268: br = new BufferedReader(new InputStreamReader(process
269: .getInputStream()));
270: String outputString = br.readLine();
271: //System.out.println("Outputstring is"+outputString);
272: try {
273: return Long.parseLong(outputString);
274: } catch (NumberFormatException nfe) {
275: throw new IOException(
276: "Received String is not a number: "
277: + outputString);
278: }
279: } finally {
280: if (br != null) {
281: br.close();
282: }
283: }
284: }
285:
286: // load the library (if applicable)
287: private static boolean libraryLoaded = false;
288:
289: private static void loadMemoryMeasurementLibrary()
290: throws MemoryMeasurementFailedException {
291: if (!libraryLoaded) {
292: try {
293: File dllLibrary = new File(Manager.getNbJUnitHome(),
294: "lib.memory-measurement.win32.dll");
295: //System.out.println("Libray path:"+dllLibrary);
296: System.load(dllLibrary.getAbsolutePath());
297: libraryLoaded = true;
298: //System.out.println("Libraru loaded");
299: } catch (IOException ioe) {
300: throw new MemoryMeasurementFailedException(
301: "Cannot load native memory measurement library lib.memory-measurement.win32.dll, reason: "
302: + ioe.getMessage(), ioe);
303: } catch (UnsatisfiedLinkError ule) {
304: // cannot load the library ....
305: throw new MemoryMeasurementFailedException(
306: "Cannot load native memory measurement library lib.memory-measurement.win32.dll, reason: "
307: + ule.getMessage(), ule);
308: }
309: }
310:
311: }
312:
313: // out value reader class - not used - the value is read directly, without necessity to start another thread !!!!
314: /*
315: static class OutputReader implements Runnable {
316: InputStream is;
317:
318: long readValue = UNKNOWN_VALUE;
319: IOException caughtException;
320:
321: public OutputReader(InputStream is) {
322: this.is = is;
323: System.out.println("Reader ready - is = "+is);
324: }
325:
326: public long getReadValue() {
327: return readValue;
328: }
329:
330: public IOException getCaughtException() {
331: return caughtException;
332: }
333:
334: public void run() {
335: System.out.println("Reader Running ...");
336: BufferedReader br = null;
337: try {
338: br = new BufferedReader(new InputStreamReader(is));
339: String temp = null;
340: while ((temp = br.readLine()) != null) {
341: System.out.println("Read: "+temp);
342: if (temp.length() > 0) {
343: try {
344: readValue = Long.parseLong(temp);
345: System.out.println("Read value:"+readValue);
346: } catch (NumberFormatException nfe) {
347: throw new IOException("Process returned value '"+temp+"', which cannot be converted to a number. Reason: "+nfe.getMessage());
348: }
349: }
350: }
351: } catch (IOException ioe) {
352: caughtException = ioe;
353: } finally {
354: if (br != null) {
355: try {
356: br.close();
357: } catch (IOException ioe) {
358: // who gives a ....
359: }
360: }
361: }
362: }
363: }*/
364:
365: }
|