Trình thu gom rác trong Java là gì?


103

Tôi mới sử dụng Java và bối rối về bộ thu gom rác trong Java. Nó thực sự làm gì và khi nào nó hoạt động. Hãy mô tả một số thuộc tính của bộ thu gom rác trong Java.


2
có thể trùng lặp của Garbage Collection
Ian Ringrose

10
Đôi khi tốt hơn là bạn nên đọc chương trong một cuốn sách hay để mong hiểu một chủ đề phức tạp từ câu trả lời cho một câu hỏi.
Ian Ringrose

4
@Ian Đó là một câu hỏi tương tự, nhưng không trùng lặp. Và câu hỏi đó lặp lại bài tập về nhà.
NullUserException,

Câu trả lời:


119

Trình thu gom rác là một chương trình chạy trên Máy ảo Java để loại bỏ các đối tượng không được ứng dụng Java sử dụng nữa. Nó là một hình thức quản lý bộ nhớ tự động .

Khi một ứng dụng Java điển hình đang chạy, nó đang tạo các đối tượng mới, chẳng hạn như Strings và Files, nhưng sau một thời gian nhất định, các đối tượng đó không được sử dụng nữa. Ví dụ, hãy xem đoạn mã sau:

for (File f : files) {
    String s = f.getName();
}

Trong đoạn mã trên, String sđang được tạo trên mỗi lần lặp lại của forvòng lặp. Điều này có nghĩa là trong mỗi lần lặp, một ít bộ nhớ sẽ được cấp phát để tạo một Stringđối tượng.

Quay trở lại đoạn mã, chúng ta có thể thấy rằng khi một lần lặp duy nhất được thực thi, trong lần lặp tiếp theo, Stringđối tượng đã được tạo trong lần lặp trước đó sẽ không được sử dụng nữa - đối tượng đó bây giờ được coi là "rác".

Cuối cùng, chúng ta sẽ bắt đầu nhận được rất nhiều rác và bộ nhớ sẽ được sử dụng cho các đối tượng không còn được sử dụng nữa. Nếu điều này tiếp diễn, cuối cùng Máy ảo Java sẽ hết dung lượng để tạo các đối tượng mới.

Đó là nơi mà bộ thu gom rác bước vào.

Bộ thu gom rác sẽ tìm kiếm các đối tượng không còn được sử dụng nữa và loại bỏ chúng, giải phóng bộ nhớ để các đối tượng mới khác có thể sử dụng phần bộ nhớ đó.

Trong Java, quản lý bộ nhớ do bộ thu gom rác đảm nhận, nhưng trong các ngôn ngữ khác như C, người ta cần tự thực hiện quản lý bộ nhớ bằng cách sử dụng các hàm như mallocfree . Quản lý bộ nhớ là một trong những việc dễ mắc sai lầm, có thể dẫn đến cái gọi là rò rỉ bộ nhớ - nơi bộ nhớ không được lấy lại khi chúng không được sử dụng nữa.

Các sơ đồ quản lý bộ nhớ tự động như thu gom rác giúp lập trình viên không phải lo lắng nhiều về các vấn đề quản lý bộ nhớ, vì vậy họ có thể tập trung hơn vào việc phát triển các ứng dụng mà họ cần phát triển.


Sẽ đúng nếu nói một ứng dụng java chạy trên máy tính có hai chức năng thu gom rác. Một với máy ảo Java. Và sau đó là một trên máy thực sự chạy windows? (Hoặc bất kỳ hệ điều hành nào khác)
Lealo

Không, các ứng dụng Java thường chỉ chạy nếu có JRE. Vì vậy, chỉ cần có chức năng thu gom rác của JVM! @Lealo
Am_I_Helpful

18

Nó giải phóng bộ nhớ được cấp cho các đối tượng không được chương trình sử dụng nữa - do đó có tên là "rác". Ví dụ:

public static Object otherMethod(Object obj) {
    return new Object();
}

public static void main(String[] args) {
    Object myObj = new Object();
    myObj = otherMethod(myObj);
    // ... more code ...  
}

