İşletim sistemi düzeyinde sistem bilgileri alın


232

Şu anda birçok farklı platformda çalıştırılabilecek bir Java uygulaması geliştiriyorum, ancak öncelikle Solaris, Linux ve Windows varyantları.

Kullanılan geçerli disk alanı, CPU kullanımı ve temel işletim sisteminde kullanılan bellek gibi bilgileri başarılı bir şekilde çıkarabilen var mı? Java uygulamasının kendisi ne tüketiyor?

Tercihen bu bilgileri JNI kullanmadan almak istiyorum.


3
Boş hafıza ile ilgili olarak bkz. Stackoverflow.com/a/18366283/231397 ( Runtime.getRuntime().freeMemory()kabul edilen cevapta önerildiği gibi size boş hafıza miktarı
Christian Fries

Yanıtlar:


206

Runtime sınıfından bazı sınırlı bellek bilgileri alabilirsiniz. Tam olarak aradığınız şey değil, ama tamlık uğruna sağlayacağımı düşündüm. İşte küçük bir örnek. Düzenleme: Ayrıca disk kullanım bilgilerini java.io.File sınıfından da alabilirsiniz. Disk alanı kullanımı için Java 1.6 veya üstü gerekir.

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
"Şu anda JVM tarafından kullanılan toplam bellek" biraz kafa karıştırıcı olduğunu düşünüyorum. Javadoc o fonksiyon döner diyor "bayt cinsinden ölçülür mevcut ve gelecekteki nesneler, şu anda kullanılabilir toplam bellek miktarını." Daha çok hafızada kalıyor ve kullanılmıyor gibi görünüyor.
Dirk

@Dirk: Yorumunuzu ele almak için ifadeyi güncelledim. Teşekkürler!
William Brendel

@LeonardoGaldioli: Bu sınıfların ve yöntemlerin performans özelliklerini bilmiyorum, ancak hız için optimize edilmezlerse şaşırmazdım. Diğer cevaplar, JMX kullanarak daha hızlı olabilecek bazı bilgilerin nasıl toplanacağını açıklar.
William Brendel

15
Bu soruya doğru cevap vermiyor. Tüm bu veriler JVM'ye ve işletim sistemine değil ...
Alvaro

Bu konunun oldukça eski olduğunu biliyorum. AMA: Gerçekten cpu çekirdeği miktarına ihtiyacınız varsa, bu çözümü kullanmayın. Her çekirdek için iki iş parçacığı olan çift çekirdekli bir CPU'm var. JVM donanım çekirdeklerini değil, yazılım çekirdeklerini / iş parçacıklarını döndürür.
F_Schmidt

95

Java.lang.management paketi size Runtime daha bir sürü daha bilgi vermek yok - örneğin bu size yığın bellek verecektir ( ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()) (non-yığın bellekten ayrı ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()).

İşlem CPU kullanımı da alabilirsiniz (kendi JNI kodunuzu yazmadan), ancak java.lang.management.OperatingSystemMXBeanbir com.sun.management.OperatingSystemMXBean. Bu Windows ve Linux üzerinde çalışıyor, başka bir yerde test etmedim.

Örneğin ... daha doğru okumalar elde etmek için get getCpuUsage () yöntemini daha sık çağırın.

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
O, derlemek döküm yerine almak için OperatingSystemMXBeaniçin com.sun.management.OperatingSystemMXBeanve tüm örneklerini önsöz getOperatingSystemMXBean()ile ManagementFactory.. Tüm sınıfları uygun şekilde içe aktarmanız gerekir.
tmarthal

2
her şey için 0 olarak cpu kullanımı alıyorum. cpu kullanım formülünü cpuUsage = processCpuTime / systemTime olarak değiştirdim. anlamıyorum cpu kullanımı için bir değer alıyorum.
Raj

yapar 1.0 den sonuç olarak getCpuUsagesistem tüm kullanılarak olduğundan ortalama availableProcessors % 100?
user454322

2
@Raj'ın dediği gibi her zaman 0 alıyorum ... Bu kodu nasıl kullanacağınıza bir örnek verebilir misiniz?
dm76

1
Deneyin((double)( processCpuTime - lastProcessCpuTime )) / ((double)( systemTime - lastSystemTime ))
Anthony O.

43

Bence en iyi yöntem Hyperic'in SIGAR API'sini uygulamak . Büyük işletim sistemlerinin çoğu için çalışır (modern her şeyin yakınında darn) ve çalışmak çok kolaydır. Geliştiriciler forumlarında ve posta listelerinde çok duyarlı. Ayrıca GPL2 Apache lisanslı olmasını seviyorum . Java'da da bir ton örnek veriyorlar!

SIGAR == Sistem Bilgisi, Toplama ve Raporlama aracı.


2
@Yohan - Tembel olma! Bağlantılı web sayfasını okuyarak bunu öğrenebilirsiniz . (Ve bu, "platformdan bağımsız" ile ne demek istediğinize bağlıdır.)
Stephen C

2
@StephenC: Sigar .dll dosyalarını kullanıyor ve bu da platformu bağımlı kılıyor. Daha yüksek seviye API Java'da olabilir, farklı bir hikaye
Lemon Juice

1
@Artificial_Intelligence evet, ancak en popüler platformlar için kütüphaneler (c ile yazılmış) sağlar. Jvm'den daha fazla platforma bağımlı değildir. Üst düzey Java API'sı tüm platformlarda tutarlı olmalıdır.
Jeshurun

8
Sigar 2010'dan beri güncellenmiyor ve 64 bit sistemlerde bir hata var gibi görünüyor: stackoverflow.com/questions/23405832/…
Alvaro

1
Ve SIGAR da (aralıklı olsa da) JVM kazasında yapar ama eminim ki üretimde bu riski almayacak.
AKS

25

JNA kullanan bir Java projesi var (kurulum için yerel kütüphaneler yok) ve aktif geliştirme aşamasında. Şu anda Linux, OSX, Windows, Solaris ve FreeBSD'yi destekliyor ve RAM, CPU, Pil ve dosya sistemi bilgileri sağlıyor.


Hiçbir yerel kütüphane belki yanıltıcı değildir. Proje , hiç yazmamış olsalar bile yerel kütüphaneleri kullanır ve görünüşe göre herhangi bir tane yüklemenize gerek yoktur.
Stephen C

1
Haklısın. JNA, yerel bileşenleri olan libffi kullanır. Ancak tüm amaçlar için, yerel kütüphaneler yok gibi görünüyor (kesinlikle kurulacak hiçbiri yok).
dB.

@StephenC, söylediklerinizin doğru olmasına rağmen, yanıltıcı çünkü yerel yöntemleri de çağıran rt.jar için aynıdır. insanların yerel yöntemleri önemsemesinin tek nedeni, bunları derlemek ve / veya kurmak zorunda olmalarıdır, ki bu genellikle önemsiz bir görevdir. libffi çok geniş bir şekilde kabul edildiğinden, taşındığından ve kurulduğundan, zorlukları azaltır. yani teknik olarak haklısınız, ama pratikte önemli değil.
rbp

@rbp - Deneyimli Java geliştiricilerinin yerel kitaplıklardan kaçınmayı tercih etmelerinin başka bir nedeni daha var . Hata içeren yerel bir kütüphane (iş parçacığı güvenliği sorunları veya bellek yönetimiyle ilgili sorunlar dahil), ana bilgisayar JVM'sinin dengesini bozabilir. Bu bir "önemli değil" sorunu değil ....
Stephen C

@StephenC weblogic uygulama sunucusunu yazmış olmak beni yeterince deneyimlemiş mi?
rbp

13

Pencereler için bu tarafa gittim.

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

İşte ayrıntılarla bağlantı .


11

System.getenv()İlgili ortam değişkeni adını parametre olarak ileterek, kullanarak sistem düzeyinde bazı bilgiler alabilirsiniz . Örneğin, Windows'ta:

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

Diğer işletim sistemleri için, ilgili ortam değişkenlerinin varlığı / yokluğu ve adları farklılık gösterecektir.


1
Bunlar platforma bağlıdır, çünkü değişken adları sistemler arasında farklıdır. Çevre değişkenleri hakkındaki Oracle makalesi bunu anlatıyor. Ayrıca sistemi bağımsız bir şekilde elde etmenin bir yolunu da buluyorum.
Limon Suyu

Linux altında (Ubuntu 17.10) ortamdaki işlemciler hakkında çok fazla ilginç bilgi yoktur.
pveentjer

8

Maaven üzerinden OSHI bağımlılığı ekleyin:

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

Pil kapasitesini yüzde olarak bırakın:

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, diğer yorumlarda açıklanan bilgilerin çoğuna sahiptir. Mümkün olduğunda işletim sistemi yerel çağrıları yoluyla almak için JNA kullanır.
Daniel Widdis

6

Java.lang.management paketinde bulunan API'lara bir göz atın . Örneğin:

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

İçinde başka yararlı şeyler de var.


2
OperatingSystemMXBean.getSystemLoadAverage (), "çok pahalı" olduğundan pencerelerde uygulanmaz
MikeNereson

1
ThreadMXBean.getCurrentThreadCpuTime () yalnızca iş parçacığının ne kadar süredir çalıştığını döndürür. İşlemci kullanım yüzdesi değil.
MikeNereson

5

Genellikle, düşük seviyeli işletim sistemi bilgilerini almak için, Runtime.exec () ile istediğiniz bilgileri veren işletim sistemine özgü komutları çağırabilir veya Linux'ta / proc / * gibi dosyaları okuyabilirsiniz.


5

CPU kullanımı kolay değildir - com.sun.management.OperatingSystemMXBean.getProcessCpuTime üzerinden java.lang.management yaklaşır (yukarıdaki Patrick'in mükemmel kod snippet'ine bakın), ancak yalnızca CPU'nun işleminizde geçirdiği zamana erişim sağladığını unutmayın. size diğer işlemlerde harcanan CPU zamanı ve hatta işleminizle ilgili sistem aktiviteleri yapmak için harcanan CPU zamanı hakkında bilgi vermez.

örneğin ağ yoğun bir java işlemi var - çalışan tek şey ve CPU% 99 ama bunun sadece% 55 "işlemci CPU" olarak bildirildi.

MX fasulyesindeki tek cpu ile ilgili ürün olmasına rağmen, işe yaramazın yanında olduğu için beni "ortalama yük" ile çalıştırmama bile gerek yok. eğer sadece ara sıra bilgeliklerinde güneş "getTotalCpuTime" gibi bir şey ortaya çıkarsa ...

ciddi CPU izleme için Matt tarafından bahsedilen SIGAR en iyi bahis gibi görünüyor.


4

Açık olarak Windows, systeminfokomutu çalıştırabilir ve çıktısını örneğin aşağıdaki kodla alabilirsiniz:

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 kullanıyorsanız, VM CPU kullanımı almanın başka bir yolu. Çalışma zamanı çekirdeği, işlemci başına CPU yükü de verebilir. Tomcat performansını gözlemlemek için bunu sadece Red Hat Linux'ta kullandım. Bunun çalışması için catalina.sh dosyasında JMX uzaktan kumandayı etkinleştirmelisiniz.

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

Hala geliştirilme aşamasındadır, ancak jHardware'i zaten kullanabilirsiniz

Java kullanarak sistem verilerini not eden basit bir kütüphanedir. Hem Linux hem de Windows'da çalışır.

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

Güzel, ama ihtiyaçlarımla çelişen Guava ve JNA sürümlerini kullanıyor (örn. GLASSFISH-21367 ).
lu_ko

Merhaba, JNA 0.8 jHardware sürümünde tanıtıldı. Sadece sıcaklık ve sensör verileri için kullanılır. Bu bilgilere ihtiyacınız yoksa 0.7 sürümünü kullanabilirsiniz. Guava için de aynı şey geçerli. Bu durumda 0.6.3 sürümünü kullanmanız gerekecektir.
profesor_falken

2

İşletim sistemi düzeyinde bilgi almak için kullanılabilecek basit bir yol ve Mac'imde iyi çalışan test ettim:

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

İşletim sisteminin birçok alakalı metrikini burada bulabilirsiniz


1

Hey bunu java / com entegrasyonu ile yapabilirsiniz. WMI özelliklerine erişerek tüm bilgileri alabilirsiniz.


0

Java yükünün içinde 1 dakika, 5 dakika ve 15 dakika Sistem Yükü ortalaması elde etmek için, komutu cat /proc/loadavgaşağıdaki gibi kullanarak ve yorumlayarak yapabilirsiniz:

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

Ve komutu çalıştırarak ve ardından aşağıdaki gibi yorumlayarak fiziksel sistem belleğini elde etmek için 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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.