Các trường tĩnh có mở để thu gom rác không?


95

Đưa ra một lớp tiện ích giả định chỉ được sử dụng trong thiết lập chương trình:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

myObject sẽ được thu gom khi nó không còn được sử dụng nữa hay nó sẽ tồn tại trong suốt thời gian của chương trình?

Câu trả lời:


112

Các biến tĩnh không thể được chọn để thu gom rác trong khi lớp được tải. Chúng có thể được thu thập khi trình tải lớp tương ứng (chịu trách nhiệm tải lớp này) được thu gom để dọn rác.

Kiểm tra JLS Phần 12.7 Dỡ bỏ các lớp và giao diện

Một lớp hoặc giao diện có thể được dỡ bỏ nếu và chỉ khi bộ tải lớp xác định của nó có thể được bộ thu gom rác khôi phục [...] Các lớp và giao diện được bộ tải bootstrap tải có thể không được dỡ bỏ.


@bruno, Theo liên kết của bạn, điều đó có nghĩa là trình nạp lớp giữ một tham chiếu đến từng và mọi lớp mà nó tải, ngay cả khi lớp được tải không có thành viên tĩnh?
Pacerier

@brunoconde, tôi không nghĩ điều đó thực sự đúng. Chính xác thì đoạn nào nói lên điều đó? (Vui lòng tiếp tục thảo luận trên stackoverflow.com/questions/405364/… )
Pacerier

Khi trình tải lớp sẽ đủ điều kiện để thu gom rác. ?
Rohit Bandil

@RohitBandil - khi không thể truy cập được.
Stephen C

55

Các biến tĩnh được tham chiếu bởi các đối tượng Lớp được tham chiếu bởi ClassLoader - ngoài ra trừ khi ClassLoader loại bỏ Lớp bằng cách nào đó (nếu điều đó thậm chí có thể) hoặc chính ClassLoader trở nên đủ điều kiện để thu thập (nhiều khả năng hơn - hãy nghĩ đến việc dỡ các ứng dụng web) các biến tĩnh (hoặc đúng hơn, các đối tượng mà họ tham chiếu) sẽ không được thu thập.


1
Các Classđối tượng không chứa biến tĩnh có được tham chiếu bởi trình nạp lớp của chúng không?
Pacerier

14

Nếu bạn muốn một đối tượng tạm thời được sử dụng để khởi tạo tĩnh sau đó bị loại bỏ, bạn có thể sử dụng khối khởi tạo tĩnh, ví dụ:

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

vì khối khởi tạo tĩnh là một loại phương thức tĩnh đặc biệt, myObject là một biến cục bộ và có thể được thu gom sau khi khối kết thúc thực thi.


13

myObject là một tham chiếu chứ không phải một đối tượng . Một đối tượng được tự động thu thập rác khi không có tham chiếu nào trỏ đến nó vì nó không thể truy cập được.

Vì vậy, đối tượng đằng sau một tham chiếu tĩnh "myObject" có thể được thu thập rác nếu bạn tham khảo nó với

myObject = null;

và không có tham chiếu nào khác đến đối tượng này.

Tuy nhiên, các tham chiếu tĩnh và các biến vẫn tồn tại trong suốt thời gian hoạt động của chương trình của bạn.


Chào mừng bạn đến với StackOverflow! Đặt đối tượng nullở cuối static blocklà một lựa chọn khả thi. Tuy nhiên, trong trường hợp của tôi, thời gian tồn tại của đối tượng cần phải dài hơn khối tĩnh. Tính hữu dụng cuối cùng của đối tượng không cụ thể lắm; do đó, câu hỏi của tôi về việc sử dụng bộ thu gom rác.
Michael Deardeuff

7

Tôi nghĩ điều này trả lời câu hỏi của bạn - về cơ bản là không trừ khi lớp đó đến từ một trình tải lớp đặc biệt và nó sẽ dỡ lớp đó.


0

Chìa khóa ở đây là Bộ sưu tập rác của các cá thể Lớp tức là Đối tượng. Về bản chất, cá thể ClassLoader là một Đối tượng. Vì vậy, nếu đối tượng Classloader không được thu gom rác, bất kỳ tham chiếu nào của chúng được lưu trữ trong heap (tức là nội dung tĩnh) sẽ gần như không bao giờ được thu gom rác. Ngoại lệ là String pool.

Vì vậy, trước khi bạn đột nhiên quyết định làm private static MyGiantClass myGiantObject = new MyGiantClass() Hãy suy nghĩ hai lần như tôi đã học được một cách khó khă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.