Tôi biết điều này là cực kỳ phức tạp, nhưng ở đây sau khi bạn gọi otherMethod(), bản gốc Objectđược tạo sẽ không thể truy cập được - và đó là "rác" được thu gom rác.

Trong Java, GC chạy tự động, nhưng bạn cũng có thể gọi nó một cách rõ ràng bằng System.gc()cố gắng buộc một bộ sưu tập rác lớn. Như Pascal Thivent đã chỉ ra, bạn thực sự không nên làm điều này và nó có thể gây hại nhiều hơn lợi (xem câu hỏi này ).

Để biết thêm, hãy xem mục nhập wikipedia về Thu gom rácĐiều chỉnh Thu gom rác (từ Oracle)


1
AFAIK System.gc()không buộc GC chạy.
Itay Karo

1
+1 cho ví dụ về mã tốt. Lưu ý rằng nó hoàn toàn hợp lệ để GC hủy myObjtrước khi lệnh gọi otherMethoddiễn ra, vì myObjkhông còn truy cập được vào thời điểm đó.
Billy ONeal

@Italy Tôi tin rằng đó là cách triển khai cụ thể.
NullUserException,

2
Tôi tin rằng một người không nên gọi System.gc(), toàn bộ điểm của việc có GC là không cần phải làm điều đó.
Pascal Thivent,

với phân tích thoát ( en.wikipedia.org/wiki/Escape_analysis ), có thể JVM thậm chí không thể phân bổ đối tượng ngay từ đầu trong ví dụ này. Toàn bộ việc tạo đối tượng (trên lý thuyết) có thể được tối ưu hóa đi. Tất nhiên phụ thuộc vào việc triển khai.
mikera

15

Một đối tượng đủ điều kiện để thu gom rác hoặc GC nếu nó không thể truy cập được từ bất kỳ chuỗi trực tiếp nào hoặc bằng bất kỳ tham chiếu tĩnh nào.

Nói cách khác, bạn có thể nói rằng một đối tượng đủ điều kiện để thu gom rác nếu tất cả các tham chiếu của nó là rỗng. Các phụ thuộc theo chu kỳ không được tính là tham chiếu vì vậy nếu đối tượng A có tham chiếu đến đối tượng B và đối tượng B có tham chiếu đến đối tượng A và chúng không có bất kỳ tham chiếu trực tiếp nào khác thì cả đối tượng A và B sẽ đủ điều kiện để thu gom rác.


Thế hệ đống để thu gom rác -

Các đối tượng Java được tạo trong HeapHeapđược chia thành ba phần hoặc thế hệ nhằm mục đích thu gom rác trong Java, chúng được gọi là thế hệ Trẻ (Mới), Thế hệ Tenured (Cũ) và Vùng Perm của đống.

Không gian đống Java New Generation được chia thành ba phần được gọi là không gian Eden, không gian Survivor 1 và Survivor 2. Khi một đối tượng được tạo lần đầu tiên trong heap của nó sẽ được tạo trong thế hệ mới bên trong không gian Eden và sau lần thu gom rác nhỏ sau đó nếu một đối tượng sống sót sẽ được chuyển đến người sống sót 1 và sau đó là người sống sót 2 trước khi bộ sưu tập rác lớn chuyển đối tượng đó sang thế hệ cũ hoặc còn hạn sử dụng .

Không gian Perm của Java Heap là nơi JVM lưu trữ Siêu dữ liệu về các lớp và phương thức, Nhóm chuỗi và chi tiết mức Lớp.

Thế hệ đống để thu gom rác

Tham khảo thêm tại đây: Thu gom rác


Bạn không thể buộc JVM chạy Bộ sưu tập rác mặc dù bạn có thể đưa ra yêu cầu bằng cách sử dụng System.gc()hoặc Runtime.gc()phương thức.

Trong java.lang.System

public static void gc() {
    Runtime.getRuntime().gc();  
}

Trong java.lang.Runtime

public native void gc();  // note native  method

Thuật toán Đánh dấu và Quét -

