英文:
JNA does not work on safe mode without networking, GetIfTable failed
问题
我在IntelliJ上创建了一个新的Maven项目,并将以下代码添加到主类:
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Advapi32;
import com.sun.jna.platform.win32.Winsvc;
public class Main {
public static void main(String[] args) throws InterruptedException {
registerHandler();
System.out.println(1);
Thread.sleep(60000);
}
public static void registerHandler(){
Winsvc.SERVICE_STATUS_HANDLE service_status_handle = Advapi32.INSTANCE.RegisterServiceCtrlHandlerEx("hvldlpxpa", new Winsvc.HandlerEx() {
@Override
public int callback(int i, int i1, Pointer pointer, Pointer pointer1) {
return i;
}
}, Pointer.NULL);
}
public static void stopService(String[] args) throws Exception {
System.exit(0);
}
}
Maven配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>jnaReg</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.12.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>Main</mainClass>
</manifest>
</archive>
<finalName>JNA</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>
在命令行中执行以下命令:
setlocal
set JARS="C:\Users\bunsal\Downloads\JNA-jar-with-dependencies.jar"
set MAINCLASS=Main
java.exe -cp %JARS% %MAINCLASS%
endlocal
在安全模式下(最小配置)运行时出现以下错误:
Exception in thread "main" java.lang.Error: IP Helper Library GetIfTable function failed
...
在带网络功能的安全模式下,程序正常工作(输出1并休眠60秒)。 Winapi文档提供的帮助有限。我还在GitHub上搜索了JNA的问题。
关于问题的完整信息:
-
JNA及相关JAR文件的版本为5.12.1。
-
Java虚拟机的版本和供应商为Oracle,1.8.0_251。
-
操作系统为Windows 10 Build 19041。
-
系统架构(CPU类型,JVM的位数)为64位。
-
问题的完整描述已经在上文提到。
-
重现问题的步骤已经在上文提到。
英文:
I created new Maven project on intellij. Added this code to main:
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Advapi32;
import com.sun.jna.platform.win32.Winsvc;
public class Main {
public static void main(String[] args) throws InterruptedException {
registerHandler();
System.out.println(1);
Thread.sleep(60000);
}
public static void registerHandler(){
Winsvc.SERVICE_STATUS_HANDLE service_status_handle = Advapi32.INSTANCE.RegisterServiceCtrlHandlerEx("hvldlpxpa", new Winsvc.HandlerEx() {
@Override
public int callback(int i, int i1, Pointer pointer, Pointer pointer1) {
return i;
}
}, Pointer.NULL);
}
public static void stopService(String[] args) throws Exception {
System.exit(0);
}
}
MAVEN FILE:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>jnaReg</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.12.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>Main</mainClass>
</manifest>
</archive>
<finalName>JNA</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>
Executed with:
setlocal
set JARS="C:\Users\bunsal\Downloads\JNA-jar-with-dependencies.jar"
set MAINCLASS=Main
java.exe -cp %JARS% %MAINCLASS%
endlocal
Booted into safe mode minimal. This error happens:
Exception in thread "main" java.lang.Error: IP Helper Library GetIfTable function failed
at java.net.NetworkInterface.getAll(Native Method)
at java.net.NetworkInterface.getNetworkInterfaces(NetworkInterface.java:355)
at sun.security.provider.SeedGenerator.addNetworkAdapterInfo(SeedGenerator.java:233)
at sun.security.provider.SeedGenerator.access$000(SeedGenerator.java:80)
at sun.security.provider.SeedGenerator$1.run(SeedGenerator.java:183)
at sun.security.provider.SeedGenerator$1.run(SeedGenerator.java:168)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.provider.SeedGenerator.getSystemEntropy(SeedGenerator.java:168)
at sun.security.provider.SecureRandom$SeederHolder.<clinit>(SecureRandom.java:201)
at sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:221)
at java.security.SecureRandom.nextBytes(SecureRandom.java:468)
at java.security.SecureRandom.next(SecureRandom.java:491)
at java.util.Random.nextLong(Random.java:424)
at java.io.File$TempDirectory.generateFile(File.java:1905)
at java.io.File.createTempFile(File.java:2010)
at com.sun.jna.Native.extractFromResourcePath(Native.java:1174)
at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:1036)
at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:1015)
at com.sun.jna.Native.<clinit>(Native.java:221)
at com.sun.jna.platform.win32.Advapi32.<clinit>(Advapi32.java:70)
at Main.registerHandler(Main.java:11)
at Main.main(Main.java:6)
In safe mode with networking it works perfectly (outputs 1 and sleeps for 60 seconds). Winapi docs does not provide much help. I also searched on jna issues on GitHub.
Provide complete information about the problem
-
Version of JNA and related jars 5.12.1
-
Version and vendor of the Java virtual machine Oracle, 1.8.0_251
-
Operating system Windows 10 Build 19041
-
System architecture (CPU type, bitness of the JVM) 64 bit
-
Complete description of the problem -> Already discussed
-
Steps to reproduce -> Already discussed
答案1
得分: 2
出现错误的原因是JNA将其本机库提取到临时目录并使用JDK的方法来创建一个随机命名的临时文件,其中内部调用了随机数生成器。
然而,bug 不在 JNA 中,而是在 JDK 的 java.io.File.createTempFile()
方法中,如堆栈跟踪中所示。
根本问题是JDK 8 中引入的 bug,JDK-8066931:
在 Azure 上运行 Java 网站时,您无法访问网络接口。自从 http://hg.openjdk.java.net/jdk8u/jdk8u20/jdk/rev/c6836440c427 开始,SecureRandom 的工作方式是将网络地址添加到种子哈希中,这会导致在部署到 Azure 时应用程序无法正常工作。由于没有很多应用程序使用 SecureRandom 类,它们无法在当前 JDK 版本下用作 Azure 网站。
这个问题在 JDK18 中得到修复,通过JDK-8275319中更好的异常处理。
解决此问题的选项:
- 升级到 JDK 18 或更新版本。看起来修复未被回溯到较早的 JDK 版本。
- 预先提取 JNA 本机库(jnidispatch)到您选择的位置,并通过
jna.boot.library.path
参数将 JNA 指向它,或将其放入系统库路径。参见概述中的“加载 JNA”部分。 - 确保至少有一个网络接口。
或者,您可以尝试使用更新版本的 JDK 进行实验;虽然根本原因可能直到 JDK 18 才得以修复,但在临时文件生成中可能已经使用了其他方法来解决这个已知问题。
您使用的 JDK 8 版本发布了将近 3 年,自那时以来已经有 4 个 Oracle 主动支持版本(最高版本为 291),如果您受限于使用 Oracle 的 JDK,则有安全支持版本高达 361。
英文:
The error occurs when JNA is extracting its native library to a temporary directory and uses the JDK’s methods for creating a randomly named temporary file, which internally invokes the
random number generator.
However, the bug is not in JNA, it's in the JDK's java.io.File.createTempFile()
method as shown in the stack trace.
The root problem is a bug in the JDK introduced in jdk8, JDK-8066931:
> When running a Java website on Azure you don't have access to the network interfaces. Since http://hg.openjdk.java.net/jdk8u/jdk8u20/jdk/rev/c6836440c427 the way SecureRandom works is to add the network addresses to the seed hash which causes the application to not work when deployed on Azure. Because no a lot of applications use the SecureRandom class they cannot be used as an Azure web site with the current JDK version.
It was fixed in JDK18 with better exception handling in JDK-8275319.
Your options to resolve this:
- Upgrade to JDK 18 or newer. It does not look like the fix has been backported to earlier JDKs.
- Pre-extract the JNA native library (jnidispatch) to a location of your choice and point JNA to it via
jna.boot.library.path
parameter, or put it in your system library path. See the "Loading JNA" section of the Overview. - Make sure you have at least one network interface.
Alternately you might experiment with newer versions of the JDK; while the underlying root cause may not have been fixed until JDK 18, there may have been other methods used in temporary file generation that worked around this known issue.
The JDK 8 version you're using was released nearly 3 years ago and there have been 4 Oracle active support releases since then (up to 291) with security support versions up to 361 if you are constrained to using Oracle's JDK.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论