Java 32位与64位的兼容性

98

在使用32位JDK编写和编译的Java代码能否在64位JVM上运行?或者说64位JVM是否需要64位字节码?

为了提供更多细节,我有一些代码曾经在运行32位JVM的Solaris环境中工作过,但现在在升级JDK和Weblogic Server到64位后出现了问题。


3
请澄清“issues”的含义。 - Thorbjørn Ravn Andersen
我遇到了类似的问题 - 在64位Weblogic服务器上部署Spring应用程序。我们遇到了各种找不到类的异常和其他无用的错误。此外,它可以在某些64位机器上部署和运行,但在其他机器上却不能。然而,我们无法确定有什么不同之处。你解决了这个问题吗? - nont
2
@nont - 无论问题是什么,它都不是32位与64位编译的问题。 - Stephen C
9个回答

95

是的,假设您使用平台无关的库,Java字节码(和源代码)是跨平台的。32位与64位并不重要。


我在寻找一个问题时遇到了这个。于是我在32位JVM下运行我的应用程序并使用64位本机库。它运行得很好。但是当我在64位JVM下运行我的应用程序并使用32位本机库时,它失败了。这怎么可能呢?只是好奇。 - Umang Desai
7
@umangdesai 原生库不是跨平台的库,因此这个假设不成立。 - Thorbjørn Ravn Andersen
“shouldn't matter” 的意思是,使用 32 位 javac 编译的代码是否能够利用 64 位 java 提供的内存并不重要? - Marcus Junius Brutus
1
如果你遇到了这个问题,要注意一些原生库被捆绑到一个 jar 包中只适用于一个平台,而不是给你带来问题的那个平台。(如果你不知道我在说什么,请参考类似这样的内容:https://dev59.com/_nA85IYBdhLWcg3wHvo0#14051512)。 - Matt S.

21

我不小心在64位虚拟机上运行了我们(相对较大的)应用程序,而不是32位虚拟机,在一些由JNI调用的外部库失败之前没有注意到。

在64位平台上读取32位平台上序列化的数据时,没有任何问题。

你遇到了什么样的问题?有些功能工作正常,而另一些则不行吗?你尝试过附加JConsole等工具并查看一下吗?

如果你使用非常大的虚拟机,你可能会发现64位GC问题会影响你。


1
你的意思是如果JNI库是32位的,它们在64位虚拟机中不会起作用吗? - C. Ross
1
它们不起作用。一个同事曾报告说他们起作用(这让我感到非常怀疑)。我想知道他是否在Solaris上运行,并且是否存在某种 thunking。但实际上并没有,他错了,它是在32位下运行的。 - Fortyrunner
我曾经遇到过一个JNI库的类似问题。32位和64位库之间没有兼容性。 - Erick Robertson
确实,您的JNI库需要被替换。您可能可以直接从供应商的网站上下载64位的替代版本。(对我来说, 对于我使用的所有JNI库都奏效了)。 - bvdb
这些是内部库,没有64位的等效物可用,因此回到32位是当天的命令。 - Fortyrunner

11

对于第一个问题是肯定的,对于第二个问题是否定的;这是一个虚拟机。你的问题可能与版本之间未指定的库实现更改有关。尽管也可能是某种竞争条件。

虚拟机必须经过一些步骤。特别地,类文件中的引用被处理为在堆栈上占用与int相同的空间。 doublelong占用两个引用槽位。对于实例字段,虚拟机通常会进行一些重新排列。这都是(相对)透明完成的。

此外,一些64位JVM使用“压缩oops”。由于数据对齐到大约每8或16字节,地址中的三到四个位是无用的(尽管可以为一些算法窃取“标志”位)。这使得32位地址数据(因此使用一半带宽,因此更快)可以在64位平台上使用35位或36位的堆大小。


3
你让我感到惊讶。我原本认为不存在32位字节码或64位字节码。 - Jon Skeet
3
重新阅读你的回答,你确定你不是反过来说了吗?(是然后否。) - Jon Skeet
+1 给 Jon Skeet。我本来也想写同样的评论,但被叫走了。 - Michael Myers
我原本的意思是不是,但问题的顺序相反了。已经回滚了一个编辑并进行了编辑(并添加了更多信息)。 - Tom Hawtin - tackline
5
@Jon Skeet: 没有32位和64位字节码,但是当JIT编译时,JVM中的指针(通常)是32位或64位,具体取决于平台。并且通过压缩对象指针技术(Compressed OOPS),即使在64位JVM上,它们也可以在许多地方使用32位指针。这可以节省相当大的内存,并增加代码局部性,从而提高速度。 - Joachim Sauer

10
所有字节码都是以8位为基础的。(这就是为什么它被称为BYTE代码) 所有指令的大小都是8位的倍数。 我们在32位的机器上开发,并使用64位的JVM运行我们的服务器。
您可以详细说明您面临的问题吗?这样我们可能有机会帮助您。否则,我们只能猜测您遇到的问题是什么。

8

除非你有本地代码(针对特定架构编译的机器代码),否则你的代码将在32位和64位JVM中运行得一样好。

但是请注意,由于地址更大(32位为4字节,64位为8字节),相同任务的64位JVM将需要比32位JVM更多的内存。


请注意,在64位系统上运行的32位JVM可能比在32位系统上运行的32位JVM可用内存更多,因此如果您有一个需要使用几GB内存的应用程序,这可能是一个有趣的选择。 - Thorbjørn Ravn Andersen

3

当您与本地库进行接口操作时,32位与64位的差异变得更加重要。64位Java将无法通过JNI与32位非Java dll进行接口交互。


5
你并未为这个非常老旧的问题提供任何新内容。 - Austin Henley

2

0

Java JNI需要与JVM相同“位数”的操作系统库。如果您尝试构建某个依赖于IESHIMS.DLL(位于%ProgramFiles%\Internet Explorer中)的东西,您需要在JVM为32位时使用32位版本,在JVM为64位时使用64位版本。其他平台也是如此。

除此之外,你应该已经准备好了。生成的Java字节码应该是相同的。

请注意,对于较大的项目,您应该使用64位Java编译器,因为它可以处理更多的内存。


-5

嘿,你错了!对于这个主题,我向Oracle提出了一个问题。答案是:

“如果你在32位机器上编译代码,那么你的代码只能在32位处理器上运行。如果你想在64位JVM上运行你的代码,你必须使用64位JDK在64位机器上编译类文件。”


5
Java代码通常编译成的字节码格式在32位或64位平台上是相同的,无论哪种平台。但对于任何本地代码而言,规则都是不同的,而Java字节码是可移植的。 - McDowell
4
好的,看起来在 Oracle 回答你的问题的人要么误解了它,要么对 JVM 一无所知。 - Paŭlo Ebermann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接