Đây là một trong những thuật toán phổ biến nhất được sử dụng bởi bộ sưu tập Rác. Bất kỳ thuật toán thu gom rác nào cũng phải thực hiện 2 thao tác cơ bản. Thứ nhất, nó phải có thể phát hiện tất cả các đối tượng không thể truy cập và thứ hai, nó phải lấy lại không gian heap được sử dụng bởi các đối tượng rác và cung cấp lại không gian cho chương trình.

Các hoạt động trên được thực hiện bởi Thuật toán Đánh dấu và Quét trong hai giai đoạn:

  1. Đánh dấu giai đoạn
  2. Giai đoạn quét

đọc ở đây để biết thêm chi tiết - Thuật toán Đánh dấu và Quét


6

bộ thu gom rác ngụ ý rằng các đối tượng không còn cần thiết của chương trình là "rác" và có thể bị vứt bỏ.


6

Garbage Collector là một phần của JRE đảm bảo rằng đối tượng không được tham chiếu sẽ được giải phóng khỏi bộ nhớ.
Nó thường chạy khi ứng dụng của bạn hết bộ nhớ. AFAIK nó chứa một đồ thị đại diện cho các liên kết giữa các đối tượng và các đối tượng bị cô lập có thể được giải phóng.
Để tiết kiệm hiệu suất, các đối tượng hiện tại được nhóm thành các thế hệ, mỗi khi GC quét một đối tượng và thấy rằng đối tượng đó vẫn được tham chiếu thì số lượng thế hệ của nó tăng lên 1 (đến giá trị lớn nhất tối đa, tôi nghĩ là 3 hoặc 4) và thế hệ mới được quét trước tiên (đối tượng ngắn nhất trong bộ nhớ thì có lẽ nó không còn cần thiết nữa) vì vậy không phải tất cả các đối tượng đều được quét mỗi khi GC chạy.
đọc cái này để biết thêm thông tin


@quantumSoup Bạn có khả năng về việc này không? Tôi tin rằng một số loại thu gom rác (loại đắt tiền hơn) chỉ xảy ra khi đống rác đầy.
Pablo Fernandez

2
@quantumSoup - điều đó phụ thuộc vào việc triển khai GC của JRE. Trong nhiều trường hợp, GC không chạy liên tục. Thay vào đó, nó chạy khi ứng dụng của bạn không thể phân bổ một đối tượng vì heap đã đầy. Các JVM HotSpot gần đây bao gồm một GC song song, nhưng nó không được bật theo mặc định.
Stephen C

Câu trả lời này tập trung quá nhiều vào cơ chế. Câu hỏi đặt ra là "các bộ thu rác là gì", không phải "Làm thế nào để thu gom rác hoạt động"
Billy Oneal

@quantum: đã vô hiệu hóa -1 của bạn, vì: Học, tức là trang này dùng để làm gì, đúng không? Để học, bạn cần phải mắc sai lầm. Sai lầm trừng phạt khiến người ta không học hỏi. Hy vọng, bạn có thể đồng ý ở điểm đó. Và có thể bạn đã làm sai ở đây.
erikbwork

1
@erikb: Theo logic đó sẽ không bao giờ có bất kỳ phiếu phản đối nào. Và phiếu phản đối là cần thiết để loại bỏ những câu trả lời tương đối kém. OP rõ ràng là một người mới bắt đầu và các hoạt động bên trong cụ thể của GC đơn giản là không quan trọng đối với câu hỏi được đặt ra. Vì câu trả lời này không trả lời câu hỏi được hỏi (nó trả lời một câu khác), phiếu phản đối là hoàn toàn hợp lý.
Billy ONeal

3

Trình thu gom rác cho phép máy tính của bạn mô phỏng một máy tính có bộ nhớ vô hạn. Phần còn lại chỉ là cơ chế.

Nó thực hiện điều này bằng cách phát hiện khi nào các phần bộ nhớ không còn có thể truy cập được từ mã của bạn và trả các phần đó về kho lưu trữ miễn phí.

CHỈNH SỬA: Có, liên kết dành cho C #, nhưng C # và Java giống hệt nhau về mặt này.


