Java'da CPU ve Bellek Kullanımını nasıl kontrol ederim?


Yanıtlar:


73

Özellikle JVM'de bellek arıyorsanız:

Runtime runtime = Runtime.getRuntime();

NumberFormat format = NumberFormat.getInstance();

StringBuilder sb = new StringBuilder();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();

sb.append("free memory: " + format.format(freeMemory / 1024) + "<br/>");
sb.append("allocated memory: " + format.format(allocatedMemory / 1024) + "<br/>");
sb.append("max memory: " + format.format(maxMemory / 1024) + "<br/>");
sb.append("total free memory: " + format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024) + "<br/>");

Ancak, bunlar sadece bir tahmin olarak alınmalıdır ...


Yani Eclipse'de koşarsam, bu benim Eclipse ayarlarıma bağlı mı?
Kahve

4
Bunun gerçek kullanılan bellek olmadığını unutmayın - bu, java'nın ayırdığı yığın anlamına gelen 'tahsis edilmiş bellek'tir, bu nedenle -Xms90g'ye sahipseniz ve uygulamanız çok hafifse, yine de tahsis edilmiş Bellek'i 90 g'den büyük bir şey olarak alacaksınız. . Aşağıdaki "bilinmeyen (yahoo)" tarafından verilen yanıtı görün (ilk bakışta farklı olabilir)
0fnt

Merak ediyorum, neden bunlar sadece bir tahmin olsun?
ComputerScientist

@ComputerScientist Ücretsiz aslında bedava olan şey olduğu için (GC sonrası) GC'yi bekleyen nesneleri göstermez. ÇOK daha doğru sonuçlar elde etmek için, bu yanıttan önce 2 çöp toplama işlemi yapın. GC ile ve GC olmadan denerseniz, GC sonrası değerleri çok tutarlı bulacaksınız, ancak preGC genellikle bunların en az iki katı olacaktır.
Bill K

@sbeliakov JavaSysmon'u ( github.com/jezhumble/javasysmon ) kullanabilirsiniz , ancak yeni bir soru açmanızı öneririm ve cevaplayacağım. GitHub'daki kütüphanede bir hata var ve 32 biti 64 bit olarak tanıyor, ancak farklı kavanozları karıştırmakla ilgili bir çalışma buldum [ github.com/goxr3plus/XR3Player/blob/master/resources/libs/… ].
GOXR3PLUS

20
package mkd.Utils;

import java.io.File;
import java.text.NumberFormat;

public class systemInfo {

    private Runtime runtime = Runtime.getRuntime();

    public String Info() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.OsInfo());
        sb.append(this.MemInfo());
        sb.append(this.DiskInfo());
        return sb.toString();
    }

    public String OSname() {
        return System.getProperty("os.name");
    }

    public String OSversion() {
        return System.getProperty("os.version");
    }

    public String OsArch() {
        return System.getProperty("os.arch");
    }

    public long totalMem() {
        return Runtime.getRuntime().totalMemory();
    }

    public long usedMem() {
        return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    }

    public String MemInfo() {
        NumberFormat format = NumberFormat.getInstance();
        StringBuilder sb = new StringBuilder();
        long maxMemory = runtime.maxMemory();
        long allocatedMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        sb.append("Free memory: ");
        sb.append(format.format(freeMemory / 1024));
        sb.append("<br/>");
        sb.append("Allocated memory: ");
        sb.append(format.format(allocatedMemory / 1024));
        sb.append("<br/>");
        sb.append("Max memory: ");
        sb.append(format.format(maxMemory / 1024));
        sb.append("<br/>");
        sb.append("Total free memory: ");
        sb.append(format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024));
        sb.append("<br/>");
        return sb.toString();

    }

    public String OsInfo() {
        StringBuilder sb = new StringBuilder();
        sb.append("OS: ");
        sb.append(this.OSname());
        sb.append("<br/>");
        sb.append("Version: ");
        sb.append(this.OSversion());
        sb.append("<br/>");
        sb.append(": ");
        sb.append(this.OsArch());
        sb.append("<br/>");
        sb.append("Available processors (cores): ");
        sb.append(runtime.availableProcessors());
        sb.append("<br/>");
        return sb.toString();
    }

    public String DiskInfo() {
        /* Get a list of all filesystem roots on this system */
        File[] roots = File.listRoots();
        StringBuilder sb = new StringBuilder();

        /* For each filesystem root, print some info */
        for (File root : roots) {
            sb.append("File system root: ");
            sb.append(root.getAbsolutePath());
            sb.append("<br/>");
            sb.append("Total space (bytes): ");
            sb.append(root.getTotalSpace());
            sb.append("<br/>");
            sb.append("Free space (bytes): ");
            sb.append(root.getFreeSpace());
            sb.append("<br/>");
            sb.append("Usable space (bytes): ");
            sb.append(root.getUsableSpace());
            sb.append("<br/>");
        }
        return sb.toString();
    }
}

