diff options
author | 2015-08-31 10:22:56 -0700 | |
---|---|---|
committer | 2015-10-26 11:10:08 -0700 | |
commit | 77ff54b5055ec55806069c8d026b102df29857b5 (patch) | |
tree | d2dca5b1118b6c36a35202a95a1ad8030dd904bb | |
parent | e04f37908bfd72382163c1285853e662373229a2 (diff) |
Limit summary string lengths to 200 characters.
Strings longer than 200 characters are now truncated and are shown
with a trailing "..." instead of an end quote. The number 200 was
chosen arbitrarily.
Bug: 23223379
Change-Id: I96d7c9d563026233ff5f4962245b4c276d776a58
-rw-r--r-- | tools/ahat/README.txt | 3 | ||||
-rw-r--r-- | tools/ahat/src/InstanceUtils.java | 30 | ||||
-rw-r--r-- | tools/ahat/src/Value.java | 16 | ||||
-rw-r--r-- | tools/ahat/src/manifest.txt | 2 | ||||
-rw-r--r-- | tools/ahat/test/InstanceUtilsTest.java | 34 |
5 files changed, 68 insertions, 17 deletions
diff --git a/tools/ahat/README.txt b/tools/ahat/README.txt index 5615f8f409..d6f55aae16 100644 --- a/tools/ahat/README.txt +++ b/tools/ahat/README.txt @@ -28,8 +28,6 @@ TODO: - Use consistent order for heap columns. Sometimes I see "app" first, sometimes last (from one heap dump to another) How about, always sort by name? - * For long strings, limit the string length shown in the summary view to - something reasonable. Say 50 chars, then add a "..." at the end. * For HeapTable with single heap shown, the heap name isn't centered? * Consistently document functions. * Should help be part of an AhatHandler, that automatically gets the menu and @@ -70,6 +68,7 @@ Things to Test: showing all the instances. * That InstanceUtils.asString properly takes into account "offset" and "count" fields, if they are present. + * InstanceUtils.getDexCacheLocation Reported Issues: * Request to be able to sort tables by size. diff --git a/tools/ahat/src/InstanceUtils.java b/tools/ahat/src/InstanceUtils.java index eb9e363d8c..c2d75c4ad7 100644 --- a/tools/ahat/src/InstanceUtils.java +++ b/tools/ahat/src/InstanceUtils.java @@ -60,9 +60,21 @@ class InstanceUtils { } - // Read the string value from an hprof Instance. - // Returns null if the object can't be interpreted as a string. + /** + * Read the string value from an hprof Instance. + * Returns null if the object can't be interpreted as a string. + */ public static String asString(Instance inst) { + return asString(inst, -1); + } + + /** + * Read the string value from an hprof Instance. + * Returns null if the object can't be interpreted as a string. + * The returned string is truncated to maxChars characters. + * If maxChars is negative, the returned string is not truncated. + */ + public static String asString(Instance inst, int maxChars) { if (!isInstanceOfClass(inst, "java.lang.String")) { return null; } @@ -81,13 +93,15 @@ class InstanceUtils { // array, we should use that here. int numChars = chars.getValues().length; int count = getIntField(inst, "count", numChars); - int offset = getIntField(inst, "offset", 0); - int end = offset + count - 1; - if (count == 0) { return ""; } + if (0 <= maxChars && maxChars < count) { + count = maxChars; + } + int offset = getIntField(inst, "offset", 0); + int end = offset + count - 1; if (offset >= 0 && offset < numChars && end >= 0 && end < numChars) { return new String(chars.asCharArray(offset, count)); } @@ -234,12 +248,14 @@ class InstanceUtils { * Assuming inst represents a DexCache object, return the dex location for * that dex cache. Returns null if the given instance doesn't represent a * DexCache object or the location could not be found. + * If maxChars is non-negative, the returned location is truncated to + * maxChars in length. */ - public static String getDexCacheLocation(Instance inst) { + public static String getDexCacheLocation(Instance inst, int maxChars) { if (isInstanceOfClass(inst, "java.lang.DexCache")) { Instance location = getRefField(inst, "location"); if (location != null) { - return asString(location); + return asString(location, maxChars); } } return null; diff --git a/tools/ahat/src/Value.java b/tools/ahat/src/Value.java index 9b483faa32..4eb27b1052 100644 --- a/tools/ahat/src/Value.java +++ b/tools/ahat/src/Value.java @@ -25,6 +25,10 @@ import java.net.URI; */ class Value { + // For string literals, we limit the number of characters we show to + // kMaxChars in case the string is really long. + private static int kMaxChars = 200; + /** * Create a DocString representing a summary of the given instance. */ @@ -43,15 +47,19 @@ class Value { link.append(inst.toString()); // Annotate Strings with their values. - String stringValue = InstanceUtils.asString(inst); + String stringValue = InstanceUtils.asString(inst, kMaxChars); if (stringValue != null) { - link.appendFormat("\"%s\"", stringValue); + link.appendFormat("\"%s", stringValue); + link.append(kMaxChars == stringValue.length() ? "..." : "\""); } // Annotate DexCache with its location. - String dexCacheLocation = InstanceUtils.getDexCacheLocation(inst); + String dexCacheLocation = InstanceUtils.getDexCacheLocation(inst, kMaxChars); if (dexCacheLocation != null) { - link.append(" for " + dexCacheLocation); + link.appendFormat(" for %s", dexCacheLocation); + if (kMaxChars == dexCacheLocation.length()) { + link.append("..."); + } } URI objTarget = DocString.formattedUri("object?id=%d", inst.getId()); diff --git a/tools/ahat/src/manifest.txt b/tools/ahat/src/manifest.txt index 7efb1a770f..421de1715a 100644 --- a/tools/ahat/src/manifest.txt +++ b/tools/ahat/src/manifest.txt @@ -1,4 +1,4 @@ Name: ahat/ Implementation-Title: ahat -Implementation-Version: 0.2 +Implementation-Version: 0.3 Main-Class: com.android.ahat.Main diff --git a/tools/ahat/test/InstanceUtilsTest.java b/tools/ahat/test/InstanceUtilsTest.java index 7613df4994..11f82a2301 100644 --- a/tools/ahat/test/InstanceUtilsTest.java +++ b/tools/ahat/test/InstanceUtilsTest.java @@ -25,21 +25,49 @@ import org.junit.Test; public class InstanceUtilsTest { @Test - public void basicString() throws IOException { + public void asStringBasic() throws IOException { TestDump dump = TestDump.getTestDump(); Instance str = (Instance)dump.getDumpedThing("basicString"); assertEquals("hello, world", InstanceUtils.asString(str)); } @Test - public void nullString() throws IOException { + public void asStringTruncated() throws IOException { + TestDump dump = TestDump.getTestDump(); + Instance str = (Instance)dump.getDumpedThing("basicString"); + assertEquals("hello", InstanceUtils.asString(str, 5)); + } + + @Test + public void asStringExactMax() throws IOException { + TestDump dump = TestDump.getTestDump(); + Instance str = (Instance)dump.getDumpedThing("basicString"); + assertEquals("hello, world", InstanceUtils.asString(str, 12)); + } + + @Test + public void asStringNotTruncated() throws IOException { + TestDump dump = TestDump.getTestDump(); + Instance str = (Instance)dump.getDumpedThing("basicString"); + assertEquals("hello, world", InstanceUtils.asString(str, 50)); + } + + @Test + public void asStringNegativeMax() throws IOException { + TestDump dump = TestDump.getTestDump(); + Instance str = (Instance)dump.getDumpedThing("basicString"); + assertEquals("hello, world", InstanceUtils.asString(str, -3)); + } + + @Test + public void asStringNull() throws IOException { TestDump dump = TestDump.getTestDump(); Instance obj = (Instance)dump.getDumpedThing("nullString"); assertNull(InstanceUtils.asString(obj)); } @Test - public void notString() throws IOException { + public void asStringNotString() throws IOException { TestDump dump = TestDump.getTestDump(); Instance obj = (Instance)dump.getDumpedThing("anObject"); assertNotNull(obj); |