Search code examples
javaeclipsejunitwindows-10jna

JNA failing to load, UnsatisfiedLinkError, "Access Denied"


There are several similar questions, but I fear mine is different enough to be distinct. I am in windows 10 64-bit, using Eclipse 4.11 with OpenJDK 11, and am not using an admin account.

When I run our suite of JUnit 5 tests on an internal project, I get an exception:

java.lang.UnsatisfiedLinkError: C:\Users\myUserName\AppData\Local\Temp\jna-762579935\jna18359705168434975905.dll: Access is denied
    at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
    at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2430)
    at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2487)
    at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2684)
    at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2617)
    at java.base/java.lang.Runtime.load0(Runtime.java:767)
    at java.base/java.lang.System.load(System.java:1831)
    at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:1018)
    at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:988)
    at com.sun.jna.Native.<clinit>(Native.java:195)
    at org.stuff.injury.orca.jna.OrcaJNAWrapper.<clinit>(OrcaJNAWrapper.java:21)
    at org.stuff.injury.orca.OrcaLibraryTest.<clinit>(OrcaLibraryTest.java:21)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:628)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:117)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$invokeBeforeAllMethods$9(ClassTestDescriptor.java:376)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.invokeBeforeAllMethods(ClassTestDescriptor.java:375)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.before(ClassTestDescriptor.java:201)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.before(ClassTestDescriptor.java:77)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:132)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

With a breakpoint in place, I can see that this DLL is there, and I can make copies (read) and rename (not quite full write perms, but still) the file. It's not empty, so the JVM was able to write to it.

Additional Information: I discovered a couple settings intended to help debugging this sort of thing, "jna.debug_load" and "jna.debug_load.jna". Their output wasn't all that illuminating, though it does show that it's trying the right DLL at least:

May 23, 2019 10:58:34 AM com.sun.jna.Native loadNativeDispatchLibrary
INFO: Looking in C:\Users\user.name\AppData\Local\Temp\jnidispatch.dll
May 23, 2019 10:58:34 AM com.sun.jna.Native loadNativeDispatchLibrary
INFO: Trying C:\Users\user.name\AppData\Local\Temp\jnidispatch.dll
May 23, 2019 10:59:18 AM com.sun.jna.Native extractFromResourcePath
INFO: Looking in classpath from jdk.internal.loader.ClassLoaders$AppClassLoader@2aae9190 for /com/sun/jna/win32-x86-64/jnidispatch.dll
May 23, 2019 10:59:18 AM com.sun.jna.Native extractFromResourcePath
INFO: Found library resource at jar:file:/D:/Tools/Java-JDK/openjdk-11+28_windows-x64_bin/jdk-11/lib/jna-5.3.1.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
May 23, 2019 10:59:18 AM com.sun.jna.Native extractFromResourcePath
INFO: Extracting library to C:\Users\user.name\AppData\Local\Temp\jna-762579935\jna7239609079883644065.dll
May 23, 2019 10:59:18 AM com.sun.jna.Native loadNativeDispatchLibraryFromClasspath
INFO: Trying C:\Users\user.name\AppData\Local\Temp\jna-762579935\jna7239609079883644065.dll

So it's definitely pulling the DLL from the appropriate resource. If it were a 32-bit DLL instead of a 64-bit one, I would expect a different error, though this would hardly be the first time I've run into a misleading error message if that is the problem.


Solution

  • Eureka! When I tried the "jna.boot.library.path" setting, I was still inside my own Temp directory. It would appear my system doesn't let DLLs load from temp folders. I do run on a relatively restrictive computer, and that seems like a reasonable precaution one might take.

    So: Extracted the DLL, moved it to a folder not under my user account temp directory, and all is well... Not actually true, I just get a new error, but at least this one is resolved.