1

我使用 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 在删除构建目录时抛出的示例错误。

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,就可以从文件资源管理器中删除该目录而不会出现任何问题。

任何帮助表示赞赏:-)

4

0 回答 0