mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-02 15:20:27 +00:00
8386334: JdepsTask keeps --system files open
Reviewed-by: vromero, alanb, liach
This commit is contained in:
parent
a84cd26198
commit
5b1b98c109
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,6 +29,7 @@ import static com.sun.tools.jdeps.Module.trace;
|
||||
import static java.util.stream.Collectors.*;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
@ -41,6 +42,7 @@ import java.lang.module.ModuleReader;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.net.URI;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
@ -282,6 +284,7 @@ public class JdepsConfiguration implements AutoCloseable {
|
||||
archive.close();
|
||||
for (Module module : nameToModule.values())
|
||||
module.close();
|
||||
system.close();
|
||||
}
|
||||
|
||||
static class SystemModuleFinder implements ModuleFinder {
|
||||
@ -290,6 +293,7 @@ public class JdepsConfiguration implements AutoCloseable {
|
||||
private final FileSystem fileSystem;
|
||||
private final Path root;
|
||||
private final Map<String, ModuleReference> systemModules;
|
||||
private final List<Closeable> closeables = new ArrayList<>();
|
||||
|
||||
SystemModuleFinder() {
|
||||
if (Files.isRegularFile(Paths.get(JAVA_HOME, "lib", "modules"))) {
|
||||
@ -321,6 +325,11 @@ public class JdepsConfiguration implements AutoCloseable {
|
||||
env.put("java.home", javaHome);
|
||||
// a remote run-time image
|
||||
this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), env);
|
||||
closeables.add(fileSystem);
|
||||
ClassLoader cl = fileSystem.provider().getClass().getClassLoader();
|
||||
if (cl instanceof URLClassLoader urlcl) {
|
||||
closeables.add(urlcl);
|
||||
}
|
||||
this.root = fileSystem.getPath("/modules");
|
||||
this.systemModules = walk(root);
|
||||
}
|
||||
@ -420,6 +429,24 @@ public class JdepsConfiguration implements AutoCloseable {
|
||||
.map(ModuleDescriptor::name)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
IOException ioe = null;
|
||||
for (Closeable closeable : closeables) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (IOException ex) {
|
||||
if (ioe == null) {
|
||||
ioe = ex;
|
||||
} else {
|
||||
ioe.addSuppressed(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ioe != null) {
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
109
test/langtools/tools/jdeps/SystemFilesClosed.java
Normal file
109
test/langtools/tools/jdeps/SystemFilesClosed.java
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8386334
|
||||
* @summary Check that `lib/jrt-fs.jar` and `lib/modules` are properly closed while
|
||||
* jdeps is invoked with `--system` option.
|
||||
* @requires os.family == "mac" | os.family == "linux"
|
||||
* @modules jdk.jdeps
|
||||
* @library lib
|
||||
* @build JdepsRunner
|
||||
* @run junit ${test.main.class}
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
|
||||
public class SystemFilesClosed {
|
||||
|
||||
private Path base;
|
||||
|
||||
@Test
|
||||
void testSystemFilesClosed() throws Exception {
|
||||
// Probe lsof availability before doing the jlink/jdeps work
|
||||
if (!lsofCommand().isPresent()) {
|
||||
Assumptions.abort("lsof command is not available on this system");
|
||||
}
|
||||
|
||||
String targetSystem = base.toString();
|
||||
int ret = java.util.spi.ToolProvider.findFirst("jlink")
|
||||
.orElseThrow()
|
||||
.run(System.out, System.err, "--add-modules", "java.base", "--output", targetSystem);
|
||||
if (ret != 0) {
|
||||
System.out.println("It is most probably an exploded build. Skip testing.");
|
||||
return;
|
||||
}
|
||||
|
||||
JdepsRunner jdeps = new JdepsRunner("--check", "java.base", "--system", targetSystem);
|
||||
Assertions.assertEquals(0, jdeps.run(true), "Jdeps task failed");
|
||||
|
||||
Process process = new ProcessBuilder()
|
||||
.command(lsofCommand().orElseThrow(() -> new RuntimeException("lsof command is not available on this system")),
|
||||
"-p", String.valueOf(ProcessHandle.current().pid()))
|
||||
.redirectOutput(ProcessBuilder.Redirect.PIPE)
|
||||
.redirectError(ProcessBuilder.Redirect.INHERIT)
|
||||
.start();
|
||||
List<String> lines;
|
||||
String realPath = base.toRealPath().toString();
|
||||
try (InputStream stdout = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(stdout))) {
|
||||
lines = reader.lines().filter(line -> line.contains(realPath)).toList();
|
||||
}
|
||||
process.waitFor();
|
||||
Assertions.assertEquals(0, lines.size(), "File(s) remain opened: " + lines);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp(TestInfo info) {
|
||||
base = Paths.get(".")
|
||||
.resolve(info.getTestMethod()
|
||||
.orElseThrow()
|
||||
.getName());
|
||||
}
|
||||
|
||||
static Optional<String> lsofCommandCache = Arrays.stream(new String[] {
|
||||
"/usr/bin/lsof",
|
||||
"/usr/sbin/lsof",
|
||||
"/bin/lsof",
|
||||
"/sbin/lsof",
|
||||
"/usr/local/bin/lsof"})
|
||||
.filter(args -> new File(args).exists())
|
||||
.findFirst();
|
||||
|
||||
static Optional<String> lsofCommand() {
|
||||
return lsofCommandCache;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user