web-dev-qa-db-fra.com

Comment déterminez-vous l'architecture 32 ou 64 bits de Windows en Java?

Comment déterminez-vous l'architecture 32 ou 64 bits de Windows en Java?

53
Matthew

Veuillez noter que la propriété os.Arch ne vous donnera que l'architecture du JRE, pas celle du système d'exploitation sous-jacent. 

Si vous installez un jre 32 bits sur un système 64 bits, System.getProperty("os.Arch") renverra x86

Afin de déterminer l'architecture sous-jacente, vous devrez écrire du code natif. Voir cet article pour plus d'informations (et un lien vers un exemple de code natif)

54
James Van Huis

Je ne fais pas vraiment confiance à la lecture de la variable système os.Arch. Bien que cela fonctionne si un utilisateur exécute une machine virtuelle Java 64 bits sur un système 64 bits. Cela ne fonctionne pas si l'utilisateur exécute une machine virtuelle Java 32 bits sur un système 64 bits.

Le code suivant permet de détecter correctement les systèmes d'exploitation Windows 64 bits. Sur un système Windows 64 bits, la variable d'environnement "Programfiles (x86)" sera définie. Il ne sera PAS défini sur un système 32 bits et Java le lira comme nul.

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

Pour d'autres systèmes d'exploitation tels que Linux ou Solaris ou Mac, nous pouvons également rencontrer ce problème. Donc, ce n'est pas une solution complète. Pour mac, vous êtes probablement en sécurité car Apple verrouille la machine virtuelle Java pour correspondre au système d'exploitation. Mais Linux et Solaris, etc. peuvent toujours utiliser une JVM 32 bits sur leur système 64 bits. Alors utilisez ceci avec prudence.

72
Boolean

J'ai utilisé la commande Invite (commande -> wmic OS get OSArchitecture) pour obtenir l'architecture OS. Le programme suivant aide à obtenir tous les paramètres requis:

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

    }

}
5
Crusaderpyro

(Seulement pour Windows) Vérifiez si C:\Windows\SysWOW64 Existe .. Si le répertoire existe, il s’agit d’un processus 64 bits . Sinon, c’est un processus 32 bits.

0
Olligaming1107

Peut-être que ce n'est pas la meilleure façon, mais ça marche. 

Tout ce que je fais est d'obtenir la "variable d'environnement" que Windows a configurée pour le dossier Program Files x86. Je veux dire que Windows x64 a le dossier (Program Files x86) et le x86 non. Puisqu'un utilisateur peut changer le chemin du programme dans Enviroment Variables, ou créer un répertoire "Program Files (x86)" dans C: \, je n'utiliserai pas la détection du dossier mais le "Chemin de l'environnement" de "Programme Fichiers (x86) "avec la variable dans le registre 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);

    }

}
0
Blackgeo32

Clause de non-responsabilité: veuillez ne pas sous-estimer cette réponse en double, car je souhaitais partager ma solution de code Java avec celle-ci (celle-ci étant un code natif).

J'aimerais ajouter à la réponse de M. James Van Huis: Puisque la propriété os.Arch: System.getProperty("os.Arch"); Renvoie le nombre de bits de JRE, cela peut en fait être très utile. 

Dans votre code, vous devez d'abord vérifier la taille de IntPtr. S'il renvoie 8, vous utilisez un système d'exploitation 64 bits. S'il renvoie 4, vous exécutez une application 32 bits. Vous devez donc maintenant savoir si vous vous exécutez en mode natif ou sous WOW64.

Par conséquent, la vérification de la taille IntPtr est la même vérification que vous effectuez en regardant le "os.Arch". Ensuite, vous pouvez déterminer si le processus s'exécute de manière native ou sous WOW64.

Cela peut être fait en utilisant la bibliothèque jna (par exemple NativeLibrary ) qui offre l’utilisation des fonctions natives dont vous avez besoin.

//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

}

Quelque chose comme cela pourrait également fonctionner, mais je recommanderais la première version, car c'est celle que j'ai testée sur JRE x64 et 32 ​​bits sur un système d'exploitation x64. Cela devrait également être le moyen le plus sûr car, dans la suite, vous ne vérifiez pas si la fonction "IsWow64Process" existe ou non.

J'ajoute ici un exemple de vérification JRE, pour que ce soit complet, même si ce n'est pas difficile à trouver.

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

Vous pouvez essayer ce code, je pense qu'il est préférable de détecter le modèle de JVM

boolean is64bit = System.getProperty("Sun.Arch.data.model").contains("64");
0
user2181778