OS- स्तरीय प्रणाली की जानकारी प्राप्त करें


232

मैं वर्तमान में एक जावा ऐप बना रहा हूं जो कई अलग-अलग प्लेटफार्मों पर चलाया जा सकता है, लेकिन मुख्य रूप से सोलारिस, लिनक्स और विंडोज के वेरिएंट।

क्या कोई भी वर्तमान डिस्क स्थान, सीपीयू उपयोग और अंतर्निहित ओएस में उपयोग की जाने वाली मेमोरी जैसे जानकारी को सफलतापूर्वक निकालने में सक्षम है? क्या जावा app ही उपभोग कर रहा है के बारे में क्या?

अधिमानतः मैं जेएनआई का उपयोग किए बिना इस जानकारी को प्राप्त करना चाहूंगा।


3
मुफ्त मेमोरी के संबंध में stackoverflow.com/a/18366283/231397 देखें ( Runtime.getRuntime().freeMemory()जैसा कि स्वीकृत उत्तर में सुझाया गया है, आपको मुफ्त मेमोरी की राशि नहीं दी गई है।
क्रिश्चियन फ्राइज़

जवाबों:


206

आप रनटाइम क्लास से कुछ सीमित मेमोरी जानकारी प्राप्त कर सकते हैं। यह वास्तव में वैसा नहीं है जैसा आप देख रहे हैं, लेकिन मैंने सोचा कि मैं इसे पूर्णता के लिए प्रदान करूंगा। यहाँ एक छोटा सा उदाहरण है। संपादित करें: आप java.io.File वर्ग से डिस्क उपयोग की जानकारी भी प्राप्त कर सकते हैं। डिस्क स्थान उपयोग सामग्री के लिए जावा 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());
    }
  }
}

7
मुझे लगता है कि "JVM द्वारा वर्तमान में उपयोग की जाने वाली कुल मेमोरी" थोड़ी भ्रमित करने वाली है। जावाडोक कि समारोह रिटर्न कहते हैं, "वर्तमान में वर्तमान और भविष्य की वस्तुओं, बाइट में मापा के लिए उपलब्ध स्मृति की कुल राशि।" शेष स्मृति की तरह लगता है और उपयोग में नहीं है।
डर्क

@ डर्क: मैंने आपकी टिप्पणी को संबोधित करने के लिए शब्दांकन अपडेट किया। धन्यवाद!
विलियम ब्रेंडेल

@ लियोनार्डो वाल्डिओली: मैं इन वर्गों और विधियों के प्रदर्शन की विशेषताओं को नहीं जानता, लेकिन मुझे आश्चर्य नहीं होगा यदि वे गति के लिए अनुकूलित नहीं थे। अन्य उत्तर बताते हैं कि जेएमएक्स का उपयोग करके कुछ जानकारी कैसे एकत्र की जाए, जो तेज हो सकती है।
विलियम ब्रेंडेल

15
यह प्रश्न का सही उत्तर नहीं देता है। वह सब डेटा जेवीएम पर निर्भर करता है और ओएस के लिए नहीं ...
अल्वारो

मुझे पता है कि यह विषय काफी पुराना है। लेकिन: यदि आपको वास्तव में सीपीयू कोर की मात्रा की आवश्यकता है, तो इस समाधान का उपयोग न करें। मेरे पास प्रत्येक कोर के लिए दो धागे के साथ एक दोहरे कोर सीपीयू है। JVM हार्डवेयर कोर को नहीं लौटाता है, बल्कि सॉफ्टवेयर कोर / थ्रेड्स को लौटाता है।
F_Schmidt

95

Java.lang.management पैकेज आप क्रम से और भी बहुत कुछ जानकारी देता है - उदाहरण के लिए यह आप ढेर स्मृति दे देंगे ( ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()) गैर ढेर स्मृति से अलग ( ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage())।

आप सीपीयू उपयोग की प्रक्रिया भी प्राप्त कर सकते हैं (अपना जेएनआई कोड लिखे बिना), लेकिन आपको java.lang.management.OperatingSystemMXBeanएक कास्ट करने की आवश्यकता है com.sun.management.OperatingSystemMXBean। यह विंडोज और लिनक्स पर काम करता है, मैंने इसे कहीं और परीक्षण नहीं किया है।

उदाहरण के लिए ... अधिक सटीक रीडिंग प्राप्त करने के लिए 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();
        }
    }
}

10
इसे संकलित करने के लिए, कलाकारों OperatingSystemMXBeanको प्रतिस्थापित करें com.sun.management.OperatingSystemMXBeanऔर सभी उदाहरणों को प्रस्तुत getOperatingSystemMXBean()करें ManagementFactory.। आपको सभी वर्गों को उचित रूप से आयात करने की आवश्यकता है।
tmarthal

