我使用 eclipse jetty 作为 web 容器,应用程序在 windows 环境中提供服务。客户端和服务器使用 javax.websocket进行通信。客户端只需将源 zip 从 linux 环境发送到 windows 环境,然后在 windows 中构建源代码环境,输出 zip 将被发送回 linux 环境。
每次成功构建时,都会在 Release 目录下创建输出可执行文件。例如:
D:\Build\26-09-2020\foo\Release\donate.exe
然后文件将被移动到输出目录,最终输出目录的内容将被发送回客户端。以下是输出目录结构的示例。
D:\build\26-09-2020\foo\wintask_output
一切正常,没有任何问题,但是当我尝试删除构建目录时(即)
D:\构建\26-09-2020
内容已被删除,但目录结构驻留在机器中,直到重新启动码头服务器。以下是 Windows 在删除构建目录时抛出的示例错误。
下面是用于将donate.exe从发布目录移动到输出目录的代码:
private boolean moveFileOrDirectory(String src, String target) {
Path source = Paths.get(src);
Path destination = Paths.get(target);
Boolean isMoved = false;
int relay = 0;
if (Files.notExists(source)) {
logger.info("source directory '" + source + "' doesn't exist, ignoring move action");
return true;
}
while (!isMoved && relay < 20) {
try {
Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING);
isMoved = true;
break;
} catch (Exception e) {
logger.trace(
":: This exception will be taken as granted beecause windows/antivirus may held the files while renaming :: Exception",
e);
}
relay++;
}
if (!isMoved) {
logger.trace("Cannot move directories using java attempting to move as native command");
String CommandLine = "-noprofile" + " " + "-nologo" + " " + "-noninteractive" + " " + "-Command" + " "
+ "Rename-Item" + " " + io.surroundWithDoubleQuotes(source.toString()) + " "
+ io.surroundWithDoubleQuotes(destination.toString());
io.executeNativeCommand(Constants.POWER_SHELL_EXECUTABLE, CommandLine, this.WorkDirectory,
this.WorkDirectory + pathSep + "renameFolder.txt", false);
}
if (Files.exists(destination)) {
logger.trace("Directory/File renamed from '" + source + "' to '"+destination+"'.");
isMoved = true;
}
return isMoved;
}
甚至我试图删除我的 cron 作业(ScheduledExecutorService)中的旧目录,下面是例外:
27 Sep 2020 20:00:27 TRACE com.integ.utils.FileIO.forceDeleteDirectory() @402 - Exception while deleting directory D:\Build\26-09-2020
java.io.IOException: Unable to delete file: D:\Build\26-09-2020
at org.apache.commons.io.FileUtils.forceDelete(FileUtils.java:1338) ~[commons-io-2.7.jar:2.7]
at com.integ.utils.FileIO.forceDeleteDirectory(FileIO.java:398) [JettyStandAloneServer.jar:?]
at com.integ.scheduledjobs.server.ScheduledTasks.deleteOneDayOlderDirectories(ScheduledTasks.java:31) [JettyStandAloneServer.jar:?]
at com.integ.scheduledjobs.server.ScheduledTasks.run(ScheduledTasks.java:50) [JettyStandAloneServer.jar:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) [?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
at java.lang.Thread.run(Thread.java:834) [?:?]
Caused by: java.nio.file.AccessDeniedException: D:\Build\26-09-2020\foo
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:89) ~[?:?]
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103) ~[?:?]
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108) ~[?:?]
at sun.nio.fs.WindowsDirectoryStream.<init>(WindowsDirectoryStream.java:86) ~[?:?]
at sun.nio.fs.WindowsFileSystemProvider.newDirectoryStream(WindowsFileSystemProvider.java:523) ~[?:?]
at java.nio.file.Files.newDirectoryStream(Files.java:471) ~[?:?]
at java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:300) ~[?:?]
at java.nio.file.FileTreeWalker.next(FileTreeWalker.java:373) ~[?:?]
at java.nio.file.Files.walkFileTree(Files.java:2760) ~[?:?]
at java.nio.file.Files.walkFileTree(Files.java:2796) ~[?:?]
at org.apache.commons.io.file.PathUtils.visitFileTree(PathUtils.java:535) ~[commons-io-2.7.jar:2.7]
at org.apache.commons.io.file.PathUtils.deleteDirectory(PathUtils.java:265) ~[commons-io-2.7.jar:2.7]
at org.apache.commons.io.file.PathUtils.delete(PathUtils.java:254) ~[commons-io-2.7.jar:2.7]
at org.apache.commons.io.FileUtils.forceDelete(FileUtils.java:1336) ~[commons-io-2.7.jar:2.7]
... 9 more
下面是jetty服务器启动和websocket集成的主要程序:
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import javax.websocket.Decoder;
import javax.websocket.Encoder;
import javax.websocket.server.ServerContainer;
import javax.websocket.server.ServerEndpointConfig;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.glassfish.jersey.servlet.ServletContainer;
import com.integ.commons.Constants;
import com.integ.jetty.filters.TokenFilter;
import com.integ.scheduledjobs.server.Cron;
import static javax.servlet.DispatcherType.REQUEST;
public class Initservice
{
private static final Logger logger = LogManager.getLogger(Initservice.class.getName());
public static Server createServer(int port)
{
Server server = new Server(port);
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/");
servletContextHandler.addServlet(DefaultServlet.class, "/");
servletContextHandler.addFilter(TokenFilter.class, "/*", EnumSet.of(REQUEST));
ServletHolder servletHolder = servletContextHandler.addServlet(ServletContainer.class, "/api/*");
server.setHandler(servletContextHandler);
servletHolder.setInitOrder(0);
servletHolder.setInitParameter(
"jersey.config.server.provider.packages",
"com.integ.rest"
);
try
{
// Initialize javax.websocket layer
ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
// Add WebSocket endpoint to javax.websocket layer
wscontainer.setDefaultMaxBinaryMessageBufferSize(65565555);
wscontainer.setDefaultMaxTextMessageBufferSize(65565555);
wscontainer.setDefaultMaxSessionIdleTimeout(0);
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(WsServer.class, "/events").build();
wscontainer.addEndpoint(config);
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
return server;
}
public static void main(String[] args) throws Exception
{
int port = Constants.Port;
Server server = createServer(port);
Cron scheduledjobs = new Cron();
try {
scheduledjobs.startScheduledServices();
server.start();
server.join();
} catch(Exception ex) {
logger.error("Error While starting jetty server");
logger.log(Level.ERROR, ex.getMessage(), ex);
} finally {
server.stop();
server.destroy();
logger.fatal("Server destroyed..");
}
}
}
Java 版本 - OpenJDK Runtime Environment Zulu11.41+23-CA (build 11.0.8+10-LTS) & Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Windows 版本 - 2019 服务器(10.0.17763 Build 17763)
该问题在使用执行移动操作的目录/文件上仍然存在
Files.move(Path source,Path target,CopyOption... options)throws IOException
更新: 该错误仅在 Windows 环境中发生,相同的设置在 Linux 中运行良好。这个异常是因为jvm吗?因为只要我关闭jvm,就可以从文件资源管理器中删除该目录而不会出现任何问题。
任何帮助表示赞赏:-)