【问题标题】:How do you determine 32 or 64 bit architecture of Windows using Java?您如何使用 Java 确定 Windows 的 32 位或 64 位体系结构?
【发布时间】:2010-12-23 19:34:49
【问题描述】:

您如何使用 Java 确定 Windows 的 32 位或 64 位体系结构?

【问题讨论】:

  • 你为什么想知道这个? Java 应该在任何有 JVM 的操作系统上运行相同 - 你的 Java 程序不应该关心它是在 32 位还是 64 位操作系统上运行。
  • @Jesper 因为多次运行 java 并不是唯一的目的。很多时候,您可能已经开发了一个应该专门在 64 位机器(或 32 位机器)上运行的程序/应用程序(原因可以是任何东西)。在这样的地方,我需要检查存在什么版本的 Windows 架构..
  • @Jesper 另一种区分 32 位或 64 位操作系统至关重要的情况是,当 Java 程序必须启动外部可执行文件时,两个版本都存在。就像编写 Selenium 测试一样,必须启动正确的浏览器驱动程序。识别操作系统本身也存在同样的需求。我敢肯定,人们还可以想到其他几种情况,其中应该“抽象掉”的东西不是。
  • @Jesper 你说的:应该

标签: java windows x86 64-bit


【解决方案1】:

您可以从命令行获取“真正的”操作系统架构。 您可以使用“wmic cpu get AddressWidth”。

如果你想要处理器拱门,你可以使用“wmic cpu get DataWidth

我写了一个简单的java静态代码来试试这个。

免责声明:如果您想重复使用此代码,则需要使用 ProcessBuilder)

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();
}

【讨论】:

    【解决方案2】:

    我想分享我的 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 操作系统上的 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);
    }
    

    【讨论】:

      【解决方案3】:

      请注意,os.arch 属性只会为您提供 JRE 的架构,而不是底层操作系统的架构。

      如果在 64 位系统上安装 32 位 jre,System.getProperty("os.arch") 将返回 x86

      为了真正确定底层架构,您需要编写一些本机代码。请参阅this post 了解更多信息(以及示例本机代码的链接)

      【讨论】:

        【解决方案4】:

        (仅适用于 Windows)检查是否 C:\Windows\SysWOW64 存在。 如果该目录存在,则它是一个 64 位进程。 否则,它是一个 32 位进程。

        【讨论】:

          【解决方案5】:

          我使用命令提示符(command --> 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();
          
              }
          
          }
          

          【讨论】:

            【解决方案6】:

            也许这不是最好的方法,但它确实有效。

            我所做的只是获取 Windows 为 Program Files x86 文件夹配置的“环境变量”。我的意思是 Windows x64 有文件夹 (Program Files x86) 而 x86 没有。因为用户可以更改Enviroment Variables中的Program Files路径,或者他/她可能在C:\中创建一个目录“Program Files(x86)”,所以我不会使用文件夹的检测而是使用“环境路径” "Program Files (x86)" 与 windows 注册表中的变量。

            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);
            
                }
            
            }
            

            【讨论】:

            • 好吧,用户 Boolean 已经采用了相同的方式,但代码更好。
            【解决方案7】:

            你可以试试这段代码,我觉得检测JVM的型号比较好

            boolean is64bit = System.getProperty("sun.arch.data.model").contains("64");
            

            【讨论】:

            • OP 询问的是操作系统而不是 JVM
            • 不工作,在 Windows 10 (64bit) 和 Java 8 32bit 上检查。
            • 它可以工作,也可以不工作;在某些操作系统中,此键不存在。检查stackoverflow.com/questions/807263/…,投票最多的答案。在我的 Win10 中它存在。
            【解决方案8】:

            我不完全相信阅读 os.arch 系统变量。如果用户在 64 位系统上运行 64 位 JVM,则它可以工作。如果用户在 64 位系统上运行 32 位 JVM,则它不起作用。

            以下代码适用于正确检测 Windows 64 位操作系统。在 Windows 64 位系统上,环境变量 将设置“程序文件(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 相同) .
            • +1 经过大量研究后,我将使用它。但我很好奇,在这台机器(Windows 8.1 64 位)上,环境变量 ProgramFiles(x86) 未列在“这台电脑”/属性/高级系统设置/环境变量下,但 System.getenv("ProgramFiles(x86)") 确实返回值 C:\Program Files (x86) ,这当然很棒,因为听起来这样的变量不能被用户修改或删除;是这样吗? ProgramFiles(x86) 是某种“内部”环境变量吗?
            【解决方案9】:

            您可以使用系统属性中的 os.arch 属性来查找。

            Properties pr = System.getProperties();
            System.out.println(pr.getProperty("os.arch"));
            

            如果你是 32 位的,它应该显示 i386 或其他东西

            【讨论】:

            • 在运行 32 位 JVM 的 64 位操作系统上,这将返回 x86,表示 32 位。虽然这对于 JVM 是正确的,但对于操作系统来说是错误的,这是 OP 所要求的。
            【解决方案10】:
            System.getProperty("os.arch");
            

            【讨论】:

            • 在 64b 窗口上,但在 32b jvm 上它为我打印“x86”。所以我猜它并没有说系统的版本,而是说虚拟机。
            猜你喜欢
            • 1970-01-01
            • 2011-03-11
            • 2010-09-16
            • 2012-10-26
            • 2021-11-25
            • 2013-12-14
            • 2019-01-07
            • 2013-10-17
            • 2011-10-24
            相关资源
            最近更新 更多