2
मैं सब कुछ के लिए 0 के रूप में CPU उपयोग कर रहा हूँ। मैंने cpu उपयोग सूत्र को cpuUsage = processCpuTime / systemTime में बदल दिया। मुझे सीपीयू के उपयोग के लिए एक मूल्य मिल रहा है जो मुझे समझ में नहीं आ रहा है।
राज

करता है 1.0 से परिणाम के रूप में getCpuUsageमतलब है कि प्रणाली का उपयोग करते हुए अपने सभी है availableProcessors 100% पर?
user454322

2
मुझे हमेशा 0 मिलता है क्योंकि @ राज ने कहा ... क्या आप उस कोड का उपयोग करने का एक उदाहरण दे सकते हैं?
dm76

1
कोशिश करें((double)( processCpuTime - lastProcessCpuTime )) / ((double)( systemTime - lastSystemTime ))
एंथनी ओ

43

मुझे लगता है कि हाइपरिक द्वारा SIGAR एपीआई को लागू करने के लिए सबसे अच्छा तरीका है । यह अधिकांश प्रमुख ऑपरेटिंग सिस्टमों के लिए काम करता है (आधुनिक कुछ भी पास नहीं है) और इसके साथ काम करना बहुत आसान है। डेवलपर अपने फ़ोरम और मेलिंग सूचियों पर बहुत संवेदनशील हैं। मुझे यह भी पसंद है कि यह GPL2 है Apache लाइसेंस है । वे जावा में उदाहरणों का एक टन भी प्रदान करते हैं!

सिगार == सिस्टम सूचना, सभा और रिपोर्टिंग उपकरण।


2
@ योहान - आलसी मत बनो! आप लिंक किए गए वेबपेज को पढ़कर इसका पता लगा सकते हैं । (और यह इस बात पर निर्भर करता है कि "प्लेटफ़ॉर्म इंडिपेंडेंट" से आपका क्या मतलब है।)
स्टीफन C

2
@StephenC: सिगार .dll फ़ाइलों का उपयोग कर रहा है, जो इसे प्लेटफ़ॉर्म पर निर्भर करता है। उच्च स्तरीय एपीआई जावा में हो सकता है, यह एक अलग कहानी है
लेमन जूस

1
@Artific_Intelligence हाँ, लेकिन यह सबसे लोकप्रिय प्लेटफार्मों के लिए पुस्तकालय (सी में लिखित) प्रदान करता है। यह jvm से ज्यादा भरोसेमंद प्लेटफॉर्म नहीं है। उच्च स्तरीय जावा एपीआई सभी प्लेटफार्मों पर संगत होना चाहिए।
जशूरुन

8
2010 से सिगार अपडेट नहीं हुआ और 64 बिट सिस्टम पर एक बग लगता है: stackoverflow.com/questions/23405832/…
अल्वारो

1
और SIGAR JVM क्रैश भी बनाता है, (हालांकि रुक-रुक कर) लेकिन मुझे यकीन है कि आप उत्पादन में यह जोखिम नहीं लेंगे।
एकेएस

25

एक जावा प्रोजेक्ट है जो JNA का उपयोग करता है (ताकि कोई मूल लाइब्रेरी स्थापित न हो) और सक्रिय विकास में है। यह वर्तमान में लिनक्स, ओएसएक्स, विंडोज, सोलारिस और फ्रीबीएसडी का समर्थन करता है और रैम, सीपीयू, बैटरी और फाइल सिस्टम जानकारी प्रदान करता है।


कोई भी देशी पुस्तकालय शायद भ्रामक नहीं है। इस परियोजना में देशी पुस्तकालयों का उपयोग किया जाता है, भले ही उन्होंने कोई लिखा न हो, और आपको स्पष्ट रूप से कोई भी स्थापित करने की आवश्यकता नहीं है।
स्टीफन C

1
आप सही हे। जेएनए लिबासि का उपयोग करता है जिसमें मूल घटक होते हैं। लेकिन सभी उद्देश्यों के लिए, यह ऐसा लगता है कि कोई मूल पुस्तकालय नहीं हैं (निश्चित रूप से कोई भी स्थापित नहीं है)।
डीबी।

