Example #1
0
func main() {
	flag.Usage = usage
	flag.Parse()

	var dump, exec string
	args := flag.Args()
	switch len(args) {
	case 1:
		dump = args[0]
		exec = ""
	case 2:
		dump = args[0]
		exec = args[1]
	default:
		usage()
		return
	}

	fmt.Println("Loading...")
	d = read.Read(dump, exec)

	fmt.Println("Analyzing...")
	prepare()

	fmt.Println("Ready.  Point your browser to localhost" + *httpAddr)
	http.HandleFunc("/", mainHandler)
	http.HandleFunc("/obj", objHandler)
	http.HandleFunc("/type", typeHandler)
	http.HandleFunc("/histo", histoHandler)
	http.HandleFunc("/globals", globalsHandler)
	http.HandleFunc("/goroutines", goListHandler)
	http.HandleFunc("/go", goHandler)
	http.HandleFunc("/frame", frameHandler)
	http.HandleFunc("/others", othersHandler)
	http.HandleFunc("/heapdump", heapdumpHandler)
	if err := http.ListenAndServe(*httpAddr, nil); err != nil {
		log.Fatal(err)
	}
}
Example #2
0
func main() {
	flag.Parse()
	args := flag.Args()
	var d *read.Dump
	if len(args) == 2 {
		d = read.Read(args[0], args[1])
	} else {
		d = read.Read(args[0], "")
	}

	// eliminate unreachable objects
	// TODO: have reader do this?
	reachable := make([]bool, d.NumObjects())
	var q []read.ObjId
	for _, f := range d.Frames {
		for _, e := range f.Edges {
			if !reachable[e.To] {
				reachable[e.To] = true
				q = append(q, e.To)
			}
		}
	}
	for _, x := range []*read.Data{d.Data, d.Bss} {
		for _, e := range x.Edges {
			if !reachable[e.To] {
				reachable[e.To] = true
				q = append(q, e.To)
			}
		}
	}
	for _, r := range d.Otherroots {
		for _, e := range r.Edges {
			if !reachable[e.To] {
				reachable[e.To] = true
				q = append(q, e.To)
			}
		}
	}
	for _, f := range d.QFinal {
		for _, e := range f.Edges {
			if !reachable[e.To] {
				reachable[e.To] = true
				q = append(q, e.To)
			}

		}
	}
	for _, g := range d.Goroutines {
		if g.Ctxt != read.ObjNil {
			if !reachable[g.Ctxt] {
				reachable[g.Ctxt] = true
				q = append(q, g.Ctxt)
			}
		}
	}
	for len(q) > 0 {
		x := q[0]
		q = q[1:]
		for _, e := range d.Edges(x) {
			if !reachable[e.To] {
				reachable[e.To] = true
				q = append(q, e.To)
			}
		}
	}

	fmt.Printf("digraph {\n")

	// print object graph
	for i := 0; i < d.NumObjects(); i++ {
		x := read.ObjId(i)
		if !reachable[x] {
			fmt.Printf("  v%d [style=filled fillcolor=gray];\n", x)
		}
		fmt.Printf("  v%d [label=\"%s\\n%d\"];\n", x, d.Ft(x).Name, d.Size(x))
		for _, e := range d.Edges(x) {
			var taillabel, headlabel string
			if e.FieldName != "" {
				taillabel = fmt.Sprintf(" [taillabel=\"%s\"]", e.FieldName)
			} else if e.FromOffset != 0 {
				taillabel = fmt.Sprintf(" [taillabel=\"%d\"]", e.FromOffset)
			}
			if e.ToOffset != 0 {
				headlabel = fmt.Sprintf(" [headlabel=\"%d\"]", e.ToOffset)
			}
			fmt.Printf("  v%d -> v%d%s%s;\n", x, e.To, taillabel, headlabel)
		}
	}

	// goroutines and stacks
	for _, t := range d.Goroutines {
		fmt.Printf("  \"goroutines\" [shape=diamond];\n")
		fmt.Printf("  \"goroutines\" -> f%x_0;\n", t.Bos.Addr)
	}

	// stack frames
	for _, f := range d.Frames {
		fmt.Printf("  f%x_%d [label=\"%s\\n%d\" shape=rectangle];\n", f.Addr, f.Depth, f.Name, len(f.Data))
		if f.Parent != nil {
			fmt.Printf("  f%x_%d -> f%x_%d;\n", f.Addr, f.Depth, f.Parent.Addr, f.Parent.Depth)
		}
		for _, e := range f.Edges {
			if e.To != read.ObjNil {
				var taillabel, headlabel string
				if e.FieldName != "" {
					taillabel = fmt.Sprintf(" [taillabel=\"%s\"]", e.FieldName)
				} else if e.FromOffset != 0 {
					taillabel = fmt.Sprintf(" [taillabel=\"%d\"]", e.FromOffset)
				}
				if e.ToOffset != 0 {
					headlabel = fmt.Sprintf(" [headlabel=\"%d\"]", e.ToOffset)
				}
				fmt.Printf("  f%x_%d -> v%d%s%s;\n", f.Addr, f.Depth, e.To, taillabel, headlabel)
			}
		}
	}
	for _, x := range []*read.Data{d.Data, d.Bss} {
		for _, e := range x.Edges {
			if e.To != read.ObjNil {
				var headlabel string
				if e.ToOffset != 0 {
					headlabel = fmt.Sprintf(" [headlabel=\"%d\"]", e.ToOffset)
				}
				fmt.Printf("  \"%s\" [shape=diamond];\n", e.FieldName)
				fmt.Printf("  \"%s\" -> v%d%s;\n", e.FieldName, e.To, headlabel)
			}
		}
	}
	for _, r := range d.Otherroots {
		for _, e := range r.Edges {
			var headlabel string
			if e.ToOffset != 0 {
				headlabel = fmt.Sprintf(" [headlabel=\"%d\"]", e.ToOffset)
			}
			fmt.Printf("  \"%s\" [shape=diamond];\n", r.Description)
			fmt.Printf("  \"%s\" -> v%d%s;\n", r.Description, e.To, headlabel)
		}
	}
	for _, f := range d.QFinal {
		for _, e := range f.Edges {
			var headlabel string
			if e.ToOffset != 0 {
				headlabel = fmt.Sprintf(" [headlabel=\"%d\"]", e.ToOffset)
			}
			fmt.Printf("  \"queued finalizers\" [shape=diamond];\n")
			fmt.Printf("  \"queued finalizers\" -> v%d%s;\n", e.To, headlabel)
		}
	}

	fmt.Printf("}\n")
}
Example #3
0
func main() {
	flag.Parse()
	args := flag.Args()
	var outfile string
	if len(args) == 2 {
		d = read.Read(args[0], "")
		outfile = args[1]
	} else {
		d = read.Read(args[0], args[1])
		outfile = args[2]
	}

	// some setup
	usedIds = make(map[uint64]struct{}, 0)
	for _, typ := range d.Types {
		usedIds[typ.Addr] = struct{}{}
	}
	for i := 0; i < d.NumObjects(); i++ {
		usedIds[d.Addr(read.ObjId(i))] = struct{}{}
	}
	stringCache = make(map[string]uint64, 0)
	threadSerialNumbers = make(map[*read.GoRoutine]uint32, 0)
	stackTraceSerialNumbers = make(map[*read.GoRoutine]uint32, 0)

	// std header
	hprof = append(hprof, []byte("JAVA PROFILE 1.0.1\x00")...)
	hprof = append32(hprof, 8) // IDs are 8 bytes (TODO: d.PtrSize?)
	hprof = append32(hprof, 0) // dummy base time
	hprof = append32(hprof, 0) // dummy base time

	// fake entries to make java tools happy
	java_lang_class, _ = addLoadClass("java.lang.Class")
	java_lang_classloader, _ = addLoadClass("java.lang.ClassLoader")
	java_lang_object, java_lang_object_ser = addLoadClass("java.lang.Object")
	java_lang_string, _ = addLoadClass("java.lang.String")
	java_lang_objectarray, _ = addLoadClass("Object[]")
	go_class, go_class_ser = addLoadClass("go")
	addLoadClass("bool[]")
	addLoadClass("char[]")
	addLoadClass("float[]")
	addLoadClass("double[]")
	addLoadClass("byte[]")
	addLoadClass("short[]")
	addLoadClass("int[]")
	addLoadClass("long[]")

	addDummyThread() // must come after addLoadClass(java.lang.Object)

	addThreads()

	// the full heap is one big tag
	addHeapDump()

	// write final file to output
	file, err := os.Create(outfile)
	if err != nil {
		log.Fatal(err)
	}
	file.Write(hprof)
	file.Close()
}