尝试删除重命名的目录时使用java.nio.file.AccessDeniedException使用Files.move

问题描述

我正在使用eclipse jetty作为Web容器,并且该应用程序在Windows环境中提供服务。客户端和服务器使用 javax.websocket 进行通信。客户端只需从linux环境发送源zip到Windows环境,并在Windows环境中构建源代码后,输出zip将发送回Linux环境。

每次成功构建时,将在Release目录下创建输出可执行文件。例如:

D:\ Build \ 26-09-2020 \ foo \ Release \ donate.exe

然后将文件移动到输出目录,并最终将输出目录的内容发送回客户端。下面是输出目录结构的示例。

D:\ build \ 26-09-2020 \ foo \ wintask_output

一切正常,没有任何问题,但是当我尝试删除构建目录时(例如)

D:\ build \ 26-09-2020

内容删除,但目录结构位于机器中,直到重新启动Jetty服务器为止。以下是Windows删除构建目录时引发的示例错误

error thrown by 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

以下是码头服务器启动以及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运行时环境Zulu11.41 + 23-CA(内部版本11.0.8 + 10-LTS)和Java™SE运行时环境(内部版本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 ,就可以从文件浏览器删除目录,而不会出现任何问题。

感谢您的帮助:-)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)