-
Bug
-
Resolution: Fixed
-
P3
-
17, 18
-
b21
-
generic
-
generic
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8342053 | 17.0.14 | Goetz Lindenmaier | P3 | Resolved | Fixed | b01 |
ADDITIONAL SYSTEM INFORMATION :
openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-39)
OpenJDK 64-Bit Server VM (build 17.0.1+12-39, mixed mode, sharing)
openjdk version "18-ea" 2022-03-15
OpenJDK Runtime Environment (build 18-ea+25-1670)
OpenJDK 64-Bit Server VM (build 18-ea+25-1670, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Using jcmd to access Java Flight Recorder on a process running a jlink:ed runtime containing module "jdk.jfr", but missing module "jdk.management.jfr",
jcmd reports "Module jdk.jfr not found."
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The attached Java 17 source code first creates a module and two runtimes (one with and one without "jdk.management.jfr"),
then launches the module with the two runtimes,
then runs "jcmd <pid> JFR.check" and prints the output.
java JcmdMissingModule.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
"Module jdk.management.jfr not found."
ACTUAL -
"Module jdk.jfr not found."
---------- BEGIN SOURCE ----------
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.spi.ToolProvider;
/**
* jcmd prints message "Module jdk.jfr not found.",
* when using slimmed jlink:ed runtime,
* containing module "jdk.jfr".
*
* Adding "jdk.management.jfr" to the jlink:ed runtime,
* makes jcmd happy.
*
* This java program creates source code of a module which just sleeps,
* compiles that,
* makes two jlink:ed runtimes (one without and one with module "jdk.management.jfr"),
* launches the sleeping module with the both runtimes,
* and invokes "jcmd <pid> JFR.check" on theses processes,
* and prints their output.
*/
class JcmdMissingModule {
static ToolProvider javac = ToolProvider.findFirst("javac").orElseThrow(() -> new RuntimeException("No javac"));
static ToolProvider jlink = ToolProvider.findFirst("jlink").orElseThrow(() -> new RuntimeException("No jlink"));
static String module = "sleep";
static String moduleInfo = "module %s {}".formatted(module);
static String Main = """
package example;
class Main {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(Long.MAX_VALUE);
}
}
""";
public static void main(String[] args) throws Exception {
Path out = Path.of("out");
Path src = out.resolve("src");
Path classes = out.resolve("classes");
del(out);
Files.createDirectories(src.resolve(module).resolve("example"));
Files.write(src.resolve(module).resolve("module-info.java"), moduleInfo.getBytes());
Files.write(src.resolve(module).resolve("example").resolve("Main.java"), Main.getBytes());
// Compile module
javac.run(System.out, System.err,
"--module-source-path", src.toString(),
"--module", module,
"-d", classes.toString());
Path javaHome = Path.of(System.getProperty("java.home"));
Path jmods = javaHome.resolve("jmods");
Path jcmd = javaHome.resolve("bin").resolve("jcmd");
String reproducerModules = String.join(",", module, "jdk.jfr", "jdk.management");
String workaroundModules = String.join(",", module, "jdk.jfr", "jdk.management", "jdk.management.jfr");
String modulePath = String.join(File.pathSeparator, jmods.toString(), classes.toString());
String reproducer = out.resolve("reproducer").toString();
String workaround = out.resolve("workaround").toString();
// Create runtimes with limited set of modules
jlink(reproducerModules, modulePath, reproducer);
jlink(workaroundModules, modulePath, workaround);
String reproducerJava = Path.of(reproducer, "bin", "java").toString();
String workaroundJava = Path.of(workaround, "bin", "java").toString();
String moduleWithMain = module + "/example.Main";
// Start processes which just sleep
long reproducerPid = run(reproducerJava, "--module", moduleWithMain).pid();
long workaroundPid = run(workaroundJava, "--module", moduleWithMain).pid();
// Run JFR.check on the processes
String reproducerJcmd = runAndReadOutput(jcmd.toString(), String.valueOf(reproducerPid), "JFR.check");
String workaroundJcmd = runAndReadOutput(jcmd.toString(), String.valueOf(workaroundPid), "JFR.check");
// List modules
String reproducerListModules = runAndReadOutput(reproducerJava, "--list-modules");
String workaroundListModules = runAndReadOutput(workaroundJava, "--list-modules");
System.out.println("""
jcmd:
%s
--list-modules:
%s
jcmd:
%s
--list-modules:
%s
""".formatted(reproducerJcmd, reproducerListModules, workaroundJcmd, workaroundListModules));
}
static Process run(String... cmd) throws Exception {
Process process = new ProcessBuilder(cmd)
.redirectErrorStream(true)
.start();
Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { process.destroy(); } } );
return process;
}
static String runAndReadOutput(String... cmd) throws Exception {
Process process = run(cmd);
process.waitFor();
String output = readOutput(process.getInputStream());
return output;
}
static String readOutput(InputStream is) throws Exception {
var baos = new ByteArrayOutputStream();
is.transferTo(baos);
return baos.toString();
}
static void jlink(String modules, String modulePath, String output) {
jlink.run(System.out, System.err,
"--add-modules", modules,
"--module-path", modulePath,
"--output", output
);
}
static void del(Path dir) {
if (dir.toFile().exists()) {
try (var files = Files.walk(dir)) {
files.sorted(Collections.reverseOrder()).map(Path::toFile).forEach(f -> f.delete());
} catch (Exception e) {}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Adding "jdk.management.jfr" to the jlink:ed runtime
FREQUENCY : always
openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-39)
OpenJDK 64-Bit Server VM (build 17.0.1+12-39, mixed mode, sharing)
openjdk version "18-ea" 2022-03-15
OpenJDK Runtime Environment (build 18-ea+25-1670)
OpenJDK 64-Bit Server VM (build 18-ea+25-1670, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Using jcmd to access Java Flight Recorder on a process running a jlink:ed runtime containing module "jdk.jfr", but missing module "jdk.management.jfr",
jcmd reports "Module jdk.jfr not found."
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The attached Java 17 source code first creates a module and two runtimes (one with and one without "jdk.management.jfr"),
then launches the module with the two runtimes,
then runs "jcmd <pid> JFR.check" and prints the output.
java JcmdMissingModule.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
"Module jdk.management.jfr not found."
ACTUAL -
"Module jdk.jfr not found."
---------- BEGIN SOURCE ----------
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.spi.ToolProvider;
/**
* jcmd prints message "Module jdk.jfr not found.",
* when using slimmed jlink:ed runtime,
* containing module "jdk.jfr".
*
* Adding "jdk.management.jfr" to the jlink:ed runtime,
* makes jcmd happy.
*
* This java program creates source code of a module which just sleeps,
* compiles that,
* makes two jlink:ed runtimes (one without and one with module "jdk.management.jfr"),
* launches the sleeping module with the both runtimes,
* and invokes "jcmd <pid> JFR.check" on theses processes,
* and prints their output.
*/
class JcmdMissingModule {
static ToolProvider javac = ToolProvider.findFirst("javac").orElseThrow(() -> new RuntimeException("No javac"));
static ToolProvider jlink = ToolProvider.findFirst("jlink").orElseThrow(() -> new RuntimeException("No jlink"));
static String module = "sleep";
static String moduleInfo = "module %s {}".formatted(module);
static String Main = """
package example;
class Main {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(Long.MAX_VALUE);
}
}
""";
public static void main(String[] args) throws Exception {
Path out = Path.of("out");
Path src = out.resolve("src");
Path classes = out.resolve("classes");
del(out);
Files.createDirectories(src.resolve(module).resolve("example"));
Files.write(src.resolve(module).resolve("module-info.java"), moduleInfo.getBytes());
Files.write(src.resolve(module).resolve("example").resolve("Main.java"), Main.getBytes());
// Compile module
javac.run(System.out, System.err,
"--module-source-path", src.toString(),
"--module", module,
"-d", classes.toString());
Path javaHome = Path.of(System.getProperty("java.home"));
Path jmods = javaHome.resolve("jmods");
Path jcmd = javaHome.resolve("bin").resolve("jcmd");
String reproducerModules = String.join(",", module, "jdk.jfr", "jdk.management");
String workaroundModules = String.join(",", module, "jdk.jfr", "jdk.management", "jdk.management.jfr");
String modulePath = String.join(File.pathSeparator, jmods.toString(), classes.toString());
String reproducer = out.resolve("reproducer").toString();
String workaround = out.resolve("workaround").toString();
// Create runtimes with limited set of modules
jlink(reproducerModules, modulePath, reproducer);
jlink(workaroundModules, modulePath, workaround);
String reproducerJava = Path.of(reproducer, "bin", "java").toString();
String workaroundJava = Path.of(workaround, "bin", "java").toString();
String moduleWithMain = module + "/example.Main";
// Start processes which just sleep
long reproducerPid = run(reproducerJava, "--module", moduleWithMain).pid();
long workaroundPid = run(workaroundJava, "--module", moduleWithMain).pid();
// Run JFR.check on the processes
String reproducerJcmd = runAndReadOutput(jcmd.toString(), String.valueOf(reproducerPid), "JFR.check");
String workaroundJcmd = runAndReadOutput(jcmd.toString(), String.valueOf(workaroundPid), "JFR.check");
// List modules
String reproducerListModules = runAndReadOutput(reproducerJava, "--list-modules");
String workaroundListModules = runAndReadOutput(workaroundJava, "--list-modules");
System.out.println("""
jcmd:
%s
--list-modules:
%s
jcmd:
%s
--list-modules:
%s
""".formatted(reproducerJcmd, reproducerListModules, workaroundJcmd, workaroundListModules));
}
static Process run(String... cmd) throws Exception {
Process process = new ProcessBuilder(cmd)
.redirectErrorStream(true)
.start();
Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { process.destroy(); } } );
return process;
}
static String runAndReadOutput(String... cmd) throws Exception {
Process process = run(cmd);
process.waitFor();
String output = readOutput(process.getInputStream());
return output;
}
static String readOutput(InputStream is) throws Exception {
var baos = new ByteArrayOutputStream();
is.transferTo(baos);
return baos.toString();
}
static void jlink(String modules, String modulePath, String output) {
jlink.run(System.out, System.err,
"--add-modules", modules,
"--module-path", modulePath,
"--output", output
);
}
static void del(Path dir) {
if (dir.toFile().exists()) {
try (var files = Files.walk(dir)) {
files.sorted(Collections.reverseOrder()).map(Path::toFile).forEach(f -> f.delete());
} catch (Exception e) {}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Adding "jdk.management.jfr" to the jlink:ed runtime
FREQUENCY : always
- backported by
-
JDK-8342053 jcmd reports "Module jdk.jfr not found." when "jdk.management.jfr" is missing
-
- Resolved
-
- links to
-
Commit openjdk/jdk/a345df20
-
Commit(master) openjdk/jdk17u-dev/aa9c49ff
-
Review openjdk/jdk/10723
-
Review(master) openjdk/jdk17u-dev/2956