日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
談?wù)勅绾卧谶\(yùn)行時(shí)獲取「環(huán)境」信息

軟件工程師,特別是開發(fā)客戶端產(chǎn)品,App這一類,都免不了需要判斷當(dāng)前所處環(huán)境。比如客戶端產(chǎn)品要判斷是Windows/Linux系統(tǒng),x86還是x64等等。 App則需要判斷安卓、iOS的版本,當(dāng)前環(huán)境是否WIFI之類的。

創(chuàng)新互聯(lián)是專業(yè)的沙洋網(wǎng)站建設(shè)公司,沙洋接單;提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作,網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行沙洋網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

對(duì)于 Java 應(yīng)用, 無論 Web 還是 桌面應(yīng)用,也會(huì)遇到需要判斷當(dāng)前所使用的 JDK 版本,當(dāng)前應(yīng)用對(duì)應(yīng)的操作系統(tǒng)等等。

比如我們?cè)趲啄昵白鰬?yīng)用服務(wù)器集群管理與監(jiān)控時(shí),需要判斷應(yīng)用服務(wù)器所屬物理機(jī)器的CPU以及內(nèi)存的使用率、對(duì)于服務(wù)器實(shí)例進(jìn)行操作,對(duì)于不同的JVM 實(shí)現(xiàn),采用不同的attach機(jī)制等等。當(dāng)時(shí)是使用 Sigar 進(jìn)行這些硬件信息的獲取。

由于提供的是All in One 的版本,所以需要判斷操作系統(tǒng)類型,來判斷加載 Sigar 的Windows支持 dll 文件還是Linux 支持 so 文件。

當(dāng)然獲取操作系統(tǒng)類型、版本都較容易,直接通過System 的getProperty再加上對(duì)應(yīng)的名稱就能拿到,比如「os.name」,「os.arch」等。對(duì)于 JVM 的廠商,則可以通過「java.vm.vendor」來得到,完整的可以通過System.getProperties全部拿到。

如果習(xí)慣使用JMX 讀取Platform 的 MBean,也可以通過 JMX來獲取,便捷操作類似這樣:

 
 
 
 
  1. OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
  2. System.out.println(os.getName());

本質(zhì)上也都是一樣的。

那除了這種方式,還有哪些方式可以獲取到呢?一般開源軟件又是怎么做的呢?

我們來看 Tomcat 內(nèi)部怎么實(shí)現(xiàn)的。

我們發(fā)現(xiàn), Tomcat 內(nèi)部,對(duì)于通過 System 的 properties獲取到的,基本都是用來打印 Log 和輸出使用,對(duì)于應(yīng)用內(nèi)的控制,基本沒看到使用。

那 Tomcat在判斷版本時(shí),是怎么做的呢?為什么不直接用這個(gè)呢?

首先看怎么做的。

前面的文章提到過, Tomcat 對(duì)于內(nèi)存泄漏做了一些努力,比如先Hold 一塊內(nèi)存這種(Tomcat與內(nèi)存泄露處理),也比如防止內(nèi)存泄漏的PreventionListener,會(huì)先將可能共用的 class加載到Common classLoader里。

那這里加載到 Common classLoader這些常用 class時(shí),就需要判斷當(dāng)前是Java 哪個(gè)版本,因?yàn)橛行?class 是某些版之后才出現(xiàn)的。

具體實(shí)現(xiàn)是這個(gè)樣子:

 
 
 
 
  1. // Trigger a call to sun.awt.AppContext.getAppContext(). This
  2. // will pin the system class loader in memory but that shouldn't
  3. // be an issue.
  4. if (appContextProtection && !JreCompat.isJre8Available()) {
  5.     ImageIO.getCacheDirectory();
  6. }
  7. // Trigger the creation of the AWT (AWT-Windows, AWT-XAWT,
  8. // etc.) thread
  9. if (awtThreadProtection && !JreCompat.isJre9Available()) {
  10.     java.awt.Toolkit.getDefaultToolkit();
  11. }

