{"id":16195967,"url":"https://github.com/gousiosg/java-callgraph","last_synced_at":"2025-05-16T15:07:07.564Z","repository":{"id":47116868,"uuid":"1808361","full_name":"gousiosg/java-callgraph","owner":"gousiosg","description":"Programs for producing static and dynamic (runtime) call graphs for Java programs","archived":false,"fork":false,"pushed_at":"2024-03-22T23:33:53.000Z","size":62,"stargazers_count":802,"open_issues_count":26,"forks_count":261,"subscribers_count":47,"default_branch":"master","last_synced_at":"2025-04-12T11:58:13.971Z","etag":null,"topics":["callgraph","dynamic","java","static"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gousiosg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2011-05-27T06:14:32.000Z","updated_at":"2025-04-08T04:45:55.000Z","dependencies_parsed_at":"2024-10-25T17:10:41.738Z","dependency_job_id":"d8e7efc6-98df-458e-b5a2-7827ee867628","html_url":"https://github.com/gousiosg/java-callgraph","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gousiosg%2Fjava-callgraph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gousiosg%2Fjava-callgraph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gousiosg%2Fjava-callgraph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gousiosg%2Fjava-callgraph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gousiosg","download_url":"https://codeload.github.com/gousiosg/java-callgraph/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254553959,"owners_count":22090417,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["callgraph","dynamic","java","static"],"created_at":"2024-10-10T08:46:11.926Z","updated_at":"2025-05-16T15:07:07.542Z","avatar_url":"https://github.com/gousiosg.png","language":"Java","readme":"java-callgraph: Java Call Graph Utilities\n=========================================\n\nA suite of programs for generating static and dynamic call graphs in Java.\n\n* javacg-static: Reads classes from a jar file, walks down the method bodies and\n   prints a table of caller-caller relationships.\n* javacg-dynamic: Runs as a [Java agent](http://download.oracle.com/javase/6/docs/api/index.html?java/lang/instrument/package-summary.html) and instruments\n  the methods of a user-defined set of classes in order to track their invocations.\n  At JVM exit, prints a table of caller-callee relationships, along with a number\n  of calls\n\n#### Compile\n\nThe java-callgraph package is build with maven. Install maven and do:\n\n```\nmvn install\n```\n\nThis will produce a `target` directory with the following three jars:\n- javacg-0.1-SNAPSHOT.jar: This is the standard maven packaged jar with static and dynamic call graph generator classes\n- `javacg-0.1-SNAPSHOT-static.jar`: This is an executable jar which includes the static call graph generator\n- `javacg-0.1-SNAPSHOT-dycg-agent.jar`: This is an executable jar which includes the dynamic call graph generator\n\n#### Run\n\nInstructions for running the callgraph generators\n\n##### Static\n\n`javacg-static` accepts as arguments the jars to analyze.\n\n```\njava -jar javacg-0.1-SNAPSHOT-static.jar lib1.jar lib2.jar...\n```\n\n`javacg-static` produces combined output in the following format:\n\n###### For methods\n\n```\n  M:class1:\u003cmethod1\u003e(arg_types) (typeofcall)class2:\u003cmethod2\u003e(arg_types)\n```\n\nThe line means that `method1` of `class1` called `method2` of `class2`.\nThe type of call can have one of the following values (refer to\nthe [JVM specification](http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc6.html)\nfor the meaning of the calls):\n\n * `M` for `invokevirtual` calls\n * `I` for `invokeinterface` calls\n * `O` for `invokespecial` calls\n * `S` for `invokestatic` calls\n * `D` for `invokedynamic` calls\n\nFor `invokedynamic` calls, it is not possible to infer the argument types.\n\n###### For classes\n\n```\n  C:class1 class2\n```\n\nThis means that some method(s) in `class1` called some method(s) in `class2`.\n\n##### Dynamic\n\n`javacg-dynamic` uses\n[javassist](http://www.csg.is.titech.ac.jp/~chiba/javassist/) to insert probes\nat method entry and exit points. To be able to analyze a class `javassist` must\nresolve all dependent classes at instrumentation time. To do so, it reads\nclasses from the JVM's boot classloader. By default, the JVM sets the boot\nclasspath to use Java's default classpath implementation (`rt.jar` on\nWin/Linux, `classes.jar` on the Mac). The boot classpath can be extended using\nthe `-Xbootclasspath` option, which works the same as the traditional\n`-classpath` option. It is advisable for `javacg-dynamic` to work as expected,\nto set the boot classpath to the same, or an appropriate subset, entries as the\nnormal application classpath.\n\nMoreover, since instrumenting all methods will produce huge callgraphs which\nare not necessarily helpful (e.g. it will include Java's default classpath\nentries), `javacg-dynamic` includes support for restricting the set of classes\nto be instrumented through include and exclude statements. The options are\nappended to the `-javaagent` argument and has the following format\n\n```\n-javaagent:javacg-dycg-agent.jar=\"incl=mylib.*,mylib2.*,java.nio.*;excl=java.nio.charset.*\"\n```\n\nThe example above will instrument all classes under the the `mylib`, `mylib2` and\n`java.nio` namespaces, except those that fall under the `java.nio.charset` namespace.\n\n```\njava\n-Xbootclasspath:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar:mylib.jar\n-javaagent:javacg-0.1-SNAPSHOT-dycg-agent.jar=\"incl=mylib.*;\"\n-classpath mylib.jar mylib.Mainclass\n```\n\n`javacg-dynamic` produces two kinds of output. On the standard output, it\nwrites method call pairs as shown below:\n\n```\nclass1:method1 class2:method2 numcalls\n```\n\nIt also produces a file named `calltrace.txt` in which it writes the entry\nand exit timestamps for methods, thereby turning `javacg-dynamic` into\na poor man's profiler. The format is the following:\n\n```\n\u003c\u003e[stack_depth][thread_id]fqdn.class:method=timestamp_nanos\n```\n\nThe output line starts with a `\u003c` or `\u003e` depending on whether it is a method\nentry or exit. It then writes the stack depth, thread id and the class and\nmethod name, followed by a timestamp. The provided `process_trace.rb`\nscript processes the callgraph output to generate total time per method\ninformation.\n\n#### Examples\n\nThe following examples instrument the\n[Dacapo benchmark suite](http://dacapobench.org/) to produce dynamic call graphs.\nThe Dacapo benchmarks come in a single big jar archive that contains all dependency\nlibraries. To build the boot class path required for the javacg-dyn program,\nextract the `dacapo.jar` to a directory: all the required libraries can be found\nin the `jar` directory.\n\nRunning the batik Dacapo benchmark:\n\n```\njava -Xbootclasspath:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar:jar/batik-all.jar:jar/xml-apis-ext.jar -javaagent:target/javacg-0.1-SNAPSHOT-dycg-agent.jar=\"incl=org.apache.batik.*,org.w3c.*;\" -jar dacapo-9.12-bach.jar batik -s small |tail -n 10\n```\n\u003cbr/\u003e\n\n```\n[...]\norg.apache.batik.dom.AbstractParentNode:appendChild org.apache.batik.dom.AbstractParentNode:fireDOMNodeInsertedEvent 6270\u003cbr/\u003e\norg.apache.batik.dom.AbstractParentNode:fireDOMNodeInsertedEvent org.apache.batik.dom.AbstractDocument:getEventsEnabled 6280\u003cbr/\u003e\norg.apache.batik.dom.AbstractParentNode:checkAndRemove org.apache.batik.dom.AbstractNode:getOwnerDocument 6280\u003cbr/\u003e\norg.apache.batik.dom.util.DoublyIndexedTable:put org.apache.batik.dom.util.DoublyIndexedTable$Entry:DoublyIndexedTable$Entry 6682\u003cbr/\u003e\norg.apache.batik.dom.util.DoublyIndexedTable:put org.apache.batik.dom.util.DoublyIndexedTable:hashCode 6693\u003cbr/\u003e\norg.apache.batik.dom.AbstractElement:invalidateElementsByTagName org.apache.batik.dom.AbstractElement:getNodeType 7198\u003cbr/\u003e\norg.apache.batik.dom.AbstractElement:invalidateElementsByTagName org.apache.batik.dom.AbstractDocument:getElementsByTagName 14396\u003cbr/\u003e\norg.apache.batik.dom.AbstractElement:invalidateElementsByTagName org.apache.batik.dom.AbstractDocument:getElementsByTagNameNS 28792\u003cbr/\u003e\n```\n\nRunning the lucene Dacapo benchmark:\n\n```\njava -Xbootclasspath:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar:jar/lucene-core-2.4.jar:jar/luindex.jar -javaagent:target/javacg-0.1-SNAPSHOT-dycg-agent.jar=\"incl=org.apache.lucene.*;\" -jar dacapo-9.12-bach.jar luindex -s small |tail -n 10\n```\n\u003cbr/\u003e\u003cbr/\u003e\n\n```\n[...]\norg.apache.lucene.analysis.Token:setTermBuffer org.apache.lucene.analysis.Token:growTermBuffer 43449\u003cbr/\u003e\norg.apache.lucene.analysis.CharArraySet:getSlot org.apache.lucene.analysis.CharArraySet:getHashCode 43472\u003cbr/\u003e\norg.apache.lucene.analysis.CharArraySet:getSlot org.apache.lucene.analysis.CharArraySet:equals 46107\u003cbr/\u003e\norg.apache.lucene.index.FreqProxTermsWriter:appendPostings org.apache.lucene.store.IndexOutput:writeVInt 46507\u003cbr/\u003e\norg.apache.lucene.store.IndexInput:readVInt org.apache.lucene.index.ByteSliceReader:readByte 63927\u003cbr/\u003e\norg.apache.lucene.index.TermsHashPerField:writeVInt org.apache.lucene.index.TermsHashPerField:writeByte 63927\u003cbr/\u003e\norg.apache.lucene.store.IndexOutput:writeVInt org.apache.lucene.store.BufferedIndexOutput:writeByte 94239\u003cbr/\u003e\norg.apache.lucene.index.TermsHashPerField:quickSort org.apache.lucene.index.TermsHashPerField:comparePostings 107343\u003cbr/\u003e\norg.apache.lucene.analysis.Token:termBuffer org.apache.lucene.analysis.Token:initTermBuffer 162115\u003cbr/\u003e\norg.apache.lucene.analysis.Token:termLength org.apache.lucene.analysis.Token:initTermBuffer 205554\u003cbr/\u003e\n```\n\n#### Known Restrictions\n\n* The static call graph generator does not account for methods invoked via\n  reflection.\n* The dynamic call graph generator will not work reliably (or at all) for\n  multithreaded programs\n* The dynamic call graph generator does not handle exceptions very well, so some\nmethods might appear as having never returned\n\n#### Author\n\nGeorgios Gousios \u003cgousiosg@gmail.com\u003e\n\n#### License\n\n[2-clause BSD](http://www.opensource.org/licenses/bsd-license.php)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgousiosg%2Fjava-callgraph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgousiosg%2Fjava-callgraph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgousiosg%2Fjava-callgraph/lists"}