diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java | |
download | cbb-gcc-4.6.4-upstream.tar.bz2 cbb-gcc-4.6.4-upstream.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java')
-rw-r--r-- | libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java b/libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java new file mode 100644 index 000000000..d56a71da3 --- /dev/null +++ b/libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java @@ -0,0 +1,458 @@ +/* MemoryAnalyze.java -- Analyzes a libgcj heap dump. + Copyright (C) 2007 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.gcj.tools.gc_analyze; + +import gnu.classpath.tools.getopt.FileArgumentCallback; +import gnu.classpath.tools.getopt.Option; +import gnu.classpath.tools.getopt.OptionException; +import gnu.classpath.tools.getopt.Parser; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +class MemoryAnalyze +{ + public MemoryAnalyze() + { + } + + private static NumberFormat numberFormat; + private static boolean verbose; + static String format(long number, int digits) + { + if (numberFormat == null) + { + numberFormat = NumberFormat.getNumberInstance(); + numberFormat.setGroupingUsed(true); + } + String temp = numberFormat.format(number); + int spaces = digits - temp.length(); + if (spaces < 0) + spaces = 0; + return " ".substring(0,spaces) + temp; + } + + static void sorted_report(String description, + int total_space, + ArrayList<String> list, + Comparator<String> comparator) + { + System.out.println("*** " + description + " ***"); + System.out.println(); + System.out.println(" Total Size Count Size Description"); + System.out.println("-------------- ----- -------- -----------------------------------"); + Collections.sort(list, comparator); + for (Iterator it = list.iterator(); it.hasNext(); ) + { + String v = (String)it.next(); + System.out.println(stripend(v)); + } + System.out.println("-------------- ----- -------- -----------------------------------"); + System.out.println(format(total_space, 14)); + System.out.println(); + System.out.println(); + } + + private static String stripend(String s) + { + int n = s.lastIndexOf(" /"); + if (n > 0) + return s.substring(0,n); + return s; + } + + static class SubstringComparator implements Comparator<String> + { + private int begin, end; + private boolean reverse; + + SubstringComparator(int begin, int end, boolean reverse) + { + this.begin = begin; + this.end = end; + this.reverse = reverse; + } + + public int compare(String s1, String s2) + { + if (end == 0) + s1 = s1.substring(begin); + else + s1 = s1.substring(begin, end); + + if (end == 0) + s2 = s2.substring(begin); + else + s2 = s2.substring(begin, end); + int i = s1.compareTo(s2); + if (reverse) + return -i; + return i; + } + } + + static class OptionParser extends Parser + { + int filesFound; + + OptionParser() + { + super("gc-analyze", + "gc-analyze (" + System.getProperty("java.vm.version") + ")"); + + add(new Option('d', + "Directory containing runtime objects", + "directory") + { + public void parsed(String argument) throws OptionException + { + ToolPrefix.pathPrefix = argument; + } + }); + + add(new Option('p', + "Binary tool prefix, prepended to nm and readelf to " + + "obtain target specific versions of these commands", + "prefix") + { + public void parsed(String argument) throws OptionException + { + ToolPrefix.toolPrefix = argument; + } + }); + + add(new Option("verbose", 'v', + "Verbose output; requires filename.bytes") + { + public void parsed(String argument) throws OptionException + { + verbose = true; + } + }); + + setHeader("usage: gc-analyze [-v] [-p tool-prefix] [-d <directory>] " + + "filename"); + } + + protected void validate() throws OptionException + { + if (filesFound != 1) + throw new OptionException("Must specify exactly one filename"); + } + + public String[] parse(String[] inArgs) + { + final ArrayList<String> fileResult = new ArrayList<String>(); + parse(inArgs, new FileArgumentCallback() + { + public void notifyFile(String fileArgument) + { + filesFound++; + fileResult.add(fileArgument); + } + }); + return fileResult.toArray(new String[1]); + } + } + + public static void main(String[] args) + { + class Info + { + int size; + int count; + } + int total_space = 0; + + Parser optionParser = new OptionParser(); + + String rest[] = optionParser.parse(args); + + String filename = rest[0]; + + try + { + BufferedReader reader = + new BufferedReader(new InputStreamReader(new FileInputStream(filename))); + SymbolLookup lookup = new SymbolLookup(reader, filename + ".bytes"); + ObjectMap objectMap = new ObjectMap(reader); + BlockMap blockMap = new BlockMap(reader); + reader.close(); + + // add info to item(s) + // add item.klass + for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap) + { + ObjectMap.ObjectItem item = me.getValue(); + + // try to get a klass (happens with intern'ed strings...) + if (item.klass==0) + { + BytePtr p = lookup.getBytePtr(item.ptr, item.size); + if (p!=null) + { + long vtable = p.getWord(0); + String sym = + lookup.getSymbolViaVtable(vtable - 2 * lookup.memoryMap.wordSize); + if (sym != null) + { + item.typeName = SymbolTable.demangleVTName(sym); + } + else if (vtable != 0) + { + // get klass from vtable + p = lookup.getBytePtr(vtable, + lookup.memoryMap.wordSize); + if (p != null) + { + long klass = p.getWord(0); + item.klass = klass; + } + } + } + } + + // figure out strings + String class_name; + if (null == item.typeName) + { + class_name = + MemoryAnalyze.getSymbolPretty(lookup, item, false); + item.typeName = class_name; + } + else + { + class_name = item.typeName; + } + System.out.print("class_name=[" + class_name + "]"); + + if (class_name.compareTo("_ZTVN4java4lang6StringE")==0 + || class_name.compareTo("java.lang.String")==0) + { + BytePtr p = lookup.getBytePtr(item.ptr, item.size); + long data = p.getWord(1); + int boffset = p.getInt(2 * p.intsPerWord()); + int count = p.getInt(1 + 2 * p.intsPerWord()); + int hash = p.getInt(2 + 2 * p.intsPerWord()); + BytePtr chars = lookup.getBytePtr(data+boffset, count * 2); + StringBuffer sb = new StringBuffer(count); + for (int qq = 0; qq<count; qq++) + sb.append((char)chars.getShort(qq)); + int newhash = sb.toString().hashCode(); + if (newhash!=hash) + { + p.setInt(4, newhash); + } + + item.string = sb.toString(); + System.out.println(" value = \"" + item.string + "\""); + if (data != item.ptr) + { + ObjectMap.ObjectItem next = objectMap.get(data); + if (next != null) + next.stringData = true; + else + System.out.println("String [" + item.string + "] at " + + Long.toHexString(item.ptr) + + " can't find array at " + + Long.toHexString(data)); + } + } + else if (null != item.string) + System.out.println(" value = \"" + item.string + "\""); + else + System.out.println(); + } + + + HashMap<String, Info> map = new HashMap<String, Info>(); + for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap) + { + ObjectMap.ObjectItem item = me.getValue(); + String name = getSymbolPretty(lookup, item, true); + Info info = map.get(name); + if (info == null) + { + info = new Info(); + info.count = 0; + info.size = item.size; + map.put(name, info); + } + info.count++; + total_space += item.size; + } + + ArrayList<String> list = new ArrayList<String>(); + for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) + { + Map.Entry me = (Map.Entry)it.next(); + String name = (String)me.getKey(); + Info info = (Info)me.getValue(); + + StringBuffer sb = new StringBuffer(); + sb.append(format(info.count * info.size * 100 / total_space, + 3)); + sb.append("%"); + sb.append(format(info.count * info.size, 10)); + sb.append(" = "); + sb.append(format(info.count, 7)); + sb.append(" * "); + sb.append(format(info.size, 9)); + sb.append(" - "); + sb.append(name); + list.add(sb.toString()); + } + + sorted_report("Memory Usage Sorted by Total Size", + total_space, list, new SubstringComparator(5,14,true)); + sorted_report("Memory Usage Sorted by Description", + total_space, list, new SubstringComparator(39,0,false)); + sorted_report("Memory Usage Sorted by Count", + total_space, list, new SubstringComparator(17,25,true)); + sorted_report("Memory Usage Sorted by Size", + total_space, list, new SubstringComparator(28,37,true)); + + blockMap.dump(); + + // dump raw memory + if (verbose) + { + // analyze references + for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap) + { + long ptr = me.getKey(); + ObjectMap.ObjectItem item = me.getValue(); + BytePtr p = lookup.getBytePtr(ptr, item.size); + if (p == null) + System.out.println("can't find ptr 0x" + + Long.toHexString(ptr)); + else if (item.kind != 0) // not GC_PTRFREE + for (int i = 1; + i < item.size / lookup.memoryMap.wordSize; i++) + { + long maybe_ptr = p.getWord(i); + ObjectMap.ObjectItem item2 = objectMap.get(maybe_ptr); + if (item2 != null) + { + item2.pointed_by.add(item); + item.points_to.add(item2); + } + } + } + System.out.println(); + System.out.println("*** All Objects ***"); + System.out.println(); + + for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap) + { + long ptr = me.getKey(); + ObjectMap.ObjectItem item = me.getValue(); + String name = getSymbolPretty(lookup, item, false); + System.out.print("0x" + Long.toHexString(ptr) + " - " + name + + " (" + item.size + ")"); + if (item.string != null) + System.out.println(" \"" + item.string + "\""); + else + System.out.println(); + + BytePtr p = lookup.getBytePtr(ptr, item.size); + + if (p == null) + System.out.println( + "can't find memory; recently allocated from free list?"); + else + p.dump(); + + item.points_to.dump(" points to:", lookup); + item.pointed_by.dump(" pointed to by:", lookup); + System.out.println(); + } + } + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + public static String kindToName(int kind) + { + String name; + switch (kind) + { + case 0: + name = "GC_PTRFREE"; + break; + case 1: + name = "GC_NORMAL"; + break; + case 2: + name = "GC_UNCOLLECTABLE"; + break; + case 3: + name = "GC_AUUNCOLLCTABLE"; + break; + case 4: + name = "(Java)"; + break; + case 5: + name = "(Java Debug)"; + break; + case 6: + name = "(Java Array)"; + break; + default: + name = "(Kind " + kind + ")"; + break; + } + return name; + } + + public static String getSymbolPretty(SymbolLookup lookup, + ObjectMap.ObjectItem item, + boolean bsize) + throws IOException + { + + String name = item.typeName; + + if (name == null) + name = lookup.getSymbol(item.klass); + + if (name == null) + { + String v = lookup.decodeUTF8(item.ptr, item.size); + if (null != v) + { + name = "UTF8Const"; + item.string = v; + } + } + + if (name == null) + { + name = kindToName(item.kind); + } + if (item.kind==6) + name += "[" + format(item.data, 0) + "]"; + if (bsize) + name = name + " / " + format(item.size, 7); + return name; + } +} |