如何在发布前检查 JRE 版本?
Posted
技术标签:
【中文标题】如何在发布前检查 JRE 版本?【英文标题】:How to check JRE version prior to launch? 【发布时间】:2010-09-18 08:12:42 【问题描述】:确定机器上安装的 JRE 版本是否足以满足用户想要运行的应用程序的最佳方法是什么?有没有办法使用仅限 java 的东西来做到这一点?我希望该解决方案适用于 Windows/Linux/MacOSX - 如果 JRE 版本太低,则应显示一条消息。目前,如果我尝试在 Java 1.5 上运行它(该应用程序是为 Java 1.6 构建的),我会遇到异常。如果没有通用的解决方案,在 Windows 上最好的方法是什么?
【问题讨论】:
【参考方案1】:您可以使用反射和两个编译器来做到这一点。使用您希望能够运行的最旧的 java 版本编译一个主类。它使用System.getProperty("java.version")
或其他方式检查版本,然后如果检查通过,则使用反射加载您的 real 主类,甚至可能直接加载 jar。 JRE 不应该在编译时加载外部主类未引用的任何类。
【讨论】:
您不一定需要两个编译器。 Java-Compiler 支持 -target-Option,它允许您指定生成的类文件的字节码版本。 谢谢。这条线有效。我加载程序并使用程序所需的版本验证字符串。【参考方案2】:您可以考虑Java Webstart。即使这个名字暗示着类似小程序的东西,它也是关于独立应用程序的。 Webstart 是一个启动器,它检查 JNLP 文件(一个简单的 XML 文件,您可以在其中配置应用程序的下载位置、所需的 Java 版本和一些其他元数据)并使用正确的 JRE 启动您的应用程序。如果有更新的版本可用,它甚至会更新应用程序。缺点是,您必须编写一个 JNLP 文件。这是一个例子:
<?xml version="1.0" encoding="utf-8"?>
<!--
###############################################################################
#
# @(#)draw.jnlp 1.6 02/09/11
#
# JNLP File for Draw Demo Application
#
###############################################################################
-->
<jnlp spec="0.2 1.0"
codebase="http://java.sun.com/javase/technologies/desktop/javawebstart/apps"
href="draw.jnlp">
<information>
<title>Draw 4 App</title>
<vendor>Sun Microsystems, Inc.</vendor>
<homepage href="http://java.sun.com/javase/technologies/desktop/javawebstart/demos.html"/>
<description>A minimalist drawing application along the lines of Illustrator</description>
<description kind="short">Draw Demo Short Description</description>
<icon href="images/draw.jpg"/>
<offline-allowed/>
</information>
<resources>
<j2se version="1.3+" href="http://java.sun.com/products/autodl/j2se"/>
<j2se version="1.3+"/>
<jar href="draw.jar" main="true" download="eager"/>
</resources>
<application-desc main-class="Draw"/>
</jnlp>
第二种可能性是使用启动程序。一个例子是Apache Commons Launcher。您也可以自己编写一些启动器应用程序,但这通常不值得。
【讨论】:
【参考方案3】:您也可以考虑使用 Commons-Launcher,它允许您设置各种环境设置,或在调用您的应用程序之前执行预检查。
http://commons.apache.org/launcher
【讨论】:
【参考方案4】:通常,我们使用 C 或(仅当 unix 时)shell 包装器来处理这个问题。不确定这是否真的适合你。
我们还通过在我们的产品中嵌入 JRE 来解决这个问题。处理 99.9% 的情况(另外 0.1% 的时间是用户显式更改我们的配置以使用不同的 JVM)。同样,不确定这是否适合您。
在我们的例子中,有大量的本地代码(JNI 和其他),因此无论如何都需要为我们支持的每个平台定制一个可安装的映像。但是,如果您正在处理纯 Java 解决方案,您可能只需要记录您的最低要求并告诉人们使用该程序(没有双关语),如果他们要运行您的东西。这有点像人们抱怨我的 Mac 无法运行 MSVC,或者我的 Linux 机器在运行《魔兽世界》时遇到问题。这不是软件所针对的(虚拟)机器——你需要切换。不过,至少在 Java 世界中,我们确实可以称其为升级,而不会伤害任何人的操作系统宗教感情。 (尝试告诉 Mac 用户“升级”到 Windows XP 以运行 MSVC - 等待发生的失败。)
【讨论】:
【参考方案5】:您可以在运行 Java 命令时要求 Java 版本,例如java -version:1.6* com.me.MyClass
。不确定这是否适用于所有 Java 版本,但无论如何它在 1.6 上都可以正常工作。
【讨论】:
【参考方案6】:为更高版本的 JRE 构建的应用程序不会在更低版本的 JRE 上运行。因此,您不能只向应用程序添加代码来检查 JRE 版本 - 如果 JRE 版本不兼容,您的 JRE 版本检查代码将不会首先运行。
您需要做的是为较低版本的 JRE(1.3?)构建某种启动器应用程序,该应用程序检查版本,然后在必要时启动您的应用程序。这对我来说听起来有点笨拙。
在安装过程中检查版本怎么样?您是否以允许您检查环境变量或执行任何类型的脚本的方式安装应用程序?
【讨论】:
这不一定是真的。在大多数情况下,它会正常工作。只有在您使用更新的语言或 API 功能时才会出现问题。 不正确。如果我使用 JDK 1.6 编译一个简单的 Hello World 应用程序,并尝试使用 JDK 1.4 运行它,我会收到 UnsupportedClassVersionError。您所说的只有在我使用 1.6 编译但指定 -target 1.4 时才有效。 仍然,是什么阻止您使用 1.3 编译主类,在其中进行所有检查,然后调用应用程序的其余部分(例如 1.6)? 您需要使用“-source 1.2 -target 1.2”之类的东西编译您的启动器类(以及它在检查之前调用的任何自定义类),以强制它发出兼容的字节码。这意味着在这些课程中您不能使用现代功能。 @Vladimir - 拥有一个 1.3 启动器和一个 1.6 主应用程序没有什么可以阻止的。我只是在评论一个单一的应用程序解决方案。【参考方案7】:对于启动器 - 检查那里的版本。
APP内部;如上使用 System.getProperties();
Properties sProp = java.lang.System.getProperties();
String sVersion = sProp.getProperty("java.version");
sVersion = sVersion.substring(0, 3);
Float f = Float.valueOf(sVersion);
if (f.floatValue() < (float) 1.4)
System.out.println("Java version too low ....");
System.exit(1);
...
【讨论】:
这是非常不确定的。如果不是那个 EXACT 版本,或者他们没有将它安装在那个位置,或者你没有运行 Windows,它将失败。可能的修改是将 java -v 的输出通过管道传输到某些东西并对其进行分析,但是仍然很难找到“或更高版本”的版本。 看看他要求什么 - linux/win/mac 平台或至少是 windows。大多数公司的东西都安装在“确切位置”。 linux 和 mac 做同样的事情。【参考方案8】:有一个为 Java 1.2 编译的启动类,它调用 1.6 类中的 real main()。如果抛出了不受支持的类异常,它们会捕获它并显示一个很好的错误消息。
【讨论】:
【参考方案9】:这是获取系统中安装的 JRE 版本的代码。
var list = deployJava.getJREs();
var result = "";
result = list[0];
for (var i=1; i<list.length; i++)
result += ", " + list[i];
document.write("jre version : "+result);
【讨论】:
【参考方案10】:System.getProperties() 为您提供 JVM 属性列表,包括 JRE、JVM 和规范的不同版本 ID。这已针对所有 Java 版本实现,因此无论编译的版本、运行的版本或实现如何,都应该可以工作。
如果您编写一个基本类来测试版本,您可以在您的 main() 启动类中首先调用它。不过,它必须是真正的基本功能,否则您可能会面临破坏它的风险。
【讨论】:
【参考方案11】:嗯 .. 说我是个无聊的家伙,但例如,使用 Launch4J 或任何其他本机启动器有什么问题。
在实际运行代码之前,使用本机启动器检查 JVM 版本。仅 Java 的解决方案(在我的书中)只有在与开发人员打交道时才有意义;一旦接触到最终用户,您就会意识到他们根本不关心 Java 或其技术细节。如果您使用 GW-Basic 编写应用程序,只要您的应用程序正常运行,他们就不会在意。
如果未安装 Java 1.6,lauchner4j 会将用户指向 JDK 1.6 的下载页面。这可能比在 Java 中变魔术更适合您的问题。
【讨论】:
【参考方案12】:我发现WinRun4J 对我来说效果很好(但话说回来,我写它之后可能会有偏见:-))。这使您可以指定允许的 Java 的最小和/或最大版本。如果没有找到合适的 JRE 版本,它将向用户弹出一个消息框(并且该消息是可自定义的)。
【讨论】:
【参考方案13】:以上所有这些都太他妈复杂了。 走吧:
Properties props = System.getProperties()
props.list(System.out)
您将看到有关您的 JVM、JRE、JDK 和员工的所有信息。 或者通过使用获取特定值:
//full list of possible props you can see if u run code above
String props = System.getProperty(prop)
【讨论】:
字符串道具 = System.getProperty("java.version")以上是关于如何在发布前检查 JRE 版本?的主要内容,如果未能解决你的问题,请参考以下文章