@StephenC यद्यपि आप जो कहते हैं वह सटीक है, इसकी भ्रामक है क्योंकि इसकी rt.jar के लिए समान है जो देशी तरीकों को भी आमंत्रित करता है। मूल तरीकों के बारे में लोगों को परवाह करने का एकमात्र कारण यह है कि उन्हें उन्हें संकलित करना और / या स्थापित करना है, जो अक्सर एक गैर-तुच्छ कार्य है। चूँकि लीबफ़ी को मोटे तौर पर अपनाया जाता है, पोर्ट किया जाता है, और स्थापित किया जाता है, यह कठिनाइयों को कम करता है। इसलिए, तकनीकी रूप से आप सही हैं, लेकिन व्यावहारिक रूप से, इससे कोई फर्क नहीं पड़ता।
आरबीपी

@rbp - एक और कारण है कि अनुभवी जावा डेवलपर्स देशी पुस्तकालयों से बचना पसंद करते हैं। एक मूल पुस्तकालय जिसमें बग्स (थ्रेड सेफ्टी इश्यू या मेमोरी मैनेजमेंट के साथ समस्याएँ शामिल हैं) होस्ट जेवीएम को अस्थिर करने के लिए उत्तरदायी है। यह एक "यह कोई फर्क नहीं पड़ता" मुद्दा नहीं है ....
स्टीफन C

@StephenC वेबलॉग एप्लिकेशन सर्वर को अधिकृत करता है जिससे मुझे काफी अनुभव हो रहा है?
आरबीपी

13

खिड़कियों के लिए मैं इस तरह से गया था।

    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();

यहाँ विवरण के साथ लिंक है


11

आप System.getenv()एक पैरामीटर के रूप में संबंधित पर्यावरण चर नाम का उपयोग करके , कुछ सिस्टम-स्तरीय जानकारी प्राप्त कर सकते हैं । उदाहरण के लिए, विंडोज पर:

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

अन्य ऑपरेटिंग सिस्टमों के लिए प्रासंगिक पर्यावरण चर की उपस्थिति / अनुपस्थिति और नाम अलग-अलग होंगे।


1
ये प्लेटफ़ॉर्म आश्रित हैं क्योंकि सिस्टम के बीच वेरिएबल नाम अलग हैं। पर्यावरण चर पर ओरेकल लेख बताता है कि। मैं सिस्टम को स्वतंत्र रूप से प्राप्त करने का एक तरीका भी ढूंढ रहा हूं।
लेमन जूस

लिनक्स (Ubuntu 17.10) के तहत वातावरण में प्रोसेसर के संबंध में बहुत दिलचस्प जानकारी नहीं है।
pwentjer

8

मावेन के माध्यम से OSHI निर्भरता जोड़ें:

<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));
}

OSHI के पास अन्य टिप्पणियों में वर्णित अधिकांश जानकारी है। यह संभव होने पर ओएस देशी कॉल के माध्यम से प्राप्त करने के लिए जेएनए का उपयोग करता है।
डैनियल विदिस

6

Java.lang.management पैकेज में उपलब्ध API पर एक नज़र डालें । उदाहरण के लिए:

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

वहाँ के रूप में अच्छी तरह से अन्य उपयोगी चीजों का भार है।


2
OperatingSystemMXBean.getSystemLoadAiture () विंडोज़ में लागू नहीं किया गया है क्योंकि "इसकी बहुत महंगी"
माइकनेसरन

1
ThreadMXBean.getCurrentThreadCpuTime () केवल तभी लौटाता है जब तक कि थ्रेड चल रहा हो। सीपीयू उपयोग प्रतिशत नहीं।
माइकनेर्सन

5

आमतौर पर, निम्न स्तर की OS जानकारी प्राप्त करने के लिए आप OS विशिष्ट आदेशों को कॉल कर सकते हैं जो आपको Runtime.exec () के साथ इच्छित जानकारी देते हैं या लिनक्स में / proc / * जैसी फाइलें पढ़ते हैं।


5

सीपीयू का उपयोग सीधा नहीं है - java.lang.management द्वारा com.sun.management.OperatingSystemMXBean.getProcessCpuTime करीब आता है (ऊपर पैट्रिक का उत्कृष्ट कोड स्निपेट देखें) लेकिन ध्यान दें कि यह केवल सीपीयू को आपकी प्रक्रिया में खर्च किए गए समय तक पहुंच प्रदान करता है। यह आपको अन्य प्रक्रियाओं में खर्च किए गए सीपीयू समय के बारे में नहीं बताएगा, या यहां तक ​​कि आपके प्रक्रिया से संबंधित सिस्टम गतिविधियों को करने में सीपीयू समय भी खर्च करेगा।

उदाहरण के लिए मेरे पास एक नेटवर्क-गहन जावा प्रक्रिया है - यह केवल एक चीज है और सीपीयू 99% पर है, लेकिन इसमें से केवल 55% को "प्रोसेसर सीपीयू" के रूप में रिपोर्ट किया गया है।

