Làm cách nào để kiểm tra mức sử dụng CPU và bộ nhớ trong Java?


97

Tôi cần kiểm tra việc sử dụng CPU và bộ nhớ cho máy chủ trong java, có ai biết cách thực hiện không?



Câu trả lời:


73

Nếu bạn đang tìm kiếm cụ thể cho bộ nhớ trong JVM:

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

Tuy nhiên, những điều này chỉ nên được coi là ước tính ...


Vì vậy, nếu tôi chạy trong Eclipse, điều này sẽ phụ thuộc vào cài đặt Eclipse của tôi?
Cà phê

4
Lưu ý rằng đây không phải là bộ nhớ được sử dụng thực tế - đây là 'bộ nhớ được cấp phát' có nghĩa là heap mà java đã cấp phát, vì vậy nếu bạn có -Xms90g và ứng dụng của bạn rất nhẹ, bạn sẽ vẫn nhận được phân bổMemory là một thứ lớn hơn 90g . Xem câu trả lời bằng cách xóa "không xác định (yahoo)" bên dưới (cái nhìn đầu tiên có thể khác)
0fnt

Chỉ tò mò, tại sao những điều này chỉ là một ước tính?
Máy tính Khoa học

@ComputerScientist Vì miễn phí thực sự là miễn phí (đăng GC) nên nó không hiển thị các đối tượng đang chờ GC. Để chính xác hơn, hãy chạy 2 bộ sưu tập rác trước câu trả lời này. Nếu bạn thử nó có và không có GC, bạn sẽ thấy các giá trị sau GC rất nhất quán nhưng preGC nói chung sẽ ít nhất gấp đôi các giá trị đó.
Bill K

@sbeliakov Bạn có thể sử dụng JavaSysmon ( github.com/jezhumble/javasysmon ), mặc dù tôi khuyên bạn nên mở một câu hỏi mới và tôi sẽ trả lời nó. Thư viện trên GitHub có một lỗi và nhận dạng 32 bit là 64 bit, nhưng tôi đã tìm thấy một công việc xoay quanh việc trộn các lọ khác nhau [ 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();
    }
}

tôi hiểu rằng chủ đề bắt đầu là hỏi về dung lượng bộ nhớ có sẵn trong hệ điều hành. freeMemoryở đây trả về dung lượng bộ nhớ có sẵn trong JVM rất khác
Tagar

Không có gì lạ khi lớp SystemInfo của bạn không bắt đầu bằng Capital và các phương thức Info (), OSname (), MemInfo () của bạn thì có?
Drswaki69

18

Nếu bạn đang sử dụng Sun JVM và quan tâm đến việc sử dụng bộ nhớ trong của ứng dụng (bao nhiêu trong số bộ nhớ được cấp phát mà ứng dụng của bạn đang sử dụng), tôi muốn bật tính năng ghi nhật ký thu gom rác tích hợp sẵn của JVM. Bạn chỉ cần thêm -verbose: gc vào lệnh khởi động.

Tài liệu từ Mặt trời:

Đối số dòng lệnh -verbose: gc in thông tin ở mọi bộ sưu tập. Lưu ý rằng định dạng của đầu ra -verbose: gc có thể thay đổi giữa các bản phát hành của nền tảng J2SE. Ví dụ, đây là đầu ra từ một ứng dụng máy chủ lớn:

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

Ở đây chúng ta thấy hai bộ sưu tập nhỏ và một bộ sưu tập lớn. Các số trước và sau mũi tên

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

cho biết kích thước tổng hợp của các vật thể sống trước và sau khi thu gom rác tương ứng. Sau các bộ sưu tập nhỏ, số lượng bao gồm các đối tượng không nhất thiết phải còn sống nhưng không thể lấy lại được, vì chúng còn sống trực tiếp hoặc vì chúng nằm trong hoặc được tham chiếu từ thế hệ được sử dụng. Số trong ngoặc đơn

(776768K) (in the first line)

là tổng không gian có sẵn, không tính khoảng trống trong thế hệ vĩnh viễn, là tổng số đống trừ đi một trong những không gian sống sót. Bộ sưu tập nhỏ diễn ra trong khoảng một phần tư giây.

0.2300771 secs (in the first line)

Để biết thêm thông tin, hãy xem: http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html


17

Từ đây

    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
Và về bộ nhớ?
Daniel De León