anladığım kadarıyla konu işletim sistemindeki kullanılabilir bellek miktarı hakkında soru sormaktı. freeMemoryburada
JVM'de

SystemInfo sınıfınızın bir Capital ile başlamaması ve yöntemlerinizin Info (), OSname (), MemInfo () başlaması garip değil mi?
Drswaki69

18

Sun JVM kullanıyorsanız ve uygulamanın dahili bellek kullanımıyla ilgileniyorsanız (uygulamanız ayrılan belleğin ne kadarını kullanıyor) JVM'nin yerleşik çöp toplama günlüğünü açmayı tercih ederim. Başlangıç ​​komutuna basitçe -verbose: gc eklersiniz.

Sun belgelerinden:

-Verbose: gc komut satırı argümanı, her koleksiyonda bilgi yazdırır. -Verbose: gc çıktısının biçiminin J2SE platformunun sürümleri arasında değişebileceğini unutmayın. Örneğin, burada büyük bir sunucu uygulamasından çıktı verilmiştir:

[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]

Burada iki küçük koleksiyon ve bir büyük koleksiyon görüyoruz. Oktan önceki ve sonraki sayılar

325407K->83000K (in the first line)

sırasıyla çöp toplamadan önce ve sonra canlı nesnelerin birleşik boyutunu gösterir. Küçük koleksiyonlardan sonra sayı, canlı olmayan ancak doğrudan canlı oldukları için ya da görevli nesil içinde oldukları veya bunlara referans verildikleri için geri alınamayacak nesneleri içerir. Parantez içindeki sayı

(776768K) (in the first line)

Kalıcı nesildeki alanı saymayan toplam kullanılabilir alandır, toplam yığın eksi hayatta kalan alanlardan biridir. Küçük koleksiyon yaklaşık bir saniyenin dörtte birini aldı.

0.2300771 secs (in the first line)

Daha fazla bilgi için bkz: http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html


17

Gönderen burada

    OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
    int availableProcessors = operatingSystemMXBean.getAvailableProcessors();
    long prevUpTime = runtimeMXBean.getUptime();
    long prevProcessCpuTime = operatingSystemMXBean.getProcessCpuTime();
    double cpuUsage;
    try
    {
        Thread.sleep(500);
    }
    catch (Exception ignored) { }

    operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    long upTime = runtimeMXBean.getUptime();
    long processCpuTime = operatingSystemMXBean.getProcessCpuTime();
    long elapsedCpu = processCpuTime - prevProcessCpuTime;
    long elapsedTime = upTime - prevUpTime;

    cpuUsage = Math.min(99F, elapsedCpu / (elapsedTime * 10000F * availableProcessors));
    System.out.println("Java CPU: " + cpuUsage);

1
Ve hafıza hakkında?
Daniel De León

2
Liste <BellekPoolMXBean> memoryPools = new ArrayList <MemoryPoolMXBean> (ManagementFactory.getMemoryPoolMXBeans ()); uzun süre usedHeapMemoryAfterLastGC = 0; for (MemoryPoolMXBean memoryPool: memoryPools) {if (memoryPool.getType (). equals (MemoryType.HEAP)) {MemoryUsage poolCollectionMemoryUsage = memoryPool.getCollectionUsage (); usedHeapMemoryAfterLastGC + = poolCollectionMemoryUsage.getUsed (); }}
danieln

