2010-02-01 22 views
23

Tôi không tìm kiếm thông thường "bạn chỉ có thể gợi ý GC trong Java bằng cách sử dụng System.gc()" câu trả lời, đây không phải là tất cả những gì câu hỏi này là về.Java: Làm thế nào để bạn thực sự buộc một GC bằng cách sử dụng ForceGargabeCollection của JVMTI?

Câu hỏi của tôi không chủ quan và dựa trên thực tế: GC có thể buộc phải thực hiện trong Java. Rất nhiều chương trình mà chúng tôi sử dụng hàng ngày làm điều đó: IntelliJ IDEA, NetBeans, VisualVM.

Tất cả đều có thể buộc GC xảy ra.

Làm cách nào?

Tôi coi là tất cả đều đang sử dụng JVMTI và cụ thể hơn là ForceGarbageCollection (chú ý đến "Force") nhưng làm thế nào tôi có thể tự mình thử?

http://java.sun.com/javase/6/docs/platform/jvmti/jvmti.html#ForceGarbageCollection

Cũng lưu ý rằng câu hỏi này không phải là về "tại sao" Tôi muốn làm điều này: "tại sao" có thể là "tò mò" hoặc "chúng tôi đang viết một chương trình tương tự như VisualVM", v.v.

Câu hỏi thực sự là "làm cách nào để ép buộc GC bằng cách sử dụng ForceGarbageCollection của JVMTI"?

JVM có cần được khởi chạy với bất kỳ thông số đặc biệt nào không?

Có bất kỳ JNI nào được yêu cầu không? Nếu vậy, mã nào chính xác?

Tính năng này chỉ hoạt động trên máy ảo Sun?

Bất kỳ ví dụ hoàn chỉnh và dễ hiểu nào sẽ được chào đón nhiều nhất.

Trả lời

10

NetBeans, ít nhất, sử dụng System.gc(): http://hg.netbeans.org/main/annotate/9779f138a9c9/openide.actions/src/org/openide/actions/GarbageCollectAction.java (đây là nút nhỏ hiển thị vùng hiện tại và cho phép bạn bắt đầu GC). Nếu bạn theo liên kết đó, bạn sẽ thấy rằng họ chạy một cách rõ ràng các finalizers. Nếu bạn có một vài gig không gian đĩa miễn phí và muốn tự mình điều tra mã, bạn có thể tự mình điều tra mã đó, nó có sẵn qua Mercurial: hg clone http://hg.netbeans.org/main/

Theo như tôi có thể nói, "System.gc() chỉ là một gợi ý" trong việc giải thích theo nghĩa của JLS và JVM Spec, cho phép triển khai Java không có đống rác được thu thập. Đó, và một đọc chưa đầy đủ của các JavaDoc:

Gọi phương thức gc gợi ý rằng Java Virtual Machine rộng nỗ lực hướng tái chế đối tượng sử dụng trong để làm cho bộ nhớ họ hiện chiếm sẵn cho nhanh tái sử dụng . Khi điều khiển trả về từ cuộc gọi phương thức , Máy ảo Java đã thực hiện một nỗ lực tốt nhất để lấy lại không gian từ tất cả các đối tượng bị loại bỏ.

Đọc câu thứ hai: "nỗ lực tốt nhất để giành lại không gian" mạnh hơn rất nhiều so với "gợi ý".

Điều đó nói rằng, hiếm khi có lý do để gọi System.gc().Với lời xin lỗi đến Knuth:

Chúng ta nên quên về quản lý bộ nhớ, nói rằng khoảng 97% thời gian: thu gom rác thải rõ là gốc rễ của mọi tội lỗi

+2

tôi sẽ không gọi nó là một giáo điều dựa trên một sự giải thích pedantic. Hầu hết các JVM ngoài kia đều có thể đơn giản vô hiệu hóa các lệnh gọi tới System.gc(), do đó bạn không thể tin tưởng các cuộc gọi đó để làm bất cứ điều gì. Khá thường xuyên, nơi bạn có một ứng dụng tốt bằng văn bản, nơi gc đang làm việc vui vẻ, giới thiệu một thư viện nơi nhà phát triển nghĩ rằng ông có thể "đảm bảo bộ nhớ khả dụng" bằng cách gọi System.gc(), tắt nó là cách tốt nhất để trở lại hiệu suất gc tốt của bạn. – Fredrik