एमएक्स बीन पर केवल सीपीयू-संबंधित आइटम होने के बावजूद, मुझे "लोड एवरेज" पर शुरू नहीं करना है। यदि उनके सामयिक ज्ञान में केवल सूर्य ही "getTotalCpuTime" की तरह कुछ उजागर करता है ...

मैट द्वारा उल्लिखित गंभीर CPU मॉनिटरिंग SIGAR के लिए सबसे अच्छा दांव लगता है।


4

पर 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();
    }
}

3

यदि आप Jrockit VM का उपयोग कर रहे हैं तो यहाँ VM CPU उपयोग प्राप्त करने का एक और तरीका है। रनटाइम सेम आपको प्रति प्रोसेसर सीपीयू लोड भी दे सकता है। मैंने इसका उपयोग केवल Red Hat Linux पर Tomcat प्रदर्शन को मानने के लिए किया है। आपको इसके लिए उत्प्रेरित करने के लिए जेएमएक्स रिमोट को सक्षम करना होगा।

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");

3

यह अभी भी विकास के अधीन है लेकिन आप पहले से ही jHardware का उपयोग कर सकते हैं

यह एक सरल पुस्तकालय है जो जावा का उपयोग करके सिस्टम डेटा को स्क्रैप करता है। यह लिनक्स और विंडोज दोनों में काम करता है।

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());
//[...]

अच्छा है, लेकिन यह अमरूद और जेएनए संस्करणों का उपयोग करता है जो मेरी आवश्यकताओं के साथ संघर्ष में हैं (उदाहरण देखें ग्लास-21367 )।
लू_को

नमस्कार, JNA को jHardware के 0.8 संस्करण में पेश किया गया है। यह केवल तापमान और सेंसर डेटा के लिए उपयोग किया जाता है। यदि आपको उस जानकारी की आवश्यकता नहीं है, तो आप 0.7 संस्करण का उपयोग कर सकते हैं। अमरूद के लिए एक ही बात। उस स्थिति में आपको 0.6.3 संस्करण का उपयोग करना होगा।
profesor_falken

2

एक सरल तरीका जिसका उपयोग ओएस स्तर की जानकारी प्राप्त करने के लिए किया जा सकता है और मैंने अपने मैक में परीक्षण किया जो अच्छी तरह से काम करता है:

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

आप ऑपरेटिंग सिस्टम के कई प्रासंगिक मेट्रिक्स यहां पा सकते हैं


1

अरे आप इसे जावा / कॉम एकीकरण के साथ कर सकते हैं। WMI सुविधाओं का उपयोग करके आप सभी जानकारी प्राप्त कर सकते हैं।


0

जावा कोड के अंदर 1 मिनट, 5 मिनट और 15 मिनट का सिस्टम लोड औसत प्राप्त करने के लिए , आप cat /proc/loadavgइसे नीचे दिए गए कमांड का उपयोग करके और इसकी व्याख्या करके कर सकते हैं :

    Runtime runtime = Runtime.getRuntime();

    BufferedReader br = new BufferedReader(
        new InputStreamReader(runtime.exec("cat /proc/loadavg").getInputStream()));

    String avgLine = br.readLine();
    System.out.println(avgLine);
    List<String> avgLineList = Arrays.asList(avgLine.split("\\s+"));
    System.out.println(avgLineList);
    System.out.println("Average load 1 minute : " + avgLineList.get(0));
    System.out.println("Average load 5 minutes : " + avgLineList.get(1));
    System.out.println("Average load 15 minutes : " + avgLineList.get(2));

और कमांड को निष्पादित करके और फिर नीचे के रूप में व्याख्या करके भौतिक सिस्टम मेमोरी प्राप्त करने के लिए free -m:

Runtime runtime = Runtime.getRuntime();

BufferedReader br = new BufferedReader(
    new InputStreamReader(runtime.exec("free -m").getInputStream()));

String line;
String memLine = "";
int index = 0;
while ((line = br.readLine()) != null) {
  if (index == 1) {
    memLine = line;
  }
  index++;
}
//                  total        used        free      shared  buff/cache   available
//    Mem:          15933        3153        9683         310        3097       12148
//    Swap:          3814           0        3814

List<String> memInfoList = Arrays.asList(memLine.split("\\s+"));
int totalSystemMemory = Integer.parseInt(memInfoList.get(1));
int totalSystemUsedMemory = Integer.parseInt(memInfoList.get(2));
int totalSystemFreeMemory = Integer.parseInt(memInfoList.get(3));

System.out.println("Total system memory in mb: " + totalSystemMemory);
System.out.println("Total system used memory in mb: " + totalSystemUsedMemory);
System.out.println("Total system free memory in mb: "   + totalSystemFreeMemory);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.