Shinya Mochida@型
2 min readFeb 14, 2021

--

How to run javap programmatically

javap as a Service

In this article, we are goring to learn how to run javap programmatically.

javap‘s main class is com.sun.tools.javap.Main and its main feature is offered by com.sun.tools.javap.JavapTask. These classes are located in jdk.jdeps module. This module is not exported to java.se module so that we cannot create its instance by new operator.

How can we call javap from java.se module? By java.util.spi.ToolProvider is the only way. com.sun.tools.javap.Main$JavapToolProvider , which is javap ‘s implementation of ToolProvider , can be obtained by passing "javap" to static method ToolProvider#findFirst(String).

ToolProvider javap = ToolProvider.findFirst("javap").orElseThrow()

ToolProvider has only one method(except for default method) run(PrintWriter, PrintWriter, String...). As you know javac is flexible, we can customize JavaFileObject and JavaFileManager to return byte[] from memory instead of files. But as you can guess from the interface of ToolProvider, there is no room for us to customize javap feature. We can only pass arguments as we always pass to javap command in terminal. For example calling run method with -v (verbose), -p(all classes and members) of Foo.class

StringWriter out = new StringWriter();
PrintWriter stdout = new PrintWriter(out);
StringWriter err = new StringWriter();
PrintWriter stderr = new PrintWriter(err);
int exitCode = javap.run(
stdout,
stderr,
"-v", "-p", "/path/to/Foo.class");

An outputs of javap is written to the first PrintWriter , and error messages are written to the first PrintWriter (I don’t know why they are not written to stderr…)

BTW I wrote an application while investigating programmatical javap calling. Here is the URL of the repository. If you are interested in the repository, please visit it.

--

--