Во время установки с помощью установщика NSIS мне нужно проверить, какая JRE (32 бит против 64 бит) установлена в системе. Я уже знаю, что могу проверить системное свойство «sun.arch.data.model
», но это зависит от Sun. Мне интересно, есть ли для этого стандартное решение.Как определить, какой тип JRE установлен - 32 бит против 64 бит
ответ
В Linux, my (java) vm сообщает java.vm.name = Java HotSpot (TM) 64-разрядная серверная VM. Javadocs for System заявляют, что System.getProperty всегда будет иметь значение для этого, но молчат на sun.arch.data.model.
К сожалению, они не указывают, что системное свойство будет таким, чтобы некоторые другие JVM могли просто сообщить java.vm.name = Edgar.
Кстати, «установлен в системе», я предполагаю, что вы имеете в виду «текущая работа JVM»?
Архитектура JVM в использовании можно получить с помощью свойства «os.arch»:
System.getProperty("os.arch");
«ОС» часть, кажется, немного некорректным, или, возможно, оригинальные дизайнеры не ожидали JVMs в работать на архитектурах, для которых они не были написаны. Возвращаемые значения выглядят как inconsistent.
Команда установщика NetBeans: tackling the issue архитектуры JVM и ОС. Цитата:
64 бит: Java и System
Гусеничный как Issue 143434.
В настоящее время мы с помощью x64 бит JVM, чтобы определить, является ли систему (и, таким образом, Platform.getHardwareArch()) является 64-битный или нет. Это определенно неправильно, так как можно запустить 32-битную JVM на 64-битной системе. Мы должны найти решение для проверки подлинности 64-битной ОС в случае работы на 32-разрядной JVM.
- для Windows, это может быть сделано с помощью WindowsRegistry.IsWow64Process()
- для Linux - путем проверки 'uname -m/р' == x86_64
- для Solaris это может быть сделано с помощью, например, «ISAInfo -b»
- для Mac OSX это не может быть сделано с помощью uname аргументы, вероятно, это может быть решена путем создания 64-разрядного двоичного кода и выполнения на платформе ... (к сожалению, это не работа :( Я создал двоичный только с x86_64 и ppc64 арки и это было успешно выполнено на Tiger ..)
- для поддержки Generic Unix - это не ясно, как хорошо ... скорее проверка для того же 'uname -m/-p'/'getconf LONG_BIT' и сравнивая его с некоторыми возможными 64-битными значениями (x86_64, x64, amd64, ia64).
Примеры свойств разных виртуальных машинах все работает на 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 ВС 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 не сообщает о «солнце. arch.data.model ", предположительно другие JVM тоже не являются.)
В системе могут быть как 32-битные, так и 64-битные JVM, и множество из них.
Если у вас уже есть dll для каждой поддерживаемой платформы, рассмотрите возможность создания небольшого исполняемого файла, который соединяется и запускается, чтобы вы могли проверить, поддерживает ли платформа данную функцию. Если исполняемые ссылки и запуск, вы можете установить соответствующие общие библиотеки.
Следующий код проверяет поле в любых Тип машины окон исполняемым, чтобы определить, является ли 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;
}
}
Обратите внимание, что код был уплотнен для краткости ...
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());
}
}
Я использую 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, которые вы копируете, не имеет значения.
Надеюсь, это полезно кому-то.
Это очень полезное решение. Проблема, если, что, если 64-битная машина пользователя не установлена с JVM? Затем скрипт сделает неправильное предположение. –
Обратите внимание, что для моего случая мне нужно сделать его в Console с помощью Launch4J. –
При написании кода Java, как я могу различать 32- и 64-разрядную операцию?
http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#64bit_detection
Там нет общественного API, который позволяет различать между 32 и 64-разрядном режиме. Подумайте о 64-битной, как о другой платформе в , пишите один раз, идите в любую традицию. Однако, если вы хотите написать код , который является специфичным для платформы (стыдно за вас), системное свойство sun.arch.data.model имеет значение «32», «64» или «неизвестно».
Как сказал Thorbjørn Ravn Andersen в другом сообщении, 32-разрядные JVM отлично работают на 64-битных ОС. Используйте свойство sun.arch.data.model, если вы беспокоитесь о ширине бита JVM, а не о битовой ширине операционной системы (при условии, что вы работаете в JVM Hot Spot ...) – billsimons
Проблема с битом не в том, что самого кода java, но из-за оболочки, которую мы отправляем с нашим программным обеспечением. Предполагая следующее: если клиент пытается установить нашу версию 64Bit SW, но у него только 32Bit Java; он должен быть проинформирован ... – user97629
Если у вас есть путь к .exe, который вы хотите проверить, вы можете использовать this answer. В основном он просто смотрит на заголовки в файле .exe и сообщает вам, является ли это 64 или 32 бит в Windows.
Ответ Питера Смита та же самая логика, но сделана правильно – Massimo
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)
Вы можете попробовать в командной строке: java -d64 -version Если это не 64-разрядная версия, вы получите сообщение, которое выглядит так: Этот экземпляр Java не поддерживает 64-битную JVM. Установите нужную версию. Обратитесь к вариантам помощи JVM за дополнительной информацией java -help – Massimo
обратите внимание, что код нарушает как только пользователь Безразлично Не используйте ту же самую версию jre ... –
-1 Ужасный метод. Нет перекрестной платформы. Жесткая версия. – Tomas
Это общий метод обнаружения 64-битного исполняемого файла в окнах. Ничего особенного для версии jre. –