我想通过编程方式确定我的Java程序正在运行的主机操作系统(例如:我希望能够根据是否在Windows或Unix平台上加载不同的属性)。有没有一种百分之百可靠的安全方法可以做到这一点?
我想通过编程方式确定我的Java程序正在运行的主机操作系统(例如:我希望能够根据是否在Windows或Unix平台上加载不同的属性)。有没有一种百分之百可靠的安全方法可以做到这一点?
你可以使用:
System.getProperty("os.name")
附带一句话:你可能会发现这段代码很有用:
class ShowProperties {
public static void main(String[] args) {
System.getProperties().list(System.out);
}
}
它所做的就是打印出Java实现提供的所有属性。这将为您提供有关通过属性了解您的Java环境的信息。
正如其他答案所示,System.getProperty提供了原始数据。然而,Apache Commons Lang组件提供了对java.lang.System的包装,其中包括方便的属性,例如SystemUtils.IS_OS_WINDOWS
,类似于上述的 Swingx OS 工具。
2008年10月:
我建议将其缓存在静态变量中:
public static final class OsUtils
{
private static String OS = null;
public static String getOsName()
{
if(OS == null) { OS = System.getProperty("os.name"); }
return OS;
}
public static boolean isWindows()
{
return getOsName().startsWith("Windows");
}
public static boolean isUnix() // and so on
}
这样做,每次你请求操作系统时,你的应用程序在其生命周期内不会再获取该属性超过一次。
2016年2月:7年多过去了:
Windows 10存在一个bug(原回答发布时不存在)。 请参见"Java's “os.name” for Windows 10?"
isWindows
、isUnix
等值。这样可以节省字符串比较的时间。 - C. K. Young以上答案中的一些链接似乎已经失效。我在下面的代码中添加了指向当前源代码的指针,并提供了一种使用枚举来处理检查的方法,以便在评估结果时可以使用switch语句:
OsCheck.OSType ostype=OsCheck.getOperatingSystemType();
switch (ostype) {
case Windows: break;
case MacOS: break;
case Linux: break;
case Other: break;
}
这个帮助类是:
/**
* helper class to check the operating system this Java VM runs in
*
* please keep the notes below as a pseudo-license
*
* https://dev59.com/VnVC5IYBdhLWcg3woSxW
* compare to http://svn.terracotta.org/svn/tc/dso/tags/2.6.4/code/base/common/src/com/tc/util/runtime/Os.java
* http://www.docjar.com/html/api/org/apache/commons/lang/SystemUtils.java.html
*/
import java.util.Locale;
public static final class OsCheck {
/**
* types of Operating Systems
*/
public enum OSType {
Windows, MacOS, Linux, Other
};
// cached result of OS detection
protected static OSType detectedOS;
/**
* detect the operating system from the os.name System property and cache
* the result
*
* @returns - the operating system detected
*/
public static OSType getOperatingSystemType() {
if (detectedOS == null) {
String OS = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
if ((OS.indexOf("mac") >= 0) || (OS.indexOf("darwin") >= 0)) {
detectedOS = OSType.MacOS;
} else if (OS.indexOf("win") >= 0) {
detectedOS = OSType.Windows;
} else if (OS.indexOf("nux") >= 0) {
detectedOS = OSType.Linux;
} else {
detectedOS = OSType.Other;
}
}
return detectedOS;
}
}
以下是具有静态方法以确定当前操作系统(如isWindows()、isLinux()等)的JavaFX类:
示例:
if (PlatformUtil.isWindows()){
...
}
简而言之:
访问操作系统使用:System.getProperty("os.name")
。
为什么不创建一个实用程序类,使其可重用! 并且在多次调用时可能会快得多。 清晰明了,更快!
为此类实用函数创建一个Util类。 然后为每种操作系统类型创建公共枚举。
public class Util {
public enum OS {
WINDOWS, LINUX, MAC, SOLARIS
};// Operating systems.
private static OS os = null;
public static OS getOS() {
if (os == null) {
String operSys = System.getProperty("os.name").toLowerCase();
if (operSys.contains("win")) {
os = OS.WINDOWS;
} else if (operSys.contains("nix") || operSys.contains("nux")
|| operSys.contains("aix")) {
os = OS.LINUX;
} else if (operSys.contains("mac")) {
os = OS.MAC;
} else if (operSys.contains("sunos")) {
os = OS.SOLARIS;
}
}
return os;
}
}
现在,您可以按照以下方式轻松地从任何类中调用类,(P.S. 由于我们将os变量声明为静态的,它将仅消耗一次时间来识别系统类型,然后可以在应用程序停止之前一直使用。)
switch (Util.getOS()) {
case WINDOWS:
//do windows stuff
break;
case LINUX:
就是这样!
你想实现的一个小例子可能类似于下面这个class
:
import java.util.Locale;
public class OperatingSystem
{
private static String OS = System.getProperty("os.name", "unknown").toLowerCase(Locale.ROOT);
public static boolean isWindows()
{
return OS.contains("win");
}
public static boolean isMac()
{
return OS.contains("mac");
}
public static boolean isUnix()
{
return OS.contains("nux");
}
}
这种具体实现非常可靠,适用性应该是普遍的。只需将其复制并粘贴到您选择的类
中。
试试这个,简单易行。
System.getProperty("os.name");
System.getProperty("os.version");
System.getProperty("os.arch");
如果您正在安全敏感的环境中工作,请仔细阅读以下内容。
请勿相信通过System#getProperty(String)
子例程获得的属性!实际上,几乎每个属性包括os.arch
、os.name
和os.version
都不是只读的,正如您所期望的那样 - 相反,它们实际上恰好相反。
首先,任何具有足够权限调用System#setProperty(String, String)
子例程的代码都可以随意修改返回的文字。然而,这并不一定是主要问题,在此处详细描述了如何使用所谓的SecurityManager
解决该问题。
实际问题在于,任何用户都可以在运行相关的JAR
时编辑这些属性(通过-Dos.name=
、-Dos.arch=
等)。避免篡改应用程序参数的可能方法是通过查询RuntimeMXBean
,如此处所示。下面的代码片段应该可以提供一些关于如何实现这一点的见解。
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
for (String argument : arguments) {
if (argument.startsWith("-Dos.name") {
// System.getProperty("os.name") altered
} else if (argument.startsWith("-Dos.arch") {
// System.getProperty("os.arch") altered
}
}
如果你对开源项目如何处理这种事情感兴趣,可以查看Terracotta类(Os.java),它在这里处理这些问题:
而且,你还可以在这里找到类似的处理JVM版本的类(Vm.java和VmVersion.java):
Windows 10
,但是os.name
却显示为Windows 8.1
。这是为什么?这个信息从哪里来的? - Brian