您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“java如何在運行時獲取環境信息”,內容詳細,步驟清晰,細節處理妥當,希望這篇“java如何在運行時獲取環境信息”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
軟件工程師,特別是開發客戶端產品,App這一類,都免不了需要判斷當前所處環境。比如客戶端產品要判斷是Windows/Linux系統,x86還是x64等等。 App則需要判斷安卓、iOS的版本,當前環境是否WIFI之類的。
對于 Java 應用, 無論 Web 還是 桌面應用,也會遇到需要判斷當前所使用的 JDK 版本,當前應用對應的操作系統等等。
比如我們在幾年前做應用服務器集群管理與監控時,需要判斷應用服務器所屬物理機器的CPU以及內存的使用率、對于服務器實例進行操作,對于不同的JVM 實現,采用不同的attach機制等等。當時是使用 Sigar 進行這些硬件信息的獲取。
由于提供的是All in One 的版本,所以需要判斷操作系統類型,來判斷加載 Sigar 的Windows支持 dll 文件還是Linux 支持 so 文件。
當然獲取操作系統類型、版本都較容易,直接通過System 的getProperty再加上對應的名稱就能拿到,比如「os.name」,「os.arch」等。對于 JVM 的廠商,則可以通過「java.vm.vendor」來得到,完整的可以通過System.getProperties全部拿到。
如果習慣使用JMX 讀取Platform 的 MBean,也可以通過 JMX來獲取,便捷操作類似這樣:
OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
System.out.println(os.getName());
本質上也都是一樣的。
那除了這種方式,還有哪些方式可以獲取到呢?一般開源軟件又是怎么做的呢?
我們來看 Tomcat 內部怎么實現的。
我們發現, Tomcat 內部,對于通過 System 的 properties獲取到的,基本都是用來打印 Log 和輸出使用,對于應用內的控制,基本沒看到使用。
那 Tomcat在判斷版本時,是怎么做的呢?為什么不直接用這個呢?
首先看怎么做的。
前面的文章提到過, Tomcat 對于內存泄漏做了一些努力,比如先Hold 一塊內存這種(Tomcat與內存泄露處理),也比如防止內存泄漏的PreventionListener,會先將可能共用的 class加載到Common classLoader里(Tomcat類加載器以及應用間class隔離與共享,類加載器與類沖突)。
那這里加載到 Common classLoader這些常用 class時,就需要判斷當前是Java 哪個版本,因為有些 class 是某些版之后才出現的。
具體實現是這個樣子:
// Trigger a call to sun.awt.AppContext.getAppContext(). This
// will pin the system class loader in memory but that shouldn't
// be an issue.
if (appContextProtection && !JreCompat.isJre8Available()) {
ImageIO.getCacheDirectory();
}
// Trigger the creation of the AWT (AWT-Windows, AWT-XAWT,
// etc.) thread
if (awtThreadProtection && !JreCompat.isJre9Available()) {
java.awt.Toolkit.getDefaultToolkit();
}
什么時候 Available了?
static {
// This is Tomcat 8 with a minimum Java version of Java 7. The latest
// Java version the optional features require is Java 9.
// Look for the highest supported JVM first
if (Jre9Compat.isSupported()) {
instance = new Jre9Compat();
jre9Available = true;
jre8Available = true;
}
else if (Jre8Compat.isSupported()) {
instance = new Jre8Compat();
jre9Available = false;
jre8Available = true;
} else {
instance = new JreCompat();
jre9Available = false;
jre8Available = false;
}
}
具體是不是支持是直接通過加載特定版JDK 對應的 class 來判斷
static {
Method m1 = null;
try {
// The class is Java6+...
Class<?> c1 = Class.forName("javax.net.ssl.SSLParameters");
// ...but this method is Java8+
m1 = c1.getMethod("setUseCipherSuitesOrder", boolean.class);
} catch (SecurityException e) {
// Should never happen
} catch (NoSuchMethodException e) {
// Expected on Java < 8
} catch (ClassNotFoundException e) {
// Should never happen
}
setUseCipherSuitesOrderMethod = m1;
}
通過這種加載 class 的方式,和 我們前面通過 System.property獲取,有啥區別呢?
要知道, System 的 Property 是個系統屬性,是可配置的,也就是說,誰都可以進行setProperty的操作。如果不巧被別人改了,那你的程序可能就會出現不符合你預期的行為。
而加載類的形式,并不受其他人的影響。是最真實的一線聲音。
這樣的判斷不方式,不僅 Tomcat 自己,其他框架也有在用。我們來看 Spring Boot。
Boot 執行的時候,有時候會判斷當前應用是否需要支持 Web, 類似于是否加載了 Spring MVC 這種。
private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private boolean deduceWebEnvironment() {
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return false;
}
}
return true;
}
然后在啟動時候,會調用deduceWebEnvironment 方法,從而決定一些執行的邏輯。
還有其他方式么? 如何不想自己手工處理,可以使用一些工具類,比如 Apache 的 commons-lang, 提供了一個 SystemUtils 可以直接。例如判斷操作系統和 Java 版本
if (SystemUtils.IS_JAVA_1_7) {
System.out.println("Hello 1.7");
}
工具類是怎么做的呢?
public static final String JAVA_VERSION = getSystemProperty("java.version");private static String getJavaVersionTrimmed() {
if(JAVA_VERSION != null) {
for(int i = 0; i < JAVA_VERSION.length(); ++i) {
char ch = JAVA_VERSION.charAt(i);
if(ch >= 48 && ch <= 57) {
return JAVA_VERSION.substring(i);
}
}
}
return null;
}
說到底,也還是System.getProperty.
所以,在檢測環境的時候,我們可以通過System.getProperty,也可以通過 Tomcat 和 Spring 這種加載 class 的方式。或者干脆直接用工具類。 你還用過啥辦法呢?
讀到這里,這篇“java如何在運行時獲取環境信息”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。