You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已通过JNA加载并释放的DLL无法删除问题求助

问题描述

尝试删除通过JNA加载并释放的DLL文件,已经试过Stack Overflow上《How to dispose library loaded with JNA》里的所有方案,但都无效。

未添加延迟的测试代码

import java.io.File;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;

class Filter {

    private static ExtDLLTool DLLUtil;
    final private static String dllPath = "./ExternalDownloader_64.dll";

    static {
        DLLUtil = (ExtDLLTool) Native.loadLibrary(dllPath, ExtDLLTool.class);
    }

    public static void main(String[] args) {

        if (DLLUtil != null) {
            DLLUtil = null;
            NativeLibrary lib = NativeLibrary.getInstance(dllPath);
            lib.dispose();
        }

        File dllFile = new File(dllPath);
        if(dllFile.exists()){
            boolean isDeleted = dllFile.delete();
            if(!isDeleted){
                System.out.println("Unable to delete dll file, since it hold by jvm");
            }
        }

    }

    private interface ExtDLLTool extends Library {
        String validateNomination(String dloadProps);
    }
}

添加延迟后的测试代码

为给本地代码时间释放句柄,添加了延迟:

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;

class Filter {

    private static ExtDLLTool DLLUtil;
    final private static String dllPath = "./ExternalDownloader_64.dll";

    static {
        DLLUtil = (ExtDLLTool) Native.loadLibrary(dllPath, ExtDLLTool.class);
    }

    public static void main(String[] args) throws Exception{

        if (DLLUtil != null) {
            DLLUtil = null;
            NativeLibrary lib = NativeLibrary.getInstance(dllPath);
            lib.dispose();
            Thread.sleep(3000);
        }

        File dllFile = new File(dllPath);
        if(dllFile.exists()){
            Files.delete(Paths.get(dllPath));
            // boolean isDeleted = dllFile.delete();
            if(dllFile.exists()){
                System.out.println("Unable to delete dll file, since it hold by jvm");
            }
        }
    }

    private interface ExtDLLTool extends Library {
        String validateNomination(String dloadProps);
    }
}

运行异常

运行上述代码均抛出异常,说明JVM未释放文件:

Exception in thread "main" java.nio.file.AccessDeniedException: .\ExternalDownloader_64.dll at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102) at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)

解决方案
  • 强制触发垃圾回收
    调用dispose()后,除了置空引用,显式触发GC能加快隐式引用的回收。在dispose()后添加:

    System.gc();
    System.runFinalization();
    

    配合延迟使用,能提升文件释放的概率。

  • 避免静态加载DLL
    静态代码块加载的DLL会绑定到类加载器,类加载器未卸载时DLL句柄不会释放。改成方法内动态加载,让引用更快被回收:

    public static void main(String[] args) throws Exception {
        ExtDLLTool dllUtil = Native.loadLibrary(dllPath, ExtDLLTool.class);
        // 执行DLL调用逻辑
        dllUtil = null;
        NativeLibrary lib = NativeLibrary.getInstance(dllPath);
        lib.dispose();
        System.gc();
        System.runFinalization();
        Thread.sleep(1000);
        // 尝试删除文件
    }
    
  • 检查DLL内部资源泄漏
    可能不是JNA的问题,而是DLL自身打开了文件句柄或其他资源未释放。确认DLL是否有资源释放的导出函数,调用该函数后再尝试删除文件。

  • 临时目录加载策略
    先把DLL复制到临时目录,加载临时目录的DLL文件,这样原文件从一开始就不会被锁定。使用完成后直接删除临时DLL即可。

内容的提问来源于stack exchange,提问作者Naveen S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:30:16