2
Danh sách <MemoryPoolMXBean> memoryPools = new ArrayList <MemoryPoolMXBean> (ManagementFactory.getMemoryPoolMXBeans ()); đã sử dụng lâuHeapMemoryAfterLastGC = 0; for (MemoryPoolMXBean memoryPool: memoryPools) {if (memoryPool.getType (). equals (MemoryType.HEAP)) {MemoryUsage poolCollectionMemoryUsage = memoryPool.getCollectionUsage (); usedHeapMemoryAfterLastGC + = poolCollectionMemoryUsage.getUsed (); }}
danieln

1
Cảm ơn bạn vì câu trả lời duy nhất hiển thị truy xuất mức sử dụng CPU.
Matthieu

1
Sự khác biệt giữa làm điều này và làm đơn giản là gì operatingSystemMXBean.getProcessCpuLoad();? Theo tài liệu của Oracle, phương thức này trả về "Trả về" việc sử dụng cpu gần đây "cho quy trình Máy ảo Java." Tuy nhiên, tôi thấy có sự khác biệt tương đối lớn giữa phương pháp của bạn và phương pháp này.
Ishnark

1
@RobHall Có hai OperatingSystemMXBeanlớp. Một là giao diện được cung cấp trong java.lang. Nhưng cũng có một phiên bản khác, mở rộng phiên bản này trong com.sun.management. Đó là phương pháp tôi đã đề cập đến là từ đóOperatingSystemMXBean
Ishnark

9

JMX, MXBeans (ThreadMXBean, v.v.) được cung cấp sẽ cung cấp cho bạn cách sử dụng Bộ nhớ và CPU.

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

8

Đối với việc sử dụng bộ nhớ, cách sau sẽ hoạt động,

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

Đối với việc sử dụng CPU, bạn sẽ cần sử dụng một ứng dụng bên ngoài để đo nó.


5

Kể từ Java 1.5, JDK đi kèm với một công cụ mới: JConsole wich có thể hiển thị cho bạn mức sử dụng CPU và bộ nhớ của bất kỳ JVM 1.5 trở lên nào. Nó có thể thực hiện các biểu đồ của các tham số này, xuất sang CSV, hiển thị số lượng các lớp được tải, số lượng phiên bản, deadlock, luồng, v.v.


4

Nếu bạn sử dụng giải pháp runtime / totalMemory đã được đăng trong nhiều câu trả lời ở đây (tôi đã làm điều đó rất nhiều), hãy đảm bảo buộc hai bộ sưu tập rác trước tiên nếu bạn muốn kết quả tương đối chính xác / nhất quán.

Để có hiệu quả, Java thường cho phép rác lấp đầy tất cả bộ nhớ trước khi buộc GC và thậm chí sau đó nó thường không phải là GC hoàn chỉnh, do đó, kết quả của bạn cho runtime.freeMemory () luôn ở đâu đó giữa lượng bộ nhớ trống "thực" và 0 .

GC đầu tiên không nhận được tất cả mọi thứ, nó nhận được hầu hết.

Điểm đáng chú ý là nếu bạn chỉ thực hiện lệnh gọi freeMemory (), bạn sẽ nhận được một số hoàn toàn vô dụng và rất khác nhau, nhưng nếu thực hiện 2 gc đầu tiên thì đó là một thước đo rất đáng tin cậy. Nó cũng làm cho quy trình chậm hơn RẤT NHIỀU (giây, có thể).


3

Đối tượng Runtime của Java có thể báo cáo việc sử dụng bộ nhớ của JVM. Để tiêu thụ CPU, bạn sẽ phải sử dụng một tiện ích bên ngoài, như Trình quản lý quy trình Windows hoặc Trình quản lý quy trình của Unix.


2

Dưới đây là một số mã đơn giản để tính toán mức sử dụng bộ nhớ hiện tại theo megabyte:

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

2

Tôi cũng sẽ thêm cách sau để theo dõi Tải CPU:

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

Bạn có thể đọc thêm tại đây


1

JConsole là một cách dễ dàng để theo dõi một ứng dụng Java đang chạy hoặc bạn có thể sử dụng Hồ sơ để biết thêm thông tin chi tiết về ứng dụng của mình. Tôi thích sử dụng NetBeans Profiler cho việc này.



1

Nếu bạn đang sử dụng Tomcat, hãy xem Psi Probe , cho phép bạn theo dõi mức tiêu thụ bộ nhớ trong và ngoài cũng như một loạt các khu vực khác.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.