الحصول على معلومات النظام على مستوى نظام التشغيل

StackOverflow https://stackoverflow.com/questions/25552

  •  09-06-2019
  •  | 
  •  

سؤال

أقوم حاليًا بإنشاء تطبيق Java يمكن تشغيله على العديد من الأنظمة الأساسية المختلفة، ولكن في المقام الأول على إصدارات مختلفة من Solaris وLinux وWindows.

هل تمكن أي شخص من استخراج معلومات بنجاح مثل مساحة القرص الحالية المستخدمة واستخدام وحدة المعالجة المركزية والذاكرة المستخدمة في نظام التشغيل الأساسي؟ماذا عن ما يستهلكه تطبيق Java نفسه؟

ويفضل أن أحصل على هذه المعلومات دون استخدام JNI.

هل كانت مفيدة؟

المحلول

يمكنك الحصول على بعض معلومات الذاكرة المحدودة من فئة وقت التشغيل.إنه ليس بالضبط ما تبحث عنه، لكنني اعتقدت أنني سأقدمه من أجل الاكتمال.هنا مثال صغير.يحرر:يمكنك أيضًا الحصول على معلومات استخدام القرص من فئة java.io.File.تتطلب عناصر استخدام مساحة القرص Java 1.6 أو أعلى.

public class Main {
  public static void main(String[] args) {
    /* Total number of processors or cores available to the JVM */
    System.out.println("Available processors (cores): " + 
        Runtime.getRuntime().availableProcessors());

    /* Total amount of free memory available to the JVM */
    System.out.println("Free memory (bytes): " + 
        Runtime.getRuntime().freeMemory());

    /* This will return Long.MAX_VALUE if there is no preset limit */
    long maxMemory = Runtime.getRuntime().maxMemory();
    /* Maximum amount of memory the JVM will attempt to use */
    System.out.println("Maximum memory (bytes): " + 
        (maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));

    /* Total memory currently available to the JVM */
    System.out.println("Total memory available to JVM (bytes): " + 
        Runtime.getRuntime().totalMemory());

    /* Get a list of all filesystem roots on this system */
    File[] roots = File.listRoots();

    /* For each filesystem root, print some info */
    for (File root : roots) {
      System.out.println("File system root: " + root.getAbsolutePath());
      System.out.println("Total space (bytes): " + root.getTotalSpace());
      System.out.println("Free space (bytes): " + root.getFreeSpace());
      System.out.println("Usable space (bytes): " + root.getUsableSpace());
    }
  }
}

نصائح أخرى

ال java.lang.management تمنحك الحزمة معلومات أكثر بكثير من وقت التشغيل - على سبيل المثال ستمنحك ذاكرة كومة (ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()) منفصلة عن الذاكرة غير الكومة (ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()).

يمكنك أيضًا الحصول على استخدام وحدة المعالجة المركزية (CPU) (بدون كتابة رمز JNI الخاص بك)، ولكنك تحتاج إلى إرسال ملف java.lang.management.OperatingSystemMXBean إلى أ com.sun.management.OperatingSystemMXBean.يعمل هذا على نظامي التشغيل Windows وLinux، ولم أختبره في أي مكان آخر.

على سبيل المثال ...قم باستدعاء طريقة getCpuUsage() بشكل متكرر للحصول على قراءات أكثر دقة.

public class PerformanceMonitor { 
    private int  availableProcessors = getOperatingSystemMXBean().getAvailableProcessors();
    private long lastSystemTime      = 0;
    private long lastProcessCpuTime  = 0;

    public synchronized double getCpuUsage()
    {
        if ( lastSystemTime == 0 )
        {
            baselineCounters();
            return;
        }

        long systemTime     = System.nanoTime();
        long processCpuTime = 0;

        if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
        {
            processCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
        }

        double cpuUsage = (double) ( processCpuTime - lastProcessCpuTime ) / ( systemTime - lastSystemTime );

        lastSystemTime     = systemTime;
        lastProcessCpuTime = processCpuTime;

        return cpuUsage / availableProcessors;
    }

    private void baselineCounters()
    {
        lastSystemTime = System.nanoTime();

        if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
        {
            lastProcessCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
        }
    }
}

أعتقد أن أفضل طريقة هي التنفيذ SIGAR API بواسطة Hyperic.إنه يعمل مع معظم أنظمة التشغيل الرئيسية (الرتق بالقرب من أي شيء حديث) ومن السهل جدًا التعامل معه.المطور (المطورون) مستجيبون للغاية في المنتدى والقوائم البريدية الخاصة بهم.أنا أيضا أحب أن يكون كذلك جي بي إل 2 أباتشي مرخص.أنها توفر طنًا من الأمثلة في Java أيضًا!

SIGAR == أداة معلومات النظام والتجميع وإعداد التقارير.

يوجد مشروع Java يستخدم JNA (لذلك لا توجد مكتبات أصلية لتثبيتها) وهو قيد التطوير النشط.وهو يدعم حاليًا Linux وOSX وWindows وSolaris وFreeBSD ويوفر معلومات عن ذاكرة الوصول العشوائي (RAM) ووحدة المعالجة المركزية (CPU) والبطارية ونظام الملفات.

يمكنك الحصول على بعض المعلومات على مستوى النظام باستخدام System.getenv(), ، بتمرير اسم متغير البيئة ذي الصلة كمعلمة.على سبيل المثال، على نظام التشغيل Windows:

System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")

بالنسبة لأنظمة التشغيل الأخرى، سيختلف وجود/غياب وأسماء متغيرات البيئة ذات الصلة.

