Summary
Improve access to tools shipping with the JDK within a JShell session.
Problem
Users exploring features of Java and the Java Development Kit often want to use tools shipping with it.
It is laborious to access JDK tools and run them without leaving the context of JShell session:
users need to reach out to the single factory method in java.util.spi.ToolFinder
, unpack its optional result, pass in streams for expected and error output, and finally create an array of arguments for the tool run.
Solution
Add TOOLING.jsh
load file to JShell's built-in resources.
This enables users to source JDK tooling support into the currently running JShell session by the /open command and also from the command line:
jshell>/open TOOLING
TOOLING.jsh
contains the following accessors as JShell code snippets:
tools()
Lists all available tools by their namerun(String name, String... args)
Runs a tool specified by its name and passing a variadic array of arguments
TOOLING.jsh
also contains the following convenient delegating accessors as JShell code snippets:
jar(String... args)
delegates torun("jar", args)
javac(String... args)
delegates torun("javac", args)
javadoc(String... args)
delegates torun("javadoc", args)
javap(String... args)
delegates torun("javap", args)
javap(Class<?> type)
delegates torun("javap", "-c", "-v", "-s", TYPE)
jdeps(String... args)
delegates torun("jdeps", args)
jlink(String... args)
delegates torun("jlink", args)
jmod(String... args)
delegates torun("jmod", args)
jpackage(String... args)
delegates torun("jpackage", args)
Specification
TOOLING.jsh
void jar(String... args) { run("jar", args); }
void javac(String... args) { run("javac", args); }
void javadoc(String... args) { run("javadoc", args); }
void javap(String... args) { run("javap", args); }
void jdeps(String... args) { run("jdeps", args); }
void jlink(String... args) { run("jlink", args); }
void jmod(String... args) { run("jmod", args); }
void jpackage(String... args) { run("jpackage", args); }
void javap(Class<?> type) throws Exception {
try {
var name = type.getCanonicalName();
if (name == null) throw new IllegalArgumentException("Type not supported: " + type);
if (type == Class.forName(name, false, ClassLoader.getSystemClassLoader())) {
run("javap", "-c", "-v", "-s", name);
return;
}
} catch (ClassNotFoundException ignored) {
// fall-through
}
var temp = java.nio.file.Files.createTempFile("TOOLING-", ".class");
try {
var name = type.getName().replace('.', '/') + ".class";
try (var in = type.getClassLoader().getResourceAsStream(name);
var out = java.nio.file.Files.newOutputStream(temp)) {
if (in == null) throw new AssertionError("Resource not found: " + name);
in.transferTo(out);
}
run("javap", "-c", "-v", "-s", temp.toString());
} finally {
java.nio.file.Files.delete(temp);
}
}
void run(String name, String... args) {
var tool = java.util.spi.ToolProvider.findFirst(name);
if (tool.isEmpty()) throw new RuntimeException("No such tool found: " + name);
var code = tool.get().run(System.out, System.err, args);
if (code == 0) return;
System.err.println(name + " returned non-zero exit code: " + code);
}
void tools() {
java.util.ServiceLoader.load(java.util.spi.ToolProvider.class).stream()
.map(java.util.ServiceLoader.Provider::get)
.map(java.util.spi.ToolProvider::name)
.sorted()
.forEach(System.out::println);
}
- csr of
-
JDK-8306560 Add TOOLING.jsh load file
- Resolved