什么時(shí)候 Available了?

 
 
 
 
  1. static {
  2.     // This is Tomcat 8 with a minimum Java version of Java 7. The latest
  3.     // Java version the optional features require is Java 9.
  4.     // Look for the highest supported JVM first
  5.     if (Jre9Compat.isSupported()) {
  6.         instance = new Jre9Compat();
  7.         jre9Available = true;
  8.         jre8Available = true;
  9.     }
  10.     else if (Jre8Compat.isSupported()) {
  11.         instance = new Jre8Compat();
  12.         jre9Available = false;
  13.         jre8Available = true;
  14.     } else {
  15.         instance = new JreCompat();
  16.         jre9Available = false;
  17.         jre8Available = false;
  18.     }
  19. }

具體是不是支持是直接通過加載特定版JDK 對(duì)應(yīng)的 class 來判斷

 
 
 
 
  1. static {
  2.     Method m1 = null;
  3.     try {
  4.         // The class is Java6+...
  5.         Class c1 = Class.forName("javax.net.ssl.SSLParameters");
  6.         // ...but this method is Java8+
  7.         m1 = c1.getMethod("setUseCipherSuitesOrder", boolean.class);
  8.     } catch (SecurityException e) {
  9.         // Should never happen
  10.     } catch (NoSuchMethodException e) {
  11.         // Expected on Java < 8
  12.     } catch (ClassNotFoundException e) {
  13.         // Should never happen
  14.     }
  15.     setUseCipherSuitesOrderMethod = m1;
  16. }

通過這種加載 class 的方式,和 我們前面通過 System.property獲取,有啥區(qū)別呢?

要知道, System 的 Property 是個(gè)系統(tǒng)屬性,是可配置的,也就是說,誰都可以進(jìn)行setProperty的操作。如果不巧被別人改了,那你的程序可能就會(huì)出現(xiàn)不符合你預(yù)期的行為。

而加載類的形式,并不受其他人的影響。是最真實(shí)的一線聲音。

這樣的判斷不方式,不僅 Tomcat 自己,其他框架也有在用。我們來看 Spring Boot。

Boot 執(zhí)行的時(shí)候,有時(shí)候會(huì)判斷當(dāng)前應(yīng)用是否需要支持 Web, 類似于是否加載了 Spring MVC 這種。

 
 
 
 
  1. private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
  2.     "org.springframework.web.context.ConfigurableWebApplicationContext" };
  3.     
  4.         private boolean deduceWebEnvironment() {
  5.             for (String className : WEB_ENVIRONMENT_CLASSES) {
  6.                 if (!ClassUtils.isPresent(className, null)) {
  7.                     return false;
  8.                 }
  9.             }
  10.             return true;
  11.         }

然后在啟動(dòng)時(shí)候,會(huì)調(diào)用deduceWebEnvironment 方法,從而決定一些執(zhí)行的邏輯。

還有其他方式么? 如何不想自己手工處理,可以使用一些工具類,比如 Apache 的 commons-lang, 提供了一個(gè) SystemUtils 可以直接。例如判斷操作系統(tǒng)和 Java 版本

 
 
 
 
  1. if (SystemUtils.IS_JAVA_1_7) {
  2.     System.out.println("Hello 1.7");
  3. }

工具類是怎么做的呢?

 
 
 
 
  1. public static final String JAVA_VERSION = getSystemProperty("java.version");
  2. private static String getJavaVersionTrimmed() {
  3.     if(JAVA_VERSION != null) {
  4.         for(int i = 0; i < JAVA_VERSION.length(); ++i) {
  5.             char ch = JAVA_VERSION.charAt(i);
  6.             if(ch >= 48 && ch <= 57) {
  7.                 return JAVA_VERSION.substring(i);
  8.             }
  9.         }
  10.     }
  11.     return null;
  12. }

說到底,也還是System.getProperty.

所以,在檢測(cè)環(huán)境的時(shí)候,我們可以通過System.getProperty,也可以通過 Tomcat 和 Spring 這種加載 class 的方式?;蛘吒纱嘀苯佑霉ぞ哳?。 你還用過啥辦法呢?

【本文為專欄作者“侯樹成”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過作者微信公眾號(hào)『Tomcat那些事兒』獲取授權(quán)】


分享名稱:談?wù)勅绾卧谶\(yùn)行時(shí)獲取「環(huán)境」信息
URL地址:http://www.dlmjj.cn/article/dphjddd.html