بالنسبة للنوافذ ذهبت بهذه الطريقة.

    com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

    long physicalMemorySize = os.getTotalPhysicalMemorySize();
    long freePhysicalMemory = os.getFreePhysicalMemorySize();
    long freeSwapSize = os.getFreeSwapSpaceSize();
    long commitedVirtualMemorySize = os.getCommittedVirtualMemorySize();

هنا هو وصلة مع التفاصيل.

أضف تبعية OSHI عبر maven:

<dependency>
    <groupId>com.github.dblock</groupId>
    <artifactId>oshi-core</artifactId>
    <version>2.2</version>
</dependency>

احصل على سعة البطارية المتبقية بالنسبة المئوية:

SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
for (PowerSource pSource : hal.getPowerSources()) {
    System.out.println(String.format("%n %s @ %.1f%%", pSource.getName(), pSource.getRemainingCapacity() * 100d));
}

قم بإلقاء نظرة على واجهات برمجة التطبيقات المتوفرة في java.lang.management طَرد.على سبيل المثال:

  • OperatingSystemMXBean.getSystemLoadAverage()
  • ThreadMXBean.getCurrentThreadCpuTime()
  • ThreadMXBean.getCurrentThreadUserTime()

هناك الكثير من الأشياء المفيدة الأخرى هناك أيضًا.

عادةً، للحصول على معلومات نظام التشغيل ذات المستوى المنخفض، يمكنك استدعاء أوامر خاصة بنظام التشغيل والتي تمنحك المعلومات التي تريدها باستخدام Runtime.exec() أو قراءة ملفات مثل /proc/* في Linux.

استخدام وحدة المعالجة المركزية ليس بالأمر السهل - java.lang.management عبر com.sun.management.OperatingSystemMXBean.getProcessCpuTime يقترب (راجع مقتطف التعليمات البرمجية الممتاز لباتريك أعلاه) ولكن لاحظ أنه يتيح فقط الوصول إلى الوقت الذي تقضيه وحدة المعالجة المركزية في العملية.ولن يخبرك عن الوقت الذي تقضيه وحدة المعالجة المركزية في عمليات أخرى، أو حتى الوقت الذي تقضيه وحدة المعالجة المركزية في القيام بأنشطة النظام المتعلقة بالعملية الخاصة بك.

على سبيل المثال، لدي عملية جافا كثيفة الاستخدام للشبكة - إنها الشيء الوحيد قيد التشغيل ووحدة المعالجة المركزية تبلغ 99٪ ولكن يتم الإبلاغ عن 55٪ فقط منها على أنها "وحدة المعالجة المركزية للمعالج".

لا تجعلني أبدأ في استخدام "متوسط ​​التحميل" لأنه قريب من عدم الفائدة، على الرغم من كونه العنصر الوحيد المتعلق بوحدة المعالجة المركزية في حبة MX.لو كشفت الشمس فقط في حكمتها العرضية شيئًا مثل "getTotalCpuTime" ...

للمراقبة الجادة لوحدة المعالجة المركزية، يبدو أن SIGAR الذي ذكره Matt هو أفضل رهان.

إنه لا يزال قيد التطوير ولكن يمكنك استخدامه بالفعل jHardware

إنها مكتبة بسيطة تقوم بإلغاء بيانات النظام باستخدام Java.وهو يعمل في كل من لينكس وويندوز.

ProcessorInfo info = HardwareInfo.getProcessorInfo();
//Get named info
System.out.println("Cache size: " + info.getCacheSize());        
System.out.println("Family: " + info.getFamily());
System.out.println("Speed (Mhz): " + info.getMhz());
//[...]

إذا كنت تستخدم Jrockit VM، فإليك طريقة أخرى للحصول على استخدام وحدة المعالجة المركزية VM.يمكن لفاصوليا وقت التشغيل أيضًا أن تمنحك حمل وحدة المعالجة المركزية لكل معالج.لقد استخدمت هذا فقط على Red Hat Linux لمراقبة أداء Tomcat.يجب عليك تمكين جهاز التحكم عن بعد JMX في catalina.sh حتى يعمل هذا.

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://my.tomcat.host:8080/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);     
MBeanServerConnection conn = jmxc.getMBeanServerConnection();       
ObjectName name = new ObjectName("oracle.jrockit.management:type=Runtime");
Double jvmCpuLoad =(Double)conn.getAttribute(name, "VMGeneratedCPULoad");

على Windows, ، يمكنك تشغيل systeminfo الأمر ويسترد مخرجاته على سبيل المثال باستخدام الكود التالي:

private static class WindowsSystemInformation
{
    static String get() throws IOException
    {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("systeminfo");
        BufferedReader systemInformationReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        StringBuilder stringBuilder = new StringBuilder();
        String line;

        while ((line = systemInformationReader.readLine()) != null)
        {
            stringBuilder.append(line);
            stringBuilder.append(System.lineSeparator());
        }

        return stringBuilder.toString().trim();
    }
}

إحدى الطرق البسيطة التي يمكن استخدامها للحصول على معلومات مستوى نظام التشغيل والتي قمت باختبارها على جهاز Mac الخاص بي والتي تعمل بشكل جيد:

 OperatingSystemMXBean osBean =
        (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
    return osBean.getProcessCpuLoad();

يمكنك العثور على العديد من المقاييس ذات الصلة بنظام التشغيل هنا

مرحبًا، يمكنك القيام بذلك من خلال تكامل Java/com.ومن خلال الوصول إلى ميزات WMI، يمكنك الحصول على كافة المعلومات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top