+0

Người dùng vẫn có quyền kiểm soát điều đó. Đối với máy ảo điểm phát sóng, bạn có thể đặt '-XX: + DisableExplicitGC' hoặc bạn không. Vì vậy, miễn là bạn có quyền kiểm soát các cờ JVM 'System.gc()' là khá đáng tin cậy. Các đối số chỉ áp dụng cho các nhà văn thư viện những người không thể kiểm soát những lá cờ/không thể giả định trên đó VM nó sẽ chạy. Đó là một trường hợp chung (spec) so với việc sử dụng cụ thể (với tất cả các tham số được kiểm soát bởi người dùng). – the8472

+0

Các nhà văn ứng dụng thường không có quyền kiểm soát các cờ JVM. Ngoại lệ là khi ứng dụng được gói trong trình khởi chạy ngăn người dùng hoặc sysadmin tinh chỉnh chúng. Đây không phải là người đi bộ. Trong thực tế, lá cờ là có đặc biệt để bảo vệ con người chống lại các ứng dụng Java/các nhà văn ứng dụng làm những điều ngu xuẩn. –

0

Có JNI mã giao diện là cần thiết để sử dụng JVMTI API vì nó là một API gốc. "native" có nghĩa là bạn chỉ có thể gọi nó trực tiếp dưới dạng native (understan c hoặc C++). Vì vậy, nếu bạn muốn gọi API này từ java, bạn cần phải viết mã JNI để giao tiếp nó.

0

Như Anon đã nói, chúng tôi có một cái gì đó tương tự trong nhật thực để chạy bộ thu gom rác một cách rõ ràng.

Vui lòng xem Eclipse: Garbage Collector Button

Điều này có vẻ hoạt động khá tốt. Tôi đề nghị bạn hãy xem mã phía sau nút "Run garbage collector" và sử dụng lại nó.

Một số thành viên nói rằng nó sử dụng System.gc() nhưng tôi không thể xác nhận. Các chuyên gia Eclipse có thể làm sáng tỏ ở đây.

4

tôi đã xây dựng một đại lý java cơ bản cho phép để gọi jvmti ForceGarbageCollection chức năng:

#include <stdlib.h> 
#include <stdio.h> 
#include <jvmti.h> 


typedef struct { 
jvmtiEnv *jvmti; 
} GlobalAgentData; 

static GlobalAgentData *gdata; 

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) 
{ 
    printf("load garbager agent\n"); 
    jvmtiEnv *jvmti = NULL; 

    // put a jvmtiEnv instance at jvmti. 
    jint result = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1); 
    if (result != JNI_OK) { 
    printf("ERROR: Unable to access JVMTI!\n"); 
    } 

    // store jvmti in a global data 
    gdata = (GlobalAgentData*) malloc(sizeof(GlobalAgentData)); 
    gdata->jvmti = jvmti; 
    return JNI_OK; 
} 


extern "C" 
JNIEXPORT void JNICALL Java_Garbager_forceGarbageCollection(JNIEnv *env, jclass thisClass) 
{ 
    printf("force garbage collection\n"); 
    gdata->jvmti->ForceGarbageCollection(); 
} 

đại lý này được gọi thông qua JNI:

class Garbager { 
    public static void main(String[] args) { 
     Garbager.garbageMemory(); 
    } 

    static void garbageMemory() { 
     forceGarbageCollection(); 
    } 

    private static native void forceGarbageCollection(); 
} 

Để biên dịch các tác nhân trên MacOSX:

clang -shared -undefined dynamic_lookup -o garbager-agent.so -I /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include/ -I /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include/darwin garbager-agent.cpp 

Để khởi chạy Garbager:

java -agentpath:garbager-agent.so Garbager 

Dựa trên hướng dẫn này: Own your heap: Iterate class instances with JVMTI

Các vấn đề liên quan