2009-03-13 18 views
40

Nếu ứng dụng của tôi có quá nhiều biến hoặc phương pháp tĩnh, thì theo định nghĩa, chúng sẽ được lưu trữ trong heap. Vui lòng sửa cho tôi nếu tôi saiCó thể sử dụng quá nhiều biến tĩnh gây ra rò rỉ bộ nhớ trong Java không?

1) Các biến này có được lưu trữ cho đến khi ứng dụng được đóng không?
2) Chúng có sẵn cho GC bất kỳ lúc nào không? Nếu tôi không thể nói nó là một rò rỉ bộ nhớ?

Trả lời

76

Phương pháp tĩnh chỉ là phương pháp, chúng không được lưu trữ trên heap, chúng chỉ không sử dụng tham số "this".

Biến tĩnh đóng vai trò là "gốc" cho GC. Kết quả là, trừ khi bạn đặt chúng một cách rõ ràng thành null, chúng sẽ sống miễn là chương trình đang hoạt động và tất cả mọi thứ đều có thể truy cập được từ chúng.

Tình huống chỉ được coi là rò rỉ bộ nhớ nếu bạn định để bộ nhớ tự do và không trở nên miễn phí. Nếu bạn dự định biến tĩnh của bạn chứa tham chiếu đến một đối tượng trong một phần thời gian, và bạn quên đặt nó thành null khi bạn đã hoàn thành với đối tượng đó, bạn có thể sẽ bị rò rỉ. Tuy nhiên, nếu bạn đặt nó trong biến tĩnh và có ý định cho nó ở đó miễn là chương trình đang chạy, thì chắc chắn nó không phải là một sự rò rỉ, nó có thể là một "singleton vĩnh viễn". Nếu đối tượng bị khai hoang trong khi bạn muốn nó vẫn tồn tại, điều đó sẽ rất tệ.

Đối với câu hỏi của bạn về heap: Tất cả các đối tượng trong Java tồn tại trên đống hoặc trên ngăn xếp. Các đối tượng được tạo trên heap với toán tử mới. Sau đó, một tham chiếu được đính kèm với chúng. Nếu tham chiếu trở thành null hoặc nằm ngoài phạm vi (ví dụ: kết thúc khối), GC sẽ nhận ra rằng không có cách nào để tiếp cận đối tượng đó một lần nữa và reclaims nó. Nếu tham chiếu của bạn nằm trong một biến tĩnh, nó không bao giờ nằm ​​ngoài phạm vi nhưng bạn vẫn có thể đặt nó thành null hoặc cho một đối tượng khác.

+0

IIRC các trường tĩnh sẽ được GCed ngay sau khi lớp khai báo là GC.Nếu trường hợp elast thứ nhất của lớp đó biến mất thì khai báo lớp sẽ đi và các trường tĩnh với nó. – ordnungswidrig

+1

Tôi không chắc chắn nếu @ o11rig hoàn toàn chính xác, nhưng tôi tin rằng GC được phép thu thập các số liệu thống kê cho các lớp học không có thành viên trong một số trường hợp nhất định. Tôi đã nghe điều này từ một vài nguồn, nhưng chưa bao giờ nghe một lời giải thích chính xác. –

+0

Giảm phân tán: Tất cả các đối tượng Java * * đều nằm trong vùng heap. Tham chiếu * đối tượng * và nguyên thủy có thể được lưu trữ trên ngăn xếp nếu chúng là người dân địa phương của phương pháp hiện đang thực hiện và được lưu trữ trên heap nếu không. (Ngoại trừ trong bất kỳ JVM hiện đại nào có JIT, nơi trình tối ưu hóa của JIT có thể đặt các đối tượng ở bất cứ nơi nào nó thích, miễn là nó vẫn hoạt động * như các đối tượng nằm trên đống.) Và có thể lập luận rằng các phương thức tĩnh - hoặc , ít nhất, mã byte Java thực hiện chúng - cũng sống trên heap, như là một phần của đối tượng Class đại diện cho lớp mà chúng được định nghĩa. –

1

Miễn là bạn có thể tham chiếu các biến này từ một nơi nào đó trong mã, nó không thể được GCed có nghĩa là chúng sẽ ở đó cho đến khi kết thúc ứng dụng.

Bạn có thể gọi nó là rò rỉ bộ nhớ, tôi không gọi nó là rò rỉ bộ nhớ, thường là bộ nhớ bị rò rỉ là bộ nhớ mà bạn thường phục hồi nhưng bạn không bao giờ làm, hoặc bạn chỉ phục hồi một phần. Ngoài ra, rò rỉ bộ nhớ thường trở nên tệ hơn theo thời gian (ví dụ: mỗi khi bạn gọi một phương thức bộ nhớ nhiều hơn là "bị rò rỉ"), tuy nhiên trong trường hợp này việc sử dụng bộ nhớ cho các biến đó là (loại) tĩnh.

+0

Không cần các biến tĩnh được tham chiếu từ mã của bạn ... trình nạp lớp sẽ giữ nguyên tham chiếu và do đó GC sẽ không bao giờ khởi động. – ReneS

1

Nó sẽ không gây ra rò rỉ bộ nhớ theo nghĩa C cổ điển ... Ví dụ

Class A{ 

static B foo; 

... 

static void makeFoo(){ 
    foo = new B(); 
    foo = new B(); 
} 

Trong trường hợp này, một cuộc gọi đến makeFoo() sẽ không dẫn đến rò rỉ bộ nhớ, như ví dụ đầu tiên có thể là rác được thu thập.

2

Các đối tượng được tham chiếu trực tiếp hoặc gián tiếp bởi các số liệu thống kê sẽ vẫn còn trên heap cho đến khi trình tải lớp thích hợp có thể được thu thập. Có những trường hợp (ThreadLocal, ví dụ), nơi các đối tượng khác gián tiếp tham chiếu đến trình nạp lớp khiến cho nó vẫn không bị thu thập.

Nếu bạn có Danh sách tĩnh, nói và thêm tham chiếu vào danh sách tĩnh, thì bạn có thể dễ dàng kết thúc với "vấn đề tranh chấp về cuộc đời đối tượng". Tránh các số liệu thống kê có thể thay đổi được vì nhiều lý do.

3

Nếu bạn có một hashmap tĩnh và bạn thêm dữ liệu vào nó ... dữ liệu sẽ không bao giờ biến mất và bạn bị rò rỉ - trong trường hợp bạn không cần dữ liệu nữa. Nếu bạn cần dữ liệu, nó không phải là một rò rỉ, nhưng một đống lớn của bộ nhớ treo xung quanh.

+0

Giả sử hashmap tĩnh có rất nhiều đối tượng; và tôi đã thực hiện tham chiếu của bản đồ thành null (không phải tất cả các đối tượng chứa nó)? nó có bị rò rỉ bộ nhớ không? vì bạn đã tuyên bố rằng "trình nạp lớp vĩnh viễn giữ một tham chiếu tĩnh và do đó GC sẽ không bao giờ khởi động"? –

+0

Nếu bạn đặt tham chiếu tĩnh thành null và bạn chưa tham chiếu bản đồ đó ở bất kỳ nơi nào khác, bộ nhớ sẽ được giải phóng. Các đối tượng được tham chiếu trong ánh xạ đó cũng sẽ được giải phóng nếu chúng không được người khác tham chiếu. – ReneS

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