1
CPU kullanımı alımını gösteren tek yanıt için teşekkür ederiz.
Matthieu

1
Bunu yapmakla basitçe yapmak arasındaki fark nedir operatingSystemMXBean.getProcessCpuLoad();? Oracle belgelerine göre, bu yöntem "Java Sanal Makinesi işlemi için" son cpu kullanımını "döndürür." Yine de sizin yönteminizle bu yöntem arasında görece büyük bir fark görüyorum.
Ishnark

1
@RobHall İki OperatingSystemMXBeansınıf var. Biri, sağlanan arabirimdir java.lang. Ama bunu genişleten başka bir versiyon daha var com.sun.management. OperatingSystemMXBean
Bahsettiğim

9

Sağlanan JMX, MXBeans (ThreadMXBean, vb.) Size Bellek ve CPU kullanımları sağlayacaktır.

OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
operatingSystemMXBean.getSystemCpuLoad();

8

Bellek kullanımı için aşağıdakiler çalışacaktır,

long total = Runtime.getRuntime().totalMemory();
long used  = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

CPU kullanımı için, ölçmek için harici bir uygulama kullanmanız gerekecektir.


6

Java 1.5'ten bu yana, JDK yeni bir araçla birlikte gelir: size herhangi bir 1.5 veya sonraki JVM'nin CPU ve bellek kullanımını gösterebilen JConsole . Bu parametrelerin grafiklerini yapabilir, CSV'ye aktarabilir, yüklenen sınıfların sayısını, örneklerin sayısını, kilitlenmeleri, iş parçacıkları vb. Gösterebilir ...


4

Burada birçok yanıtta gönderilmiş olan çalışma zamanı / totalMemory çözümünü kullanıyorsanız (bunu çok yaptım), oldukça doğru / tutarlı sonuçlar istiyorsanız önce iki çöp toplamayı zorladığınızdan emin olun.

Verimlilik için Java genellikle çöpün bir GC'yi zorlamadan önce tüm belleği doldurmasına izin verir ve bu durumda bile genellikle tam bir GC değildir, bu nedenle runtime.freeMemory () için sonuçlarınız her zaman "gerçek" boş bellek miktarı ile 0 arasında bir yerde olur .

İlk GC her şeyi almaz, çoğunu alır.

Yükseliş şu ki, sadece freeMemory () çağrısını yaparsanız, kesinlikle yararsız olan ve büyük ölçüde değişen bir numara alacaksınız, ancak 2 gc'yi ilk yaparsanız çok güvenilir bir ölçümdür. Ayrıca rutini ÇOK yavaşlatır (muhtemelen saniyeler).


3

Java'nın Runtime nesnesi, JVM'nin bellek kullanımını bildirebilir. CPU tüketimi için Unix'in top veya Windows Process Manager gibi harici bir yardımcı program kullanmanız gerekir.


2

JConsole , çalışan bir Java uygulamasını izlemenin kolay bir yoludur veya uygulamanız hakkında daha ayrıntılı bilgi almak için bir Profiler kullanabilirsiniz. Bunun için NetBeans Profiler'ı kullanmayı seviyorum .


2

Mevcut bellek kullanımını megabayt cinsinden hesaplamak için bazı basit kodlar:

double currentMemory = ( (double)((double)(Runtime.getRuntime().totalMemory()/1024)/1024))- ((double)((double)(Runtime.getRuntime().freeMemory()/1024)/1024));

2

Ayrıca CPU Yükünü izlemek için şu yolu eklerdim:

import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;

double getCpuLoad() {
    OperatingSystemMXBean osBean =
        (com.sun.management.OperatingSystemMXBean) ManagementFactory.
        getPlatformMXBeans(OperatingSystemMXBean.class);
    return osBean.getProcessCpuLoad();
}

Daha fazlasını buradan okuyabilirsiniz




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.