2013-03-05 38 views
11

Giả sử tôi có đoạn mã sau:Garbage Collection Java trên Mảng stack-Based

public void process() { 
    byte[] data = new byte[size]; 
    ... // code that uses the above data 
    longProcess(); // a very long running process that does not use the data. 
} 

Giả sử rằng các dữ liệu không được tham chiếu bất cứ nơi nào khác trong chương trình, là JVM đủ thông minh để cho phép các dữ liệu được rác được thu thập trong khi quá trình dài vẫn đang chạy?

Nếu không, sẽ thêm

data = null; 

trước khi quá trình dài cho phép điều này xảy ra?

+0

có thể, có thể. – Cubic

+0

Bạn chỉ có thể bao quanh mã bằng dấu ngoặc vuông. – MikeTheLiar

+0

'dữ liệu = null' làm cho nó đủ điều kiện để được thu gom rác. –

Trả lời

6

Điều này phụ thuộc vào JVM. Các phiên bản của JVM của Oracle mà tôi đã thử (1.6.0_41 và 1.7.0_09) không thực hiện tối ưu hóa này theo mặc định. Tuy nhiên, 1.7.0_09 thực hiện nó khi tối ưu hóa tích cực được bật.

Dưới đây là là kiểm tra tôi đã thực hiện:

public class Main { 
    public static int g() { 
     int n = 100000; 
     int arr[][] = new int[n][]; 
     for (int i = 0; i < n; ++i) { 
      try { 
       arr[i] = new int[100000]; 
      } catch (OutOfMemoryError ex) { 
       return i; 
      } 
     } 
     return -1; 
    } 
    public static void f1() { 
     int arr[] = new int[1000000]; 
     System.out.println(g()); 
    } 
    public static void f2() { 
     int arr[] = new int[1000000]; 
     arr = null; 
     System.out.println(g()); 
    } 
    public static void main(String[] argv) { 
     for (int j = 0; j < 2; ++j) { 
      for (int i = 0; i < 10; ++i) { 
       f1(); 
      } 
      System.out.println("-----"); 
      for (int i = 0; i < 10; ++i) { 
       f2(); 
      } 
      System.out.println("-----"); 
     } 
    } 
} 

Sử dụng JVM 1,7 với các thiết lập mặc định, f1() liên tục chạy ra khỏi bộ nhớ sau 3195 lần lặp lại, trong khi f2() thống nhất quản lý 3205 lần lặp lại.

Hình ảnh thay đổi nếu mã được chạy bằng Java 1.7.0_09 với -XX:+AggressiveOpts -XX:CompileThreshold=1: cả hai phiên bản có thể thực hiện 3205 lần lặp lại, cho biết HotSpot thực hiện tối ưu hóa này trong trường hợp này. Java 1.6.0_41 không xuất hiện để làm điều này. Trong thử nghiệm của tôi, hạn chế phạm vi của mảng có cùng tác dụng như thiết lập tham chiếu null và có lẽ nên là lựa chọn ưu tiên nếu bạn cảm thấy bạn nên giúp JVM thu thập mảng càng sớm càng tốt.

+0

bạn đã thử chơi xung quanh với cờ opts tích cực chưa? – radai

+0

@radai: Bạn nghĩ gì về lá cờ? – NPE

+0

-XX: + AggressiveOpts -XX: Biên dịchThreshold = 1 chủ yếu, để thử và ép buộc biên dịch và tối ưu hóa – radai

0

Nếu không có tham chiếu đến dữ liệu, thì GC sẽ thực hiện công việc.

+0

Điều này không trả lời được câu hỏi. chỉnh sửa: Tôi không phải là downvoter bằng cách này :) –

+0

Những gì ông nói là một tham chiếu đến mảng tồn tại trong phạm vi, nhưng nó không được sử dụng cho phần còn lại của (dài chạy) thực hiện của chương trình. Tôi nghĩ rằng câu hỏi có thể được diễn đạt tốt hơn: "Dữ liệu có thể là rác được thu thập nếu một tham chiếu tồn tại nhưng không được sử dụng?" – asteri

1

Với mã được viết, mảng chắc chắn sẽ không được thu thập rác trong quá trình thực thi longprocess(), vì vẫn còn một tham chiếu phạm vi cho mảng trên ngăn xếp. Khi mảng đó đã được khai báo, nó sẽ không đủ điều kiện để thu thập rác cho đến khi tất cả các tham chiếu đến nó đã bị loại bỏ. Dòng của bạn

data = null; 

sẽ xóa một tham chiếu đến nó, mặc dù tùy thuộc vào mã xử lý của bạn, nó có thể không phải là tham chiếu duy nhất. Nếu tất cả các tham chiếu đã được gỡ bỏ, thì bộ thu gom rác có thể thu thập rất tốt bộ nhớ của mảng đó theo thời gian longprocess() trả về, mặc dù điều này không được đảm bảo.

0

Mảng dữ liệu sẽ chỉ được deallocated với bộ nhớ sau khi phương pháp xử lý kết thúc. Vì vậy, nếu bạn muốn trình biên dịch để deallocate bộ nhớ thì bạn sẽ phải rõ ràng thêm dữ liệu = null trong mã.

Bộ gom rác chỉ giải phóng bộ nhớ không có tham chiếu hợp lệ có sẵn và không còn cách nào khác để trỏ đến bộ nhớ đó nữa.

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