Có thực sự là một câu hỏi về SO về sự khác biệt giữa java và C # 's GC: stackoverflow.com/questions/492703/c-vs-java-garbage-collector
NullUserException

3

Nhiều người nghĩ rằng việc thu gom rác thải sẽ thu gom và loại bỏ những đồ vật đã chết.
Trong thực tế, bộ sưu tập rác Java đang làm ngược lại! Các đối tượng sống được theo dõi và mọi thứ rác được chỉ định khác.

Khi một đối tượng không còn được sử dụng nữa, bộ thu gom rác sẽ lấy lại bộ nhớ bên dưới và sử dụng lại nó để phân bổ đối tượng trong tương lai. Điều này có nghĩa là không có xóa rõ ràng và không có bộ nhớ nào được trả lại cho hệ điều hành. Để xác định đối tượng nào không còn được sử dụng nữa, JVM chạy liên tục cái được gọi là thuật toán đánh dấu và quét.

Kiểm tra phần này để biết thêm thông tin chi tiết: http://javabook.compuware.com/content/memory/how-garbage-collection-works.aspx


1

Nói một cách đơn giản nhất mà ngay cả một người không phải là lập trình viên cũng có thể hiểu được, khi một chương trình xử lý dữ liệu, nó sẽ tạo ra dữ liệu trung gian và không gian lưu trữ (biến, mảng, siêu dữ liệu đối tượng nhất định, v.v.) cho dữ liệu đó.

Khi các đối tượng này được truy cập qua các chức năng hoặc trên một kích thước nhất định, chúng được cấp phát từ một đống trung tâm. Sau đó, khi chúng không cần thiết lâu nữa, chúng cần được dọn dẹp.

Có một số bài báo rất hay trên mạng về cách thức hoạt động của điều này, vì vậy tôi sẽ chỉ đề cập đến định nghĩa rất cơ bản.

GC về cơ bản là chức năng thực hiện công việc dọn dẹp này. Để làm điều này là xóa các mục nhập bảng không được tham chiếu bởi bất kỳ đối tượng đang hoạt động nào, xóa các đối tượng một cách hiệu quả hơn là sao chép và thu gọn bộ nhớ. Nó phức tạp hơn một chút so với điều này, nhưng bạn sẽ hiểu.

Vấn đề lớn là một số phần, quá trình này thường yêu cầu toàn bộ máy ảo Java yêu cầu phải tạm dừng để diễn ra, cũng như toàn bộ quá trình này rất tốn băng thông bộ xử lý và bộ nhớ. Các tùy chọn khác nhau của GC và các tùy chọn điều chỉnh cho mỗi tùy chọn được thiết kế để cân bằng các vấn đề khác nhau này với toàn bộ quy trình GC.


0

Thu gom rác trong Java (và các ngôn ngữ / nền tảng khác) là một cách để môi trường thời gian chạy java (JRE) sử dụng lại bộ nhớ từ các đối tượng java không còn cần thiết. Nói một cách đơn giản, khi JRE ban đầu khởi động, nó yêu cầu Hệ điều hành (O / S) cung cấp một lượng bộ nhớ nhất định. Khi JRE chạy (các) ứng dụng của bạn, nó sẽ sử dụng bộ nhớ đó. Khi ứng dụng của bạn được hoàn tất bằng cách sử dụng bộ nhớ đó, "Bộ thu gom rác" của JRE sẽ xuất hiện và lấy lại bộ nhớ đó để sử dụng cho các phần khác nhau của (các) ứng dụng hiện có của bạn. "Trình thu gom rác" của JRE là một nhiệm vụ nền luôn chạy và cố gắng chọn thời điểm khi hệ thống không hoạt động để tiếp tục chạy rác của nó.

Một sự tương tự trong thế giới thực sẽ là những người đổ rác đến nhà bạn và nhặt rác có thể tái chế của bạn ... cuối cùng, nó được sử dụng lại theo những cách khác bởi chính bạn và / hoặc những người khác.


0

Bộ thu gom rác có thể được xem như một trình quản lý số lượng tham chiếu. nếu một đối tượng được tạo và tham chiếu của nó được lưu trữ trong một biến, số lượng tham chiếu của nó sẽ tăng lên một. trong quá trình thực hiện nếu biến đó được gán với NULL. số lượng tham chiếu cho đối tượng đó bị giảm. vì vậy số tham chiếu hiện tại cho đối tượng là 0. Bây giờ khi bộ thu gom rác được thực thi, nó sẽ kiểm tra các đối tượng có số tham chiếu bằng 0. và giải phóng tài nguyên được cấp cho nó.

Việc gọi trình thu gom rác được kiểm soát bởi các chính sách thu gom rác.

Bạn có thể lấy một số dữ liệu ở đây. http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html


1
Đếm tham chiếu là một cách tệ hại để triển khai GC. Tôi không nghĩ rằng bất kỳ triển khai JVM lớn nào sử dụng điều này.
NullUserException,

0

Bộ thu gom rác là một thành phần của jvm.

Nó được sử dụng để thu gom rác khi cpu được miễn phí.

Ở đây rác có nghĩa là các đối tượng không sử dụng nó chạy trong Nền của chương trình chính

để theo dõi trạng thái của chương trình chính.


0

Tự động thu gom rác là quá trình xem xét bộ nhớ heap, xác định đối tượng nào đang được sử dụng và đối tượng nào không và xóa các đối tượng không sử dụng. Một đối tượng đang được sử dụng, hoặc một đối tượng được tham chiếu, có nghĩa là một số phần của chương trình của bạn vẫn duy trì một con trỏ đến đối tượng đó. Một đối tượng không được sử dụng, hoặc đối tượng không được tham chiếu, không còn được tham chiếu bởi bất kỳ phần nào trong chương trình của bạn. Vì vậy, bộ nhớ được sử dụng bởi một đối tượng không được tham chiếu có thể được lấy lại.

Trong một ngôn ngữ lập trình như C, cấp phát và phân bổ bộ nhớ là một quá trình thủ công. Trong Java, quá trình phân bổ bộ nhớ được xử lý tự động bởi bộ thu gom rác. Vui lòng kiểm tra liên kết để hiểu rõ hơn. http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html


0

Thu gom rác đề cập đến quá trình tự động giải phóng bộ nhớ trên heap bằng cách xóa các đối tượng không còn truy cập được trong chương trình của bạn. Heap là một bộ nhớ được gọi là kho lưu trữ miễn phí, đại diện cho một nhóm lớn bộ nhớ không sử dụng được phân bổ cho ứng dụng Java của bạn.


1
Không sử dụng định dạng trích dẫn cho văn bản không được trích dẫn và nếu nó được trích dẫn, bạn cần phải trích dẫn nguồn.
Marquis of Lorne,

0

Nguyên tắc cơ bản của việc thu gom rác là tìm các đối tượng dữ liệu trong một chương trình không thể truy cập được trong tương lai, và lấy lại các tài nguyên được sử dụng bởi các đối tượng đó. https://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29

Ưu điểm

1) Tiết kiệm khỏi lỗi, xảy ra khi một phần bộ nhớ được giải phóng trong khi vẫn còn con trỏ đến nó và một trong những con trỏ đó được tham chiếu. https://en.wikipedia.org/wiki/Dangling_pointer

2) Lỗi kép miễn phí, xảy ra khi chương trình cố gắng giải phóng một vùng bộ nhớ đã được giải phóng và có lẽ đã được cấp phát lại.

3) Ngăn chặn một số loại rò rỉ bộ nhớ, trong đó một chương trình không thể giải phóng bộ nhớ bị chiếm bởi các đối tượng trở nên không thể truy cập được, có thể dẫn đến cạn bộ nhớ.

Nhược điểm

1) Tiêu tốn tài nguyên bổ sung, tác động đến hiệu suất, các lỗi có thể xảy ra khi thực hiện chương trình và không tương thích với quản lý tài nguyên thủ công. Việc thu gom rác tiêu tốn tài nguyên máy tính để quyết định bộ nhớ nào cần giải phóng, mặc dù lập trình viên có thể đã biết thông tin này.

2) Thời điểm mà rác thực sự được thu gom có ​​thể không thể đoán trước được, dẫn đến các gian hàng (tạm dừng để thay đổi / bộ nhớ trống) nằm rải rác trong suốt một phiên. Những gian hàng không thể đoán trước có thể không được chấp nhận trong môi trường thời gian thực, trong quá trình xử lý giao dịch hoặc trong các chương trình tương tác.


Hướng dẫn về Oracle http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

Thu gom rác là quá trình xác định đối tượng nào đang được sử dụng và đối tượng nào không và xóa các đối tượng không sử dụng.

Trong các ngôn ngữ lập trình như C, C ++, cấp phát và giải phóng bộ nhớ là một quá trình thủ công.

int * array = new int[size];
processArray(array); //do some work.
delete array; //Free memory

Bước đầu tiên của quá trình này được gọi là đánh dấu. Đây là nơi bộ thu gom rác xác định phần bộ nhớ nào đang được sử dụng và phần nào không.

Bước 2a. Xóa thông thường loại bỏ các đối tượng không được tham chiếu để lại các đối tượng và con trỏ được tham chiếu đến không gian trống.

Để cải thiện hiệu suất, chúng tôi muốn xóa các đối tượng không được tham chiếu và cũng thu gọn các đối tượng được tham chiếu còn lại. Chúng tôi muốn giữ các đối tượng được tham chiếu lại với nhau, vì vậy sẽ nhanh hơn khi cấp phát bộ nhớ mới.

Như đã nói trước đó, việc phải đánh dấu và thu gọn tất cả các đối tượng trong một JVM là không hiệu quả. Khi càng nhiều đối tượng được phân bổ, danh sách các đối tượng ngày càng lớn lên dẫn đến thời gian thu gom rác ngày càng lâu hơn.

Tiếp tục đọc hướng dẫn này và bạn sẽ biết GC thực hiện thử thách này như thế nào.

Tóm lại, có ba vùng của đống, YoungGeneration cho các đối tượng vòng đời ngắn, OldGeneration cho các đối tượng chu kỳ dài và PermanentGeneration cho các đối tượng sống trong vòng đời ứng dụng, ví dụ, các lớp, thư viện.


0

Khi các đối tượng được cấp phát động bởi toán tử mới , bạn có thể hỏi cách các đối tượng này bị phá hủy và bộ nhớ bận được giải phóng như thế nào. Trong các ngôn ngữ khác như C ++, bạn cần giải phóng các đối tượng được cấp phát động theo cách thủ công bởi toán tử xóa. Java có một cách tiếp cận khác; nó tự động xử lý phân bổ giao dịch. Kỹ thuật này được gọi là Thu gom rác .

Nó hoạt động như thế này: khi không có tham chiếu nào đến một đối tượng, nó được giả định rằng đối tượng này không còn cần thiết nữa và bạn có thể truy xuất bộ nhớ bị chiếm bởi đối tượng. Không nhất thiết phải hủy đối tượng một cách rõ ràng như trong C ++. Việc thu gom rác diễn ra không thường xuyên trong quá trình thực hiện chương trình; Nó không chỉ đơn giản xảy ra vì có một hoặc nhiều đối tượng không còn được sử dụng nữa. Ngoài ra, một số triển khai thời gian chạy Java có các cách tiếp cận khác nhau để thu gom rác, nhưng hầu hết các lập trình viên không phải lo lắng về điều này khi viết chương trình.


-2

Tự động thu gom rác là một quá trình mà JVM loại bỏ hoặc giữ một số điểm dữ liệu nhất định trong bộ nhớ để cuối cùng giải phóng dung lượng cho chương trình đang chạy. Đầu tiên bộ nhớ được gửi đến bộ nhớ heap, đó là nơi bộ thu gom rác (GC) thực hiện công việc của nó, sau đó được quyết định kết thúc hoặc giữ lại. Java cho rằng không phải lúc nào lập trình viên cũng đáng tin cậy, vì vậy nó kết thúc các mục mà nó cho rằng nó không cần.

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.