Как определить, какой тип JRE установлен - 32-битный или 64-битный - PullRequest
49 голосов
/ 30 апреля 2009

Во время установки с помощью установщика NSIS мне нужно проверить, какая JRE (32-битная или 64-битная версия) установлена ​​в системе. Я уже знаю, что могу проверить системное свойство "sun.arch.data.model", но это зависит от Солнца. Мне интересно, есть ли стандартное решение для этого.

Ответы [ 9 ]

48 голосов
/ 30 апреля 2009

Используемую архитектуру JVM можно получить с помощью свойства " os.arch ":

System.getProperty("os.arch");

Часть "os" кажется немного неправильной, или, возможно, оригинальные дизайнеры не ожидали, что JVM будут работать на архитектурах, для которых они не были написаны. Возвращаемые значения кажутся несовместимыми .

Команда установщика NetBeans решает проблему архитектуры JVM против ОС. Цитата:

x64 бит: Java и система

Отслеживается как Выпуск 143434 .

В настоящее время мы используем x64 бит JVM для определить, если система (и, следовательно, Platform.getHardwareArch ()) является 64-разрядным или нет. Это определенно неправильно, так как можно запустить 32-битную JVM на 64-битная система. Мы должны найти Решение для проверки ОС на реальную 64-битность в случае работы на 32-битной JVM.

  • для Windows это можно сделать с помощью WindowsRegistry.IsWow64Process ()
  • для Linux - отметив 'uname -m / -p' == x86_64
  • для Solaris это можно сделать, например, с помощью 'isainfo -b'
  • для Mac OSX это нельзя сделать с помощью аргументов uname, возможно, это может быть решается созданием 64-битного двоичного файла и выполнение на платформе ... (к сожалению, это не работает :( Я создал двоичный файл только с x86_64 и арка ppc64, и это было успешно казненный на тигре ..)
  • для поддержки Generic Unix - это тоже не ясно ... скорее всего, проверка для того же 'uname -m / -p' / 'getconf LONG_BIT 'и сравнивая его с некоторыми возможные 64-битные значения (x86_64, x64, amd64, ia64).

Примеры свойств из разных JVM, работающих на 64-битной Ubuntu 8.0.4:

32bit IBM 1.5:

java.vendor=IBM Corporation
java.vendor.url=http://www.ibm.com/
java.version=1.5.0
java.vm.info=J2RE 1.5.0 IBM J9 2.3 Linux x86-32 j9vmxi3223-20061001 (JIT enabled)
J9VM - 20060915_08260_lHdSMR
JIT  - 20060908_1811_r8
GC   - 20060906_AA
java.vm.name=IBM J9 VM
java.vm.specification.name=Java Virtual Machine Specification
java.vm.specification.vendor=Sun Microsystems Inc.
java.vm.specification.version=1.0
java.vm.vendor=IBM Corporation
java.vm.version=2.3
os.arch=x86
os.name=Linux
os.version=2.6.24-23-generic
sun.arch.data.model=32

64bit Sun 1.6:

java.vendor=Sun Microsystems Inc.
java.vendor.url=http://java.sun.com/
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport.cgi
java.version=1.6.0_05
java.vm.info=mixed mode
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vm.specification.name=Java Virtual Machine Specification
java.vm.specification.vendor=Sun Microsystems Inc.
java.vm.specification.version=1.0
java.vm.vendor=Sun Microsystems Inc.
java.vm.version=10.0-b19
os.arch=amd64
os.name=Linux
os.version=2.6.24-23-generic
sun.arch.data.model=64

64bit GNU 1.5:

java.vendor=Free Software Foundation, Inc.
java.vendor.url=http://gcc.gnu.org/java/
java.version=1.5.0
java.vm.info=GNU libgcj 4.2.4 (Ubuntu 4.2.4-1ubuntu3)
java.vm.name=GNU libgcj
java.vm.specification.name=Java(tm) Virtual Machine Specification
java.vm.specification.vendor=Sun Microsystems Inc.
java.vm.specification.version=1.0
java.vm.vendor=Free Software Foundation, Inc.
java.vm.version=4.2.4 (Ubuntu 4.2.4-1ubuntu3)
os.arch=x86_64
os.name=Linux
os.version=2.6.24-23-generic

(GNU-версия не сообщает о свойстве «sun.arch.data.model»; предположительно, другие JVM тоже этого не делают)

7 голосов
/ 09 ноября 2010

Я использую NSIS и Launch4j, чтобы обернуть приложение Java Desktop. Так что мне нужно не только обнаружить какой-либо JRE, но и тот, который Launch4j найдет с его алгоритмом поиска. Единственный подход, который имеет смысл - это запустить короткую Java-программу в установщике NSIS. Вот Java:


    public class DetectJVM {
        private static final String keys [] = {
            "sun.arch.data.model",
            "com.ibm.vm.bitmode",
            "os.arch",
        };
        public static void main (String [] args) {
            boolean print = args.length > 0 && "-print".equals(args[0]);
            for (String key : keys ) {
                String property = System.getProperty(key);
                if (print) System.out.println(key + "=" + property);
                if (property != null) {
                    int errCode = (property.indexOf("64") >= 0) ? 64 : 32;
                    if (print) System.out.println("err code=" + errCode);
                    System.exit(errCode);
                }
            }
        }
    }

Оберните это с Launch4J. Используйте тип заголовка GUI, но также установите значение true. В противном случае код ошибки будет утерян. (Я включил все это в мой скрипт сборки Netbeans Ant.

Вот соответствующий код NSIS, который его использует:


File ... ; unpack files including detectjvm.exe.
ClearErrors
ExecWait '"$INSTDIR\detectjvm.exe"' $0
IfErrors DetectExecError
IntCmp $0 0 DetectError DetectError DoneDetect
DetectExecError:
    StrCpy $0 "exec error"
DetectError:
    MessageBox MB_OK "Could not determine JVM architecture ($0). Assuming 32-bit."
    Goto NotX64
DoneDetect:
IntCmp $0 64 X64 NotX64 NotX64
X64:
    File  ... 64-bit AMD DLLs.
    Goto DoneX64
NotX64:
    File ... 32-bit x86 DLLs.
DoneX64:
Delete $INSTDIR\detectjvm.exe

Это прекрасно работает на очень большом количестве машин от WinXP без SP до Vista и Win7 со всеми SP, 32- и 64-разрядными.

Обратите внимание, что в моем сценарии NSIS я использую существующий пакет, который проверяет, установлена ​​ли JVM, и делает ли это в первую очередь, поэтому 32-разрядный выбор по умолчанию будет происходить только в том случае, если что-то пошло не так с установкой JVM, в этом случае набор копируемых вами DLL-файлов в любом случае не будет иметь значения.

Надеюсь, это кому-нибудь пригодится.

4 голосов
/ 15 января 2011

Когда я пишу код Java, как различить 32- и 64-битные операции?

http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#64bit_detection

Нет общедоступного API, позволяющего различать 32 и 64-битная операция. Думайте о 64-битном как о еще одной платформе в пиши один раз, беги куда угодно, традиция. Тем не менее, если вы хотите написать код, который зависит от платформы (позор вам), системное свойство sun.arch.data.model имеет значение «32», «64» или «неизвестно».

1 голос
/ 13 октября 2009
import sun.misc.*;

import java.lang.reflect.*;

public class UnsafeTest {
  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
    unsafeField.setAccessible(true);
    Unsafe unsafe = (Unsafe) unsafeField.get(null);
    System.out.println(unsafe.addressSize());
  }
}
0 голосов
/ 24 мая 2016
java -version

Для 64-битной версии Java будет напечатано:

java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) ***64-Bit*** Server VM (build 25.92-b14, mixed mode)

