Avatar
0
tunguyen Beginner
tunguyen Beginner
garbage collection
Cơ chế garbage collection

GC có 1 cơ chế là quét các object k được tham chiếu trong heap từ stack. Như vậy khi nào ta  cần manual - quét thủ công bằng cách gọi gc.collect(), khi nào ta nên để hệ thống tự quét. Many thanks mọi người

  • Answer
Remain: 5
1 Answer
Avatar
monkey Beginner
monkey Beginner
Không rõ những thông tin em tìm được là ở nguồn nào, nhưng chúng ta hãy tìm hiểu sâu 1 chút để trả lời câu hỏi của em nhé. Bản chất bên trong của System.gc(); là gọi đến Runtime.getRuntime().gc();, và gc là 1 hàm native: public native void gc();, và java thì có nhiều loại GC khác nhau, tuy nhiên ở phiên bản OpẹnJDK hiện tại thì đâu đó có 2 hay 4 loại dùng cho G1CollectionGenCollectedHeap là "young" generation và Concurrent Mark Sweep (anh cũng ko biết tên thế có đúng không, em đọc code OpenJDK nhé). Bây giờ mình sẽ tập trung vào G1Collection nhé:

void G1CollectedHeap::collect(GCCause::Cause cause) {
  try_collect(cause, collection_counters(this));
}

bool G1CollectedHeap::try_collect(GCCause::Cause cause,
                                  const G1GCCounters& counters_before) {
  if (should_do_concurrent_full_gc(cause)) {
    return try_collect_concurrently(cause,
                                    counters_before.total_collections(),
                                    counters_before.old_marking_cycles_started());
  } else if (GCLocker::should_discard(cause, counters_before.total_collections())) {
    // Indicate failure to be consistent with VMOp failure due to
    // another collection slipping in after our gc_count but before
    // our request is processed.
    return false;
  } else if (cause == GCCause::_gc_locker || cause == GCCause::_wb_young_gc
             DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) {

    // Schedule a standard evacuation pause. We're setting word_size
    // to 0 which means that we are not requesting a post-GC allocation.
    VM_G1CollectForAllocation op(0,     /* word_size */
                                 counters_before.total_collections(),
                                 cause,
                                 policy()->max_pause_time_ms());
    VMThread::execute(&op);
    return op.gc_succeeded();
  } else {
    // Schedule a Full GC.
    VM_G1CollectFull op(counters_before.total_collections(),
                        counters_before.total_full_collections(),
                        cause);
    VMThread::execute(&op);
    return op.gc_succeeded();
  }
}
</pre>

Em có thể thấy rằng nó check should_do_concurrent_full_gc, nên không phải em cứ gọi gc là được, thêm vào nữa việc gọi gc nhiều sẽ làm chương trình bị tăng độ trễ, vì nó phải lock các đối tượng lại để tiến hành kiểm tra và remove để tránh race condition, nên lời khuyên là em không nên tự gọi gc làm gì, hãy để việc đó cho máy ảo java lập lịch nhé

Em có thể tự pull <a href="https://github.com/openjdk/jdk" rel="nofollow ugc">OpenJDK</a> và sử dụng các từ khoá sau để tìm kiếm nhé:

<pre>
JvmtiGCMarker
SvcGCMarker
CollectedHeap
G1CollectedHeap
G1FullGCScope
post_garbage_collection_finish

JVM_ENTRY_NO_ENV(void, JVM_GC(void))
  if (!DisableExplicitGC) {
    EventSystemGC event;
    event.set_invokedConcurrent(ExplicitGCInvokesConcurrent);
    Universe::heap()->collect(GCCause::_java_lang_system_gc);
    event.commit();
  }
JVM_END
</pre>
  • 0
  • Reply