it-swarm-vi.tech

Khi nào System.gc () làm gì đó?

Tôi biết rằng bộ sưu tập rác được tự động hóa trong Java. Nhưng tôi hiểu rằng nếu bạn gọi System.gc() trong mã của mình thì JVM có thể hoặc không thể quyết định thực hiện thu gom rác tại thời điểm đó. Làm thế nào để nó hoạt động chính xác? Trên cơ sở/tham số nào chính xác, JVM quyết định thực hiện (hoặc không làm) một GC khi thấy System.gc()?

Có bất kỳ ví dụ nào trong trường hợp đó là một ý tưởng tốt để đưa mã này vào mã của bạn không?

111
harry

Trong thực tế, nó thường quyết định thực hiện một bộ sưu tập rác. Câu trả lời khác nhau tùy thuộc vào nhiều yếu tố, như bạn đang chạy JVM nào, chế độ nào và sử dụng thuật toán thu gom rác nào.

Tôi sẽ không phụ thuộc vào nó trong mã của bạn. Nếu JVM chuẩn bị ném OutOfMemoryError, việc gọi System.gc () sẽ không dừng lại, bởi vì trình thu gom rác sẽ cố gắng giải phóng hết mức có thể trước khi nó đi đến cực điểm đó. Lần duy nhất tôi thấy nó được sử dụng trong thực tế là trong các IDE có gắn nút mà người dùng có thể nhấp vào, nhưng ngay cả ở đó nó cũng không hữu ích lắm.

58
jodonnell

Ví dụ duy nhất tôi có thể nghĩ về nơi hợp lý khi gọi System.gc () là khi cấu hình một ứng dụng để tìm kiếm rò rỉ bộ nhớ có thể. Tôi tin rằng các trình biên dịch gọi phương thức này ngay trước khi chụp ảnh bộ nhớ.

29
Guillermo Vasconcelos

Java Đặc tả ngôn ngữ không đảm bảo rằng JVM sẽ khởi động một GC khi bạn gọi System.gc(). Đây là lý do của việc này "có thể hoặc không thể quyết định làm một GC tại thời điểm đó".

Bây giờ, nếu bạn nhìn vào mã nguồn OpenJDK , đó là xương sống của Oracle JVM, bạn sẽ thấy rằng một lệnh gọi tới System.gc() sẽ bắt đầu một chu trình GC. Nếu bạn sử dụng một JVM khác, chẳng hạn như J9, bạn phải kiểm tra tài liệu của họ để tìm ra câu trả lời. Chẳng hạn, JVM của Azul có trình thu gom rác chạy liên tục, do đó, một cuộc gọi đến System.gc() sẽ không làm gì cả

Một số câu trả lời khác đề cập đến việc bắt đầu một GC trong JConsole hoặc VisualVM. Về cơ bản, các công cụ này thực hiện cuộc gọi từ xa tới System.gc().

Thông thường, bạn không muốn bắt đầu một chu trình thu gom rác từ mã của mình, vì nó làm rối tung ngữ nghĩa của ứng dụng của bạn. Ứng dụng của bạn thực hiện một số công việc kinh doanh, JVM đảm nhiệm việc quản lý bộ nhớ. Bạn nên tách biệt những mối quan tâm đó (đừng làm cho ứng dụng của bạn thực hiện một số quản lý bộ nhớ, tập trung vào công việc).

Tuy nhiên, có một vài trường hợp mà một cuộc gọi đến System.gc() có thể hiểu được. Hãy xem xét, ví dụ, microbenchmark. Không ai muốn có một chu trình GC xảy ra ở giữa một microbenchmark. Vì vậy, bạn có thể kích hoạt chu trình GC giữa mỗi phép đo để đảm bảo mọi phép đo bắt đầu với một đống trống.

24
Pierre Laporte

Bạn không có quyền kiểm soát đối với GC trong Java - quyết định VM. Tôi chưa bao giờ chạy qua một trường hợp trong đó System.gc() cần thiết . Vì một System.gc() gọi đơn giản là SUGGESTS rằng VM thực hiện một bộ sưu tập rác và nó cũng thực hiện một bộ sưu tập rác ĐẦY ĐỦ (thế hệ cũ và mới trong một đống nhiều thế hệ), nên nó thực sự có thể gây ra - MORE chu kỳ cpu sẽ được tiêu thụ hơn mức cần thiết.

Trong một số trường hợp, có thể có ý nghĩa khi đề xuất với VM rằng nó thực hiện một bộ sưu tập đầy đủ NGAY BÂY GIỜ vì bạn có thể biết ứng dụng sẽ không hoạt động trong vài phút tiếp theo trước khi xảy ra tình trạng nặng. Ví dụ, ngay sau khi khởi tạo rất nhiều đối tượng tạm thời trong quá trình khởi động ứng dụng (tức là tôi chỉ lưu vào TON thông tin và tôi biết rằng mình sẽ không nhận được nhiều hoạt động trong một phút hoặc lâu hơn). Hãy nghĩ về một IDE chẳng hạn như Eclipse khởi động - việc khởi tạo rất nhiều, vì vậy có lẽ ngay sau khi khởi tạo, sẽ rất hợp lý khi thực hiện một gc đầy đủ tại thời điểm đó.