Для 32 бит это будет просто

java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) Client VM (build 25.92-b14, mixed mode)
0 голосов
/ 15 февраля 2016

Если у вас есть путь к .exe, который вы хотите проверить, вы можете использовать этот ответ . По сути, он просто просматривает заголовки в файле .exe и сообщает, является ли он 64- или 32-разрядным в Windows.

0 голосов
/ 04 июня 2009

Следующий код проверяет поле machineType в любом исполняемом файле Windows, чтобы определить, является ли оно 32- или 64-битным:

public class ExeDetect
{
  public static void main(String[] args) throws Exception {
    File x64 = new File("C:/Program Files/Java/jre1.6.0_04/bin/java.exe");
    File x86 = new File("C:/Program Files (x86)/Java/jre1.6.0/bin/java.exe");
    System.out.println(is64Bit(x64));
    System.out.println(is64Bit(x86));
  }

  public static boolean is64Bit(File exe) throws IOException {
    InputStream is = new FileInputStream(exe);
    int magic = is.read() | is.read() << 8;
    if(magic != 0x5A4D) 
        throw new IOException("Invalid Exe");
    for(int i = 0; i < 58; i++) is.read(); // skip until pe offset
    int address = is.read() | is.read() << 8 | 
         is.read() << 16 | is.read() << 24;
    for(int i = 0; i < address - 60; i++) is.read(); // skip until pe header+4
    int machineType = is.read() | is.read() << 8;
    return machineType == 0x8664;
  }
}

Обратите внимание, что код был сжат для краткости ...

0 голосов
/ 01 мая 2009

В системе могут быть доступны как 32-разрядные, так и 64-разрядные JVM, и их множество.

Если у вас уже есть dll для каждой поддерживаемой платформы - рассмотрите возможность создания небольшого исполняемого файла, который связывает и запускает, чтобы вы могли проверить, поддерживает ли платформа определенную функциональность. Если исполняемые файлы запускаются и запускаются, вы можете установить соответствующие общие библиотеки.

0 голосов
/ 30 апреля 2009

В Linux мой (java) vm сообщает java.vm.name = Java HotSpot (TM) 64-битная виртуальная машина сервера. Javadocs для System объявляет, что System.getProperty всегда будет иметь значение для этого, но ничего не говорит о sun.arch.data.model.

К сожалению, они не указывают, каким будет системное свойство, поэтому некоторые другие JVM могут просто сообщить java.vm.name = Edgar.

Кстати, под "установленным в системе" я предполагаю, что вы имеете в виду "текущая работающая JVM"?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...