如何检测哪种JRE安装 – 32位与64位
在使用NSIS安装程序进行安装期间,我需要检查系统上安装了哪个JRE(32位和64位)。 我已经知道我可以检查系统属性“ sun.arch.data.model
”,但是这是Sun特有的。 我想知道是否有一个标准的解决scheme。
正在使用的JVM体系结构可以使用“ os.arch ”属性进行检索:
System.getProperty("os.arch");
“os”部分似乎有点不恰当,或者原来的devise者可能不希望JVM运行在没有写入的架构上。 返回值似乎不一致 。
NetBeans安装程序团队正在解决 JVM vs OS体系结构的问题 。 引用:
x64位:Java和System
跟踪问题143434 。
目前我们使用x64位的JVM来确定系统(以及Platform.getHardwareArch())是否为64位。 这是绝对错误的,因为可以在64位系统上运行32位JVM。 如果在32位JVM上运行,我们应该find一个解决scheme来检查操作系统真正的64位。
- 对于Windows,可以使用WindowsRegistry.IsWow64Process()
- 对于Linux – 通过检查'uname -m / -p'== x86_64
- 对于Solaris,可以使用例如'isainfo -b'
- 对于Mac OSX,它不能使用uname参数来完成,可能可以通过创build64位二进制文件并在平台上执行来解决…(不幸的是,这不起作用:(我只用x86_64创build了二进制文件和ppc64拱,它成功地执行在老虎..)
- 对于通用的Unix支持 – 它不是很清楚…可能检查相同的'uname -m / -p'/'getconf LONG_BIT'并将其与一些可能的64位值(x86_64,x64,amd64,ia64 )。
所有运行在64位Ubuntu 8.0.4上的不同JVM的示例属性:
32位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
64位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
64位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也不会)。
我正在使用NSIS和Launch4j来包装Java桌面应用程序。 所以我不仅需要检测任何JRE,而且Launch4j会使用它的searchalgorithm。 唯一有意义的方法是在NSIS安装程序中运行一个简短的Java程序。 这是Java:
公共类DetectJVM { 私人静态最终的string键[] = { “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); 如果(打印)System.out.println(键+“=”+属性); if(property!= null){ int errCode =(property.indexOf(“64”)> = 0)? 64:32; 如果(打印)System.out.println(“err code =”+ errCode); System.exit(ERRCODE); } } } }
用Launch4J把它包起来。 使用GUI标题types,但也设置为true。 否则,错误代码将会丢失。 (我把这一切都放在我的Netbeans Ant构build脚本中。
这是使用它的匹配的NSIS代码:
文件...; 解压缩文件,包括detectjvm.exe。 ClearErrors ExecWait'“$ INSTDIR \ detectjvm.exe”'$ 0 IfErrors DetectExecError IntCmp $ 0 0 DetectError DetectError DoneDetect DetectExecError: StrCpy $ 0“执行错误” DetectError: MessageBox MB_OK“无法确定JVM架构($ 0),假设是32位”。 转到NotX64 DoneDetect: IntCmp $ 0 64 X64 NotX64 NotX64 X64: 文件... 64位AMD DLL。 转到DoneX64 NotX64: 文件... 32位x86 DLL。 DoneX64: 删除$ INSTDIR \ detectjvm.exe
这在WinXP的很多种机器上都运行良好,没有SP,通过Vista和Win7,所有的SP都是32位和64位。
请注意,在我的NSIS脚本中,我正在使用一个现有的程序包来检查JVM是否已安装并首先执行,因此默认的32位select只会在JVM安装出现问题时才会发生,在这种情况下无论如何,您复制的DLL集合都无关紧要。
希望这对某人有帮助。
在编写Java代码时,如何区分32位和64位操作?
http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#64bit_detection
没有公共的API可以让你区分32位和64位操作。 把64位看作是一次写入的另一个平台,随处运行传统。 但是,如果您想要编写特定于平台的代码(对您不利),则系统属性sun.arch.data.model的值为“32”,“64”或“unknown”。
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()); } }
在linux上,my(java)vm报告java.vm.name = Java HotSpot(TM)64位服务器虚拟机。 系统的javadocs声明System.getProperty将始终有一个值,但沉默sun.arch.data.model。
不幸的是,他们没有指定系统属性是什么,所以其他一些JVM可能会报告java.vm.name = Edgar。
顺便说一下,通过“安装在系统上”,我假设你的意思是“当前运行的JVM”?
在系统上可能有32位和64位的JVM,并且其中很多。
如果你已经有了每个受支持的平台的dll,可以考虑制作一个链接和运行的小型可执行文件,以便testing平台是否支持给定的function。 如果可执行文件链接并运行,则可以安装相应的共享库。
如果你有你要检查的.exe的path,你可以使用这个答案 。 基本上它只是查看.exe文件中的头文件,并告诉您在Windows上是否是64位或32位。
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)
以下代码检查任何Windows可执行文件中的machineType字段以确定它是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; } }
请注意,为简洁起见,代码已被压缩。