23
DustinB

Bạn cần hết sức cẩn thận nếu bạn gọi System.gc(). Gọi nó có thể thêm các vấn đề hiệu suất không cần thiết vào ứng dụng của bạn và nó không được đảm bảo để thực sự thực hiện một bộ sưu tập. Thực tế có thể vô hiệu hóa System.gc() thông qua đối số Java -XX:+DisableExplicitGC.

Tôi thực sự khuyên bạn nên đọc qua các tài liệu có sẵn tại Bộ sưu tập rác Java HotSpot để biết thêm chi tiết về bộ sưu tập rác.

17
David Schlosnagle

System.gc() được VM triển khai và những gì nó thực hiện là cụ thể. Ví dụ, người triển khai có thể trả lại và không làm gì cả.

Về thời điểm phát hành một bộ sưu tập thủ công, lần duy nhất khi bạn có thể muốn làm điều này là khi bạn từ bỏ một bộ sưu tập lớn chứa vô số bộ sưu tập nhỏ hơn - ví dụ: _Map<String,<LinkedList>>_ - và bạn muốn thử và lấy sự hoàn hảo sau đó và ở đó, nhưng đối với hầu hết các phần, bạn không nên lo lắng về nó. GC biết rõ hơn bạn - thật đáng buồn - hầu hết thời gian.

10
Patrick

Nếu bạn sử dụng bộ đệm bộ nhớ trực tiếp, JVM sẽ không chạy GC cho bạn ngay cả khi bạn sắp hết bộ nhớ trực tiếp.

Nếu bạn gọi ByteBuffer.allocateDirect() và bạn nhận được OutOfMemoryError, bạn có thể thấy cuộc gọi này vẫn ổn sau khi kích hoạt một cách thủ công.

8
Peter Lawrey

Hầu hết các JVM sẽ khởi động một GC (tùy thuộc vào -XX: DiableExplicitGC và -XX: + ExplicitGCInvokesConcản chuyển đổi). Nhưng đặc điểm kỹ thuật chỉ được xác định kém hơn để cho phép thực hiện tốt hơn sau này.

Thông số kỹ thuật cần làm rõ: Lỗi # 6668279: (spec) System.gc () sẽ cho biết rằng chúng tôi không khuyến nghị sử dụng và không đảm bảo hành vi

Bên trong phương thức gc được sử dụng bởi RMI và NIO và chúng yêu cầu thực thi đồng bộ, điều này: hiện đang được thảo luận:

Lỗi # 5025281: Cho phép System.gc () kích hoạt các bộ sưu tập đầy đủ đồng thời (không dừng lại trên thế giới)

5
eckes

Garbage Collection tốt trong Java, nếu chúng tôi đang thực thi Phần mềm được mã hóa trong Java trong Máy tính để bàn/máy tính xách tay/máy chủ. Bạn có thể gọi System.gc() hoặc Runtime.getRuntime().gc() trong Java.

Chỉ cần lưu ý rằng không có cuộc gọi nào được đảm bảo để làm bất cứ điều gì. Chúng chỉ là một gợi ý cho jvm để chạy Garbage Collector. Đó là JVM cho dù nó có chạy GC hay không. Vì vậy, câu trả lời ngắn gọn: chúng ta không biết khi nào nó chạy. Câu trả lời dài hơn: JVM sẽ chạy gc nếu có thời gian cho việc đó.

Tôi tin rằng, áp dụng tương tự cho Android. Tuy nhiên, điều này có thể làm chậm hệ thống của bạn.

2
Naveen

Thông thường, VM sẽ tự động thực hiện việc thu gom rác trước khi ném OutOfMemoryException, do đó, việc thêm một cuộc gọi rõ ràng không nên giúp đỡ ngoại trừ việc nó có thể chuyển hiệu suất đạt đến thời điểm sớm hơn.

Tuy nhiên, tôi nghĩ rằng tôi đã gặp một trường hợp có thể liên quan. Mặc dù vậy, tôi không chắc lắm, vì tôi vẫn chưa kiểm tra xem nó có ảnh hưởng gì không:

Khi bạn ánh xạ bộ nhớ một tệp, tôi tin rằng lệnh gọi map () sẽ ném IOException khi không có sẵn một khối bộ nhớ đủ lớn. Một bộ sưu tập rác ngay trước tập tin map () có thể giúp ngăn chặn điều đó, tôi nghĩ vậy. Bạn nghĩ sao?

2
Vashek

chúng tôi không bao giờ có thể buộc thu gom rác. System.gc chỉ đề xuất vm cho bộ sưu tập rác, tuy nhiên, thực sự thời gian cơ chế chạy, không ai biết, điều này được nêu trong thông số kỹ thuật của JSR.

2
lwpro2

Có rất nhiều điều phải nói khi dành thời gian để kiểm tra các cài đặt thu gom rác khác nhau, nhưng như đã đề cập ở trên, thường không hữu ích khi làm như vậy.

Tôi hiện đang làm việc trong một dự án liên quan đến môi trường bị giới hạn bộ nhớ và một lượng dữ liệu tương đối lớn - có một vài dữ liệu lớn đẩy môi trường của tôi đến giới hạn của nó, và mặc dù tôi có thể giảm mức sử dụng bộ nhớ rằng về mặt lý thuyết nó sẽ hoạt động tốt, tôi vẫn sẽ gặp lỗi không gian heap --- các tùy chọn GC dài dòng cho tôi thấy rằng nó đang cố gắng thu gom rác, nhưng không có kết quả. Trong trình gỡ lỗi, tôi có thể thực hiện System.gc () và chắc chắn sẽ có "nhiều" bộ nhớ khả dụng ... không có nhiều phụ, nhưng đủ.

Do đó, lần duy nhất ứng dụng của tôi gọi System.gc () là khi nó sắp vào đoạn mã nơi bộ đệm lớn cần thiết để xử lý dữ liệu sẽ được phân bổ và thử nghiệm trên bộ nhớ trống có sẵn cho biết tôi không Đảm bảo có nó. Cụ thể, tôi đang xem xét môi trường 1gb nơi có ít nhất 300mb bị chiếm giữ bởi dữ liệu tĩnh, với phần lớn dữ liệu không tĩnh có liên quan đến thực thi trừ khi dữ liệu được xử lý xảy ra ít nhất 100-200 MB tại nguồn. Đây là một phần của quá trình chuyển đổi dữ liệu tự động, vì vậy tất cả dữ liệu tồn tại trong khoảng thời gian tương đối ngắn trong thời gian dài.

Thật không may, mặc dù thông tin về các tùy chọn khác nhau để điều chỉnh bộ thu gom rác có sẵn, nhưng dường như phần lớn là một quy trình thử nghiệm và các chi tiết cụ thể ở cấp độ thấp hơn cần thiết để hiểu cách xử lý các tình huống cụ thể này không dễ dàng có được.

Tất cả điều đó đã được nói, mặc dù tôi đang sử dụng System.gc (), tôi vẫn tiếp tục điều chỉnh bằng cách sử dụng các tham số dòng lệnh và quản lý để cải thiện thời gian xử lý chung của ứng dụng của mình một lượng tương đối đáng kể, mặc dù không thể vượt qua vấp ngã khối đặt ra bằng cách làm việc với các khối dữ liệu lớn hơn. Điều đó đang được nói, System.gc () là một công cụ .... một công cụ rất không đáng tin cậy và nếu bạn không cẩn thận với cách bạn sử dụng nó, bạn sẽ ước rằng nó không hoạt động thường xuyên hơn không.

2
Kyune

Nói ngắn gọn:

Các tham số là VM phụ thuộc.

Sử dụng ví dụ - không thể nghĩ ra một ứng dụng cho thời gian chạy/ứng dụng sản xuất, nhưng thật hữu ích khi chạy nó cho một số khai thác định hình, như gọi điện

// test run #1
test();
for (int i=0; i<10; i++) { 
// calling repeatedly to increase chances of a clean-up
  System.gc(); 
}
// test run #2
test();
1
mataal

Nếu bạn muốn biết nếu System.gc() của bạn được gọi, bạn có thể với Java 7 bản cập nhật 4 mới nhận thông báo khi JVM thực hiện Bộ sưu tập rác.

Tôi không chắc chắn 100% rằng lớp GarbageCollectorMXBean đã được giới thiệu trong Java 7 bản cập nhật 4 mặc dù tôi không thể tìm thấy nó trong ghi chú phát hành, nhưng tôi đã tìm thấy thông tin trong javaperformancetuning . com trang web

1
Shervin Asgari

Theo Thinking in Java của Bruce Eckel, một trường hợp sử dụng cho cuộc gọi rõ ràng System.gc () là khi bạn muốn buộc quyết toán, tức là cuộc gọi đến hoàn thiện phương thức.

0
Asterisk

Tôi không thể nghĩ ra một ví dụ cụ thể khi chạy GC rõ ràng.

Nói chung, chạy GC rõ ràng thực sự có thể gây hại nhiều hơn lợi, bởi vì một gc rõ ràng sẽ kích hoạt một bộ sưu tập đầy đủ, mất nhiều thời gian hơn khi nó đi qua mọi đối tượng. Nếu gc rõ ràng này kết thúc việc được gọi liên tục, nó có thể dễ dàng dẫn đến một ứng dụng chậm vì nhiều thời gian được sử dụng để chạy các GC đầy đủ.

Ngoài ra, nếu đi qua heap với bộ phân tích heap và bạn nghi ngờ một thành phần thư viện đang gọi GC rõ ràng, bạn có thể tắt nó đi thêm: gc = -XX: + DisableExplicitGC vào các tham số JVM.

0
zxcv

trong khi system.gc hoạt động, nó sẽ dừng thế giới: tất cả các âm thanh đều bị dừng để trình thu gom rác có thể quét mọi đối tượng để kiểm tra xem có cần xóa không. nếu ứng dụng là một dự án web, tất cả các yêu cầu sẽ bị dừng cho đến khi gc kết thúc và điều này sẽ khiến dự án web của bạn không thể hoạt động được.

0
fleture