谈谈如何在运行时获取「环境」信息

作者:网友投稿 时间:2018-06-24 21:24

字号
技术沙龙 | 6月30日与多位专家探讨技术高速发展下如何应对运维新挑战!

软件工程师,特别是开发客户端产品,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里。

那这里加载到 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+... 

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接