如何使用Java确定Windows的32位还是64位架构?
如何使用Java确定Windows的32位还是64位架构?
我不太信任读取os.arch系统变量。虽然它可以在用户在64位系统上运行64位JVM时正常工作,但如果用户在64位系统上运行32位JVM,则无法正常工作。
下面的代码可以正确检测Windows 64位操作系统。在Windows 64位系统上,“Programfiles(x86)”环境变量将被设置。但在32位系统上不会设置该变量,Java 将其读取为 null。
boolean is64bit = false;
if (System.getProperty("os.name").contains("Windows")) {
is64bit = (System.getenv("ProgramFiles(x86)") != null);
} else {
is64bit = (System.getProperty("os.arch").indexOf("64") != -1);
}
对于像Linux、Solaris或Mac这样的其他操作系统,我们也可能会遇到这个问题。因此这并不是完整的解决方案。对于Mac来说,你可能是安全的,因为苹果将JVM锁定以匹配操作系统。但是Linux和Solaris等操作系统在64位系统上仍然可能使用32位JVM,因此请谨慎使用。
os.arch
系统变量。这种行为的原因是,例如对于 JNI 来说,了解 JVM 的架构非常重要,而不是底层操作系统(如果您需要将自己的平台相关共享库加载到 Java 代码中,则它们需要与 JVM 相同的架构)。 - pevikProgramFiles(x86)
没有列在“This PC” / 属性/高级系统设置/环境变量下,然而System.getenv("ProgramFiles(x86)")
确实返回值C:\Program Files (x86)
,这当然很好,因为看起来这样的变量不能被用户修改或删除;是这样吗? ProgramFiles(x86)
是某种“内部”的环境变量吗?答案:+1 经过相当多的研究,我将使用此方法。但我很好奇,对于这台机器(Windows 8.1 64位),环境变量ProgramFiles(x86)
未列在“This PC” / 属性/高级系统设置/环境变量中,但是System.getenv("ProgramFiles(x86)")
却可以返回值C:\Program Files (x86)
,这当然很好,因为看起来这个变量不能被用户修改或删除;是这样吗? ProgramFiles(x86)
是一种“内部”的环境变量吗? - SantiBailors%Windir%\SysWOW64
(表示 64 位进程)和 %Windir%\Sysnative
(表示在 64 位 Windows 中运行的 32 位进程)的存在。 - phuclv请注意,os.arch
属性只会给出JRE的架构,而不是底层操作系统的架构。
如果在64位系统上安装了32位的jre,则System.getProperty("os.arch")
将返回x86
为了实际确定底层架构,您需要编写一些本地代码。请参阅此文章获取更多信息(以及示例本地代码的链接)。
我使用命令提示符 (命令 --> wmic OS get OSArchitecture) 来获取操作系统架构。以下程序可以帮助获取所有必需的参数:
import java.io.*;
public class User {
public static void main(String[] args) throws Exception {
System.out.println("OS --> "+System.getProperty("os.name")); //OS Name such as Windows/Linux
System.out.println("JRE Architecture --> "+System.getProperty("sun.arch.data.model")+" bit."); // JRE architecture i.e 64 bit or 32 bit JRE
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe", "/c","wmic OS get OSArchitecture");
builder.redirectErrorStream(true);
Process p = builder.start();
String result = getStringFromInputStream(p.getInputStream());
if(result.contains("64"))
System.out.println("OS Architecture --> is 64 bit"); //The OS Architecture
else
System.out.println("OS Architecture --> is 32 bit");
}
private static String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
我想分享一下我的Java代码解决方案(一个类似的是本机代码)。
我想要补充一下James Van Huis先生的答案。由于属性os.arch System.getProperty("os.arch")
返回JRE的位数,因此这实际上非常有用。从文章中可以看到:
在您的代码中,您首先需要检查IntPtr的大小,如果返回8,则正在运行64位操作系统。如果返回4,则运行32位应用程序,现在您需要知道是否在WOW64下运行。
因此,IntPtr大小检查与查看"os.arch"执行的相同检查相同。之后,您可以继续找出进程是在本机环境下运行还是在WOW64下运行。
这可以使用jna库(例如NativeLibrary)来完成,该库提供了所需的本机函数的使用。
//test the JRE here by checking the os.arch property
//go into the try block if JRE is 32bit
try {
NativeLibrary kernel32Library = NativeLibrary.getInstance("kernel32");
Function isWow64Function = kernel32Library.getFunction("IsWow64Process");
WinNT.HANDLE hProcess = Kernel32.INSTANCE.GetCurrentProcess();
IntByReference isWow64 = new IntByReference(0);
Boolean returnType = false;
Object[] inArgs = {
hProcess,
isWow64
};
if ((Boolean) isWow64Function.invoke(returnType.getClass(), inArgs)) {
if (isWow64.getValue() == 1) {
//32bit JRE on x64OS
}
}
} catch (UnsatisfiedLinkError e) { //thrown by getFunction
}
类似这样的代码也可能会起作用,但我建议使用第一种版本,因为我在x64和32位JRE上测试过,而且应该更加安全,因为以下代码实际上没有检查“IsWow64Process”函数是否存在。
这里我添加了一个JRE检查的示例,以便完整,尽管很容易找到。
Map<String, Integer> archMap = new HashMap<String, Integer>();
archMap.put("x86", 32);
archMap.put("i386", 32);
archMap.put("i486", 32);
archMap.put("i586", 32);
archMap.put("i686", 32);
archMap.put("x86_64", 64);
archMap.put("amd64", 64);
//archMap.put("powerpc", 3);
this.arch = archMap.get(SystemUtils.OS_ARCH);
if (this.arch == null) {
throw new IllegalArgumentException("Unknown architecture " + SystemUtils.OS_ARCH);
}
(仅适用于Windows) 检查 C:\Windows\SysWOW64 是否存在。如果该目录存在,则是64位进程。否则,它是32位进程。
你可以通过命令行获取“真实”的操作系统架构。 你可以使用“wmic cpu get AddressWidth”命令。
如果你想要处理器架构,可以使用"wmic cpu get DataWidth"。public static String getOsArch() {
String arch = null;
try {
arch = HotUtils.executeCmd("wmic cpu get AddressWidth");
arch = arch.trim();
arch = arch.replace("\n\n", "\n");
arch = arch.replace(" ", "");
arch = arch.trim();
return arch.endsWith("64")? "64": "32";
} catch (IOException ex) {
Logger.getLogger(HotUtils.class.getName()).log(Level.SEVERE, null, ex);
}
return arch;
}
public static void main(String[] args) {
System.out.println(HotUtils.getOsArch());
}
public static String executeCmd(String cmd) throws IOException {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
StringBuilder out = new StringBuilder();
String s;
while ((s = stdInput.readLine()) != null) {
out.append(s);
}
while ((s = stdError.readLine()) != null) {
out.append(s);
}
return out.toString();
}
也许这不是最好的方法,但它能够工作。
我所做的就是获取Windows为Program Files x86文件夹配置的"环境变量"。我的意思是,Windows x64有文件夹(Program Files x86),而x86没有。因为用户可以在"环境变量"中更改Program Files路径,或者他/她可能在C:\中创建一个名为"Program Files (x86)"的目录,所以我不会使用检测文件夹而是使用Windows注册表中"Program Files (x86)"的"环境路径"变量。
public class getSystemInfo {
static void suckOsInfo(){
// Get OS Name (Like: Windows 7, Windows 8, Windows XP, etc.)
String osVersion = System.getProperty("os.name");
System.out.print(osVersion);
String pFilesX86 = System.getenv("ProgramFiles(X86)");
if (pFilesX86 !=(null)){
// Put here the code to execute when Windows x64 are Detected
System.out.println(" 64bit");
}
else{
// Put here the code to execute when Windows x32 are Detected
System.out.println(" 32bit");
}
System.out.println("Now getSystemInfo class will EXIT");
System.exit(0);
}
}
你可以尝试这段代码,我认为检测JVM的型号会更好一些。
boolean is64bit = System.getProperty("sun.arch.data.model").contains("64");
System.getProperty("os.arch");
Properties pr = System.getProperties();
System.out.println(pr.getProperty("os.arch"));
如果您使用的是32位系统,应该会显示i386或类似的内容。