diff options
author | Brian Carlstrom <bdc@google.com> | 2011-03-29 22:55:01 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2011-03-29 22:55:01 -0700 |
commit | 645d772dfc09d9f0a384e3e9bb7894df5887de65 (patch) | |
tree | b753c6a09de8eec53dd26836ab1a3ed6613a0971 /dalvik | |
parent | b39fa9149966992e55b8dd6bc75c27d7a6768ddc (diff) | |
parent | e9af8901fc4ed7c05d085e2e492f5dcc857f0146 (diff) | |
download | libcore-645d772dfc09d9f0a384e3e9bb7894df5887de65.zip libcore-645d772dfc09d9f0a384e3e9bb7894df5887de65.tar.gz libcore-645d772dfc09d9f0a384e3e9bb7894df5887de65.tar.bz2 |
am e9af8901: SamplingProfilerIntegration and SamplingProfiler improvements (2/3)
* commit 'e9af8901fc4ed7c05d085e2e492f5dcc857f0146':
SamplingProfilerIntegration and SamplingProfiler improvements (2/3)
Diffstat (limited to 'dalvik')
12 files changed, 392 insertions, 86 deletions
diff --git a/dalvik/src/main/java/dalvik/system/VMStack.java b/dalvik/src/main/java/dalvik/system/VMStack.java index 6f38f7e..a8430d8 100644 --- a/dalvik/src/main/java/dalvik/system/VMStack.java +++ b/dalvik/src/main/java/dalvik/system/VMStack.java @@ -75,4 +75,18 @@ public final class VMStack { * doesn't have a stack trace (e.g. because it exited) */ native public static StackTraceElement[] getThreadStackTrace(Thread t); + + /** + * Retrieves a partial stack trace from the specified thread into + * the provided array. + * + * @param t + * thread of interest + * @param stackTraceElements + * preallocated array for use when only the top of stack is + * desired. Unused elements will be filled with null values. + * @return the number of elements filled + */ + native public static int fillStackTraceElements(Thread t, + StackTraceElement[] stackTraceElements); } diff --git a/dalvik/src/main/java/dalvik/system/profiler/AsciiHprofWriter.java b/dalvik/src/main/java/dalvik/system/profiler/AsciiHprofWriter.java index 130d032..dbddcc6 100644 --- a/dalvik/src/main/java/dalvik/system/profiler/AsciiHprofWriter.java +++ b/dalvik/src/main/java/dalvik/system/profiler/AsciiHprofWriter.java @@ -25,17 +25,28 @@ import java.util.Comparator; import java.util.Date; import java.util.List; -public final class AsciiHprofWriter implements HprofWriter { +/** + * AsciiHprofWriter produces hprof compatible text output for use with + * third party tools such as PerfAnal. + */ +public final class AsciiHprofWriter { private final HprofData data; private final PrintWriter out; - public AsciiHprofWriter(HprofData data, OutputStream outputStream) { + /** + * Writes the provided data to the specified stream. + */ + public static void write(HprofData data, OutputStream outputStream) throws IOException { + new AsciiHprofWriter(data, outputStream).write(); + } + + private AsciiHprofWriter(HprofData data, OutputStream outputStream) { this.data = data; this.out = new PrintWriter(outputStream); } - public void write() throws IOException { + private void write() throws IOException { for (HprofData.ThreadEvent e : data.getThreadHistory()) { out.println(e); } diff --git a/dalvik/src/main/java/dalvik/system/profiler/BinaryHprof.java b/dalvik/src/main/java/dalvik/system/profiler/BinaryHprof.java index 26eb290..9720446 100644 --- a/dalvik/src/main/java/dalvik/system/profiler/BinaryHprof.java +++ b/dalvik/src/main/java/dalvik/system/profiler/BinaryHprof.java @@ -16,6 +16,8 @@ package dalvik.system.profiler; +import java.io.DataInputStream; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -29,6 +31,34 @@ public final class BinaryHprof { */ public static final int ID_SIZE = 4; + /** + * Prefix of valid magic values from the start of a binary hprof file. + */ + static String MAGIC = "JAVA PROFILE "; + + /** + * Returns the file's magic value as a String if found, otherwise null. + */ + public static final String readMagic(DataInputStream in) { + try { + byte[] bytes = new byte[512]; + for (int i = 0; i < bytes.length; i++) { + byte b = in.readByte(); + if (b == '\0') { + String string = new String(bytes, 0, i, "UTF-8"); + if (string.startsWith(MAGIC)) { + return string; + } + return null; + } + bytes[i] = b; + } + return null; + } catch (IOException e) { + return null; + } + } + public static enum Tag { STRING_IN_UTF8(0x01, -ID_SIZE), diff --git a/dalvik/src/main/java/dalvik/system/profiler/BinaryHprofReader.java b/dalvik/src/main/java/dalvik/system/profiler/BinaryHprofReader.java index 65e5178..75a17f3 100644 --- a/dalvik/src/main/java/dalvik/system/profiler/BinaryHprofReader.java +++ b/dalvik/src/main/java/dalvik/system/profiler/BinaryHprofReader.java @@ -123,23 +123,14 @@ public final class BinaryHprofReader { } private void parseVersion() throws IOException { - byte[] bytes = new byte[512]; - for (int i = 0; i < bytes.length; i++) { - byte b = in.readByte(); - if (b == '\0') { - String version = new String(bytes, 0, i, "UTF-8"); - if (TRACE) { - System.out.println("\tversion=" + version); - } - if (!version.startsWith("JAVA PROFILE ")) { - throw new MalformedHprofException("Unexpected version: " + version); - } - this.version = version; - return; - } - bytes[i] = b; + String version = BinaryHprof.readMagic(in); + if (version == null) { + throw new MalformedHprofException("Could not find HPROF version"); + } + if (TRACE) { + System.out.println("\tversion=" + version); } - throw new MalformedHprofException("Could not find HPROF version"); + this.version = version; } private void parseIdSize() throws IOException { diff --git a/dalvik/src/main/java/dalvik/system/profiler/BinaryHprofWriter.java b/dalvik/src/main/java/dalvik/system/profiler/BinaryHprofWriter.java index 808572d..5c29838 100644 --- a/dalvik/src/main/java/dalvik/system/profiler/BinaryHprofWriter.java +++ b/dalvik/src/main/java/dalvik/system/profiler/BinaryHprofWriter.java @@ -23,7 +23,12 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -public final class BinaryHprofWriter implements HprofWriter { +/** + * BinaryHprofWriter produces hprof compatible binary output for use + * with third party tools. Such files can be converted to text with + * with {@link HprofBinaryToAscii} or read back in with {@link BinaryHprofReader}. + */ +public final class BinaryHprofWriter { private int nextStringId = 1; // id 0 => null private int nextClassId = 1; @@ -36,12 +41,19 @@ public final class BinaryHprofWriter implements HprofWriter { private final HprofData data; private final DataOutputStream out; - public BinaryHprofWriter(HprofData data, OutputStream outputStream) { + /** + * Writes the provided data to the specified stream. + */ + public static void write(HprofData data, OutputStream outputStream) throws IOException { + new BinaryHprofWriter(data, outputStream).write(); + } + + private BinaryHprofWriter(HprofData data, OutputStream outputStream) { this.data = data; this.out = new DataOutputStream(outputStream); } - public void write() throws IOException { + private void write() throws IOException { try { writeHeader(data.getStartMillis()); @@ -65,7 +77,7 @@ public final class BinaryHprofWriter implements HprofWriter { } private void writeHeader(long dumpTimeInMilliseconds) throws IOException { - out.writeBytes("JAVA PROFILE 1.0.2"); + out.writeBytes(BinaryHprof.MAGIC + "1.0.2"); out.writeByte(0); // null terminated string out.writeInt(BinaryHprof.ID_SIZE); out.writeLong(dumpTimeInMilliseconds); @@ -238,8 +250,4 @@ public final class BinaryHprofWriter implements HprofWriter { return id; } - - public void close() throws IOException { - out.close(); - } } diff --git a/dalvik/src/main/java/dalvik/system/profiler/DalvikThreadSampler.java b/dalvik/src/main/java/dalvik/system/profiler/DalvikThreadSampler.java new file mode 100644 index 0000000..c20cc32 --- /dev/null +++ b/dalvik/src/main/java/dalvik/system/profiler/DalvikThreadSampler.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dalvik.system.profiler; + +import dalvik.system.VMStack; +import java.util.Arrays; + +class DalvikThreadSampler implements ThreadSampler { + + private int depth; + + /** + * Reusable storage for sampling sized for the specified depth. + */ + private StackTraceElement[][] mutableStackTraceElements; + + @Override public void setDepth(int depth) { + this.depth = depth; + this.mutableStackTraceElements = new StackTraceElement[depth+1][]; + for (int i = 1; i < mutableStackTraceElements.length; i++) { + this.mutableStackTraceElements[i] = new StackTraceElement[i]; + } + } + + @Override public StackTraceElement[] getStackTrace(Thread thread) { + int count = VMStack.fillStackTraceElements(thread, mutableStackTraceElements[depth]); + if (count == 0) { + return null; + } + if (count < depth) { + System.arraycopy(mutableStackTraceElements[depth], 0, + mutableStackTraceElements[count], 0, + count); + } + return mutableStackTraceElements[count]; + } +} diff --git a/dalvik/src/main/java/dalvik/system/profiler/HprofBinaryToAscii.java b/dalvik/src/main/java/dalvik/system/profiler/HprofBinaryToAscii.java index 2fed9d8..46c443d 100644 --- a/dalvik/src/main/java/dalvik/system/profiler/HprofBinaryToAscii.java +++ b/dalvik/src/main/java/dalvik/system/profiler/HprofBinaryToAscii.java @@ -17,6 +17,9 @@ package dalvik.system.profiler; import java.io.BufferedInputStream; +import java.io.Closeable; +import java.io.DataInputStream; +import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -24,18 +27,25 @@ import java.io.InputStream; /** * Run on device with: - * adb shell dalvikvm 'dalvik.system.SamplingProfiler\$HprofBinaryToAscii' + * adb shell dalvikvm 'dalvik.system.profiler.HprofBinaryToAscii' * * Run on host with: * java -classpath out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar */ public final class HprofBinaryToAscii { + /** + * Main entry point for HprofBinaryToAscii command line tool + */ public static void main(String[] args) { System.exit(convert(args) ? 0 : 1); } - public static boolean convert(String[] args) { + /** + * Reads single file from arguments and attempts to read it as + * either a binary hprof file or a version with a text header. + */ + private static boolean convert(String[] args) { if (args.length != 1) { usage("binary hprof file argument expected"); @@ -47,29 +57,110 @@ public final class HprofBinaryToAscii { return false; } + if (startsWithMagic(file)) { + HprofData hprofData; + try { + hprofData = readHprof(file); + } catch (IOException e) { + System.out.println("Problem reading binary hprof data from " + + file + ": " + e.getMessage()); + return false; + } + return write(hprofData); + } + HprofData hprofData; - InputStream inputStream = null; try { - inputStream = new BufferedInputStream(new FileInputStream(file)); - BinaryHprofReader reader = new BinaryHprofReader(inputStream); - reader.setStrict(false); - reader.read(); - hprofData = reader.getHprofData(); + hprofData = readSnapshot(file); } catch (IOException e) { - System.out.println("Problem reading binary hprof data from " + System.out.println("Problem reading snapshot containing binary hprof data from " + file + ": " + e.getMessage()); return false; + } + return write(hprofData); + } + + /** + * Probe the start of file to see if it starts with a plausible + * binary hprof magic value. If so, it is returned. On any other + * case including unexpected errors, false is returned. + */ + private static boolean startsWithMagic(File file) { + DataInputStream inputStream = null; + try { + inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); + return BinaryHprof.readMagic(inputStream) != null; + } catch (IOException e) { + return false; } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ignored) { + closeQuietly(inputStream); + } + } + + /** + * Read and return an HprofData from a vanilla binary hprof file. + */ + private static HprofData readHprof(File file) throws IOException { + InputStream inputStream = null; + try { + inputStream = new BufferedInputStream(new FileInputStream(file)); + return read(inputStream); + } finally { + closeQuietly(inputStream); + } + } + + /** + * Read a file looking for text header terminated by two newlines, + * then proceed to read binary hprof data. + */ + private static HprofData readSnapshot(File file) throws IOException { + InputStream inputStream = null; + try { + inputStream = new BufferedInputStream(new FileInputStream(file)); + int ch; + while ((ch = inputStream.read()) != -1) { + if (ch == '\n' && inputStream.read() == '\n') { + return read(inputStream); } } + throw new EOFException("Could not find expected header"); + } finally { + closeQuietly(inputStream); + } + } + + /** + * Read binary hprof data from the provided input stream and + * return the HprofData object. + */ + private static HprofData read(InputStream inputStream) throws IOException { + BinaryHprofReader reader = new BinaryHprofReader(inputStream); + reader.setStrict(false); + reader.read(); + return reader.getHprofData(); + } + + /** + * From IoUtils.closeQuietly but replicated for open source + * version. + */ + private static void closeQuietly(Closeable c) { + if (c != null) { + try { + c.close(); + } catch (IOException ignored) { + } } + } + + /** + * Write text verion of hprof data to standard output. Returns + * false on error. + */ + private static boolean write(HprofData hprofData) { try { - HprofWriter writer = new AsciiHprofWriter(hprofData, System.out); - writer.write(); + AsciiHprofWriter.write(hprofData, System.out); } catch (IOException e) { System.out.println("Problem writing ASCII hprof data: " + e.getMessage()); return false; @@ -77,6 +168,9 @@ public final class HprofBinaryToAscii { return true; } + /** + * Prints usage error but does not exit. + */ private static void usage(String error) { System.out.print("ERROR: "); System.out.println(error); diff --git a/dalvik/src/main/java/dalvik/system/profiler/HprofWriter.java b/dalvik/src/main/java/dalvik/system/profiler/HprofWriter.java deleted file mode 100644 index b1d5a9b..0000000 --- a/dalvik/src/main/java/dalvik/system/profiler/HprofWriter.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dalvik.system.profiler; - -import java.io.IOException; - -public interface HprofWriter { - public void write() throws IOException; -} diff --git a/dalvik/src/main/java/dalvik/system/profiler/PortableThreadSampler.java b/dalvik/src/main/java/dalvik/system/profiler/PortableThreadSampler.java new file mode 100644 index 0000000..96e0b27 --- /dev/null +++ b/dalvik/src/main/java/dalvik/system/profiler/PortableThreadSampler.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dalvik.system.profiler; + +import java.util.Arrays; + +/** + * ThreadSampler implementation that only uses Thread.getStackTrace() + * and therefore is portable. + */ +class PortableThreadSampler implements ThreadSampler { + + private int depth; + + @Override public void setDepth(int depth) { + this.depth = depth; + } + + @Override public StackTraceElement[] getStackTrace(Thread thread) { + StackTraceElement[] stackFrames = thread.getStackTrace(); + if (stackFrames.length == 0) { + return null; + } + if (stackFrames.length > depth) { + stackFrames = Arrays.copyOfRange(stackFrames, 0, depth); + } + return stackFrames; + } +} diff --git a/dalvik/src/main/java/dalvik/system/profiler/SamplingProfiler.java b/dalvik/src/main/java/dalvik/system/profiler/SamplingProfiler.java index 13421ec..0266103 100644 --- a/dalvik/src/main/java/dalvik/system/profiler/SamplingProfiler.java +++ b/dalvik/src/main/java/dalvik/system/profiler/SamplingProfiler.java @@ -51,8 +51,7 @@ import java.util.TimerTask; * // another period of measurement * profiler.stop(); * profiler.shutdown(); - * HprofWriter writer = new AsciiHprofWriter(profiler.getHprofData(), System.out); - * writer.write(); + * AsciiHprofWriter.write(profiler.getHprofData(), System.out); * }</pre> */ public final class SamplingProfiler { @@ -78,7 +77,7 @@ public final class SamplingProfiler { * everytime profiling stops because once a {@code TimerTask} is * canceled it cannot be reused. */ - private TimerTask sampler; + private Sampler sampler; /** * The maximum number of {@code StackTraceElements} to retain in @@ -115,13 +114,22 @@ public final class SamplingProfiler { private final Map<Thread, Integer> threadIds = new HashMap<Thread, Integer>(); /** - * Mutable StackTrace that is used for probing stackTraces Map - * without allocating a StackTrace. If addStackTrace needs to - * be thread safe, this would need to be reconsidered. + * Mutable {@code StackTrace} that is used for probing the {@link + * #stackTraces stackTraces} map without allocating a {@code + * StackTrace}. If {@link #addStackTrace addStackTrace} needs to + * be thread safe, have a single mutable instance would need to be + * reconsidered. */ private final HprofData.StackTrace mutableStackTrace = new HprofData.StackTrace(); /** + * The {@code ThreadSampler} is used to produce a {@code + * StackTraceElement} array for a given thread. The array is + * expected to be {@link #depth depth} or less in length. + */ + private final ThreadSampler threadSampler; + + /** * Create a sampling profiler that collects stacks with the * specified depth from the threads specified by the specified * thread collector. @@ -135,14 +143,36 @@ public final class SamplingProfiler { * depth, simply passing in a value for Integer.MAX_VALUE is not * advised because of the significant memory need to retain such * stacks and runtime overhead to compare stacks. + * + * @param threadSet The thread set specifies which threads to + * sample. In a general purpose program, all threads typically + * should be sample with a ThreadSet such as provied by {@link + * #newThreadGroupTheadSet newThreadGroupTheadSet}. For a + * benchmark a fixed set such as provied by {@link + * #newArrayThreadSet newArrayThreadSet} can reduce the overhead + * of profiling. */ public SamplingProfiler(int depth, ThreadSet threadSet) { this.depth = depth; this.threadSet = threadSet; + this.threadSampler = findDefaultThreadSampler(); + threadSampler.setDepth(depth); hprofData.setFlags(BinaryHprof.ControlSettings.CPU_SAMPLING.bitmask); hprofData.setDepth(depth); } + private static ThreadSampler findDefaultThreadSampler() { + if ("Dalvik Core Library".equals(System.getProperty("java.specification.name"))) { + String className = "dalvik.system.profiler.DalvikThreadSampler"; + try { + return (ThreadSampler) Class.forName(className).newInstance(); + } catch (Exception e) { + System.out.println("Problem creating " + className + ": " + e); + } + } + return new PortableThreadSampler(); + } + /** * A ThreadSet specifies the set of threads to sample. */ @@ -263,7 +293,15 @@ public final class SamplingProfiler { if (sampler == null) { return; } - sampler.cancel(); + synchronized(sampler) { + sampler.stop = true; + while (!sampler.stopped) { + try { + sampler.wait(); + } catch (InterruptedException ignored) { + } + } + } sampler = null; } @@ -305,9 +343,21 @@ public final class SamplingProfiler { */ private class Sampler extends TimerTask { + private boolean stop; + private boolean stopped; + private Thread timerThread; public void run() { + synchronized(this) { + if (stop) { + cancel(); + stopped = true; + notifyAll(); + return; + } + } + if (timerThread == null) { timerThread = Thread.currentThread(); } @@ -329,15 +379,10 @@ public final class SamplingProfiler { continue; } - // TODO replace with a VMStack.getThreadStackTrace - // variant to avoid allocating unneeded elements - StackTraceElement[] stackFrames = thread.getStackTrace(); - if (stackFrames.length == 0) { + StackTraceElement[] stackFrames = threadSampler.getStackTrace(thread); + if (stackFrames == null) { continue; } - if (stackFrames.length > depth) { - stackFrames = Arrays.copyOfRange(stackFrames, 0, depth); - } recordStackTrace(thread, stackFrames); } } @@ -357,8 +402,10 @@ public final class SamplingProfiler { int[] countCell = stackTraces.get(mutableStackTrace); if (countCell == null) { countCell = new int[1]; + // cloned because the ThreadSampler may reuse the array + StackTraceElement[] stackFramesCopy = stackFrames.clone(); HprofData.StackTrace stackTrace - = new HprofData.StackTrace(nextStackTraceId++, threadId, stackFrames); + = new HprofData.StackTrace(nextStackTraceId++, threadId, stackFramesCopy); hprofData.addStackTrace(stackTrace, countCell); } countCell[0]++; diff --git a/dalvik/src/main/java/dalvik/system/profiler/ThreadSampler.java b/dalvik/src/main/java/dalvik/system/profiler/ThreadSampler.java new file mode 100644 index 0000000..104b16d --- /dev/null +++ b/dalvik/src/main/java/dalvik/system/profiler/ThreadSampler.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dalvik.system.profiler; + +import java.io.IOException; + +/** + * The {@code ThreadSampler} interfaces allows a profiler to choose + * between portable and VM specific implementations of thread + * sampling. + */ +public interface ThreadSampler { + + /** + * Used to specify the maximum stack depth to collect. + */ + public void setDepth(int depth); + + /** + * Return a stack trace for the current thread limited by the + * maximum depth specified by {@link #setDepth setDepth}. May + * return null if no sample is availble for the thread, which may + * happen in cases such as thread termination. The resulting array + * should be copied before the next call to {@code getStackTrace} + * if the caller wants to use the results, since the {@code + * ThreadSampler} may reuse the array. Note that the elements + * themselves are immutable and do not need to be copied. + */ + public StackTraceElement[] getStackTrace(Thread thread); +} diff --git a/dalvik/src/test/java/dalvik/system/profiler/SamplingProfilerTest.java b/dalvik/src/test/java/dalvik/system/profiler/SamplingProfilerTest.java index 6a43aad..d022cd0 100644 --- a/dalvik/src/test/java/dalvik/system/profiler/SamplingProfilerTest.java +++ b/dalvik/src/test/java/dalvik/system/profiler/SamplingProfilerTest.java @@ -23,7 +23,6 @@ import dalvik.system.profiler.HprofData.Sample; import dalvik.system.profiler.HprofData.StackTrace; import dalvik.system.profiler.HprofData.ThreadEvent; import dalvik.system.profiler.HprofData; -import dalvik.system.profiler.HprofWriter; import dalvik.system.profiler.SamplingProfiler.ThreadSet; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -261,9 +260,7 @@ public class SamplingProfilerTest extends TestCase { */ private void test_HprofData_ascii(HprofData hprofData) throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); - HprofWriter writer = new AsciiHprofWriter(hprofData, out); - writer.write(); - out.close(); + AsciiHprofWriter.write(hprofData, out); assertFalse(out.toByteArray().length == 0); } @@ -274,8 +271,7 @@ public class SamplingProfilerTest extends TestCase { private void test_HprofData_binary(HprofData hprofData, boolean strict) throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); - HprofWriter writer = new BinaryHprofWriter(hprofData, out); - writer.write(); + BinaryHprofWriter.write(hprofData, out); out.close(); byte[] bytes = out.toByteArray(); |