1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2008 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License.
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License.
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.Serializable;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.IOException;
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.BufferedReader;
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.InputStreamReader;
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.InputStream;
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.OutputStream;
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.List;
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.ArrayList;
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Arrays;
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Memory usage information.
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass MemoryUsage implements Serializable {
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final long serialVersionUID = 0;
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static final MemoryUsage NOT_AVAILABLE = new MemoryUsage();
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static int errorCount = 0;
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // These values are in 1kB increments (not 4kB like you'd expect).
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int nativeSharedPages;
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int javaSharedPages;
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int otherSharedPages;
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int nativePrivatePages;
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int javaPrivatePages;
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int otherPrivatePages;
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int allocCount;
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int allocSize;
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int freedCount;
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int freedSize;
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final long nativeHeapSize;
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public MemoryUsage(String line) {
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String[] parsed = line.split(",");
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        nativeSharedPages = Integer.parseInt(parsed[1]);
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        javaSharedPages = Integer.parseInt(parsed[2]);
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        otherSharedPages = Integer.parseInt(parsed[3]);
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        nativePrivatePages = Integer.parseInt(parsed[4]);
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        javaPrivatePages = Integer.parseInt(parsed[5]);
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        otherPrivatePages = Integer.parseInt(parsed[6]);
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        allocCount = Integer.parseInt(parsed[7]);
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        allocSize = Integer.parseInt(parsed[8]);
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        freedCount = Integer.parseInt(parsed[9]);
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        freedSize = Integer.parseInt(parsed[10]);
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        nativeHeapSize = Long.parseLong(parsed[11]);
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MemoryUsage() {
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        nativeSharedPages = -1;
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        javaSharedPages = -1;
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        otherSharedPages = -1;
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        nativePrivatePages = -1;
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        javaPrivatePages = -1;
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        otherPrivatePages = -1;
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        allocCount = -1;
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        allocSize = -1;
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        freedCount = -1;
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        freedSize = -1;
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        nativeHeapSize = -1;
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MemoryUsage(int nativeSharedPages,
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int javaSharedPages,
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int otherSharedPages,
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int nativePrivatePages,
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int javaPrivatePages,
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int otherPrivatePages,
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int allocCount,
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int allocSize,
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int freedCount,
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int freedSize,
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            long nativeHeapSize) {
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.nativeSharedPages = nativeSharedPages;
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.javaSharedPages = javaSharedPages;
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.otherSharedPages = otherSharedPages;
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.nativePrivatePages = nativePrivatePages;
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.javaPrivatePages = javaPrivatePages;
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.otherPrivatePages = otherPrivatePages;
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.allocCount = allocCount;
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.allocSize = allocSize;
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.freedCount = freedCount;
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.freedSize = freedSize;
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.nativeHeapSize = nativeHeapSize;
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MemoryUsage subtract(MemoryUsage baseline) {
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new MemoryUsage(
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                nativeSharedPages - baseline.nativeSharedPages,
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                javaSharedPages - baseline.javaSharedPages,
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                otherSharedPages - baseline.otherSharedPages,
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                nativePrivatePages - baseline.nativePrivatePages,
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                javaPrivatePages - baseline.javaPrivatePages,
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                otherPrivatePages - baseline.otherPrivatePages,
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                allocCount - baseline.allocCount,
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                allocSize - baseline.allocSize,
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                freedCount - baseline.freedCount,
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                freedSize - baseline.freedSize,
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                nativeHeapSize - baseline.nativeHeapSize);
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int javaHeapSize() {
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return allocSize - freedSize;
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int totalHeap() {
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return javaHeapSize() + (int) nativeHeapSize;
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int javaPagesInK() {
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return javaSharedPages + javaPrivatePages;
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int nativePagesInK() {
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return nativeSharedPages + nativePrivatePages;
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int otherPagesInK() {
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return otherSharedPages + otherPrivatePages;
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int totalPages() {
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return javaSharedPages + javaPrivatePages + nativeSharedPages +
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                nativePrivatePages + otherSharedPages + otherPrivatePages;
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Was this information available?
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    boolean isAvailable() {
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return nativeSharedPages != -1;
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Measures baseline memory usage.
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static MemoryUsage baseline() {
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return forClass(null);
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final String CLASS_PATH = "-Xbootclasspath"
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            + ":/system/framework/core.jar"
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            + ":/system/framework/ext.jar"
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            + ":/system/framework/framework.jar"
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            + ":/system/framework/framework-tests.jar"
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            + ":/system/framework/services.jar"
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            + ":/system/framework/loadclass.jar";
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final String[] GET_DIRTY_PAGES = {
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "adb", "shell", "dalvikvm", CLASS_PATH, "LoadClass" };
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Measures memory usage for the given class.
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static MemoryUsage forClass(String className) {
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        MeasureWithTimeout measurer = new MeasureWithTimeout(className);
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        new Thread(measurer).start();
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        synchronized (measurer) {
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (measurer.memoryUsage == null) {
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Wait up to 10s.
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                try {
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    measurer.wait(30000);
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } catch (InterruptedException e) {
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    System.err.println("Interrupted waiting for measurement.");
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e.printStackTrace();
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NOT_AVAILABLE;
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // If it's still null.
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (measurer.memoryUsage == null) {
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    System.err.println("Timed out while measuring "
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            + className + ".");
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NOT_AVAILABLE;
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            System.err.println("Got memory usage for " + className + ".");
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return measurer.memoryUsage;
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static class MeasureWithTimeout implements Runnable {
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final String className;
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        MemoryUsage memoryUsage = null;
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        MeasureWithTimeout(String className) {
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            this.className = className;
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void run() {
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            MemoryUsage measured = measure();
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            synchronized (this) {
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memoryUsage = measured;
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                notifyAll();
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        private MemoryUsage measure() {
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String[] commands = GET_DIRTY_PAGES;
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (className != null) {
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                List<String> commandList = new ArrayList<String>(
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        GET_DIRTY_PAGES.length + 1);
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                commandList.addAll(Arrays.asList(commands));
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                commandList.add(className);
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                commands = commandList.toArray(new String[commandList.size()]);
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            try {
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                final Process process = Runtime.getRuntime().exec(commands);
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                final InputStream err = process.getErrorStream();
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Send error output to stderr.
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Thread errThread = new Thread() {
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void run() {
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        copy(err, System.err);
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                };
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                errThread.setDaemon(true);
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                errThread.start();
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                BufferedReader in = new BufferedReader(
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        new InputStreamReader(process.getInputStream()));
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String line = in.readLine();
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (line == null || !line.startsWith("DECAFBAD,")) {
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    System.err.println("Got bad response for " + className
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            + ": " + line + "; command was " + Arrays.toString(commands));
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    errorCount += 1;
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NOT_AVAILABLE;
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                in.close();
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err.close();
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                process.destroy();
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MemoryUsage(line);
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } catch (IOException e) {
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                System.err.println("Error getting stats for "
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        + className + ".");
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                e.printStackTrace();
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NOT_AVAILABLE;
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Copies from one stream to another.
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static void copy(InputStream in, OutputStream out) {
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        byte[] buffer = new byte[1024];
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int read;
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((read = in.read(buffer)) > -1) {
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                out.write(buffer, 0, read);
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } catch (IOException e) {
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            e.printStackTrace();
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Measures memory usage information and stores it in the model. */
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static void main(String[] args) throws IOException,
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ClassNotFoundException {
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Root root = Root.fromFile(args[0]);
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root.baseline = baseline();
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (LoadedClass loadedClass : root.loadedClasses.values()) {
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (loadedClass.systemClass) {
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                loadedClass.measureMemoryUsage();
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root.toFile(args[0]);
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
299