2010-01-19 27 views
8

Tôi nghe tài sản thanh lịch nhất của java là Garbage Collection Tôi muốn biết nó có đảm bảo rằng một chương trình sẽ không hết bộ nhớ?Việc thu gom rác có đảm bảo rằng một chương trình sẽ không hết bộ nhớ?

+4

Nếu thu thập rác có nghĩa là ứng dụng nhiều terabyte của tôi không bao giờ hết bộ nhớ, điều đó sẽ thực sự tuyệt vời để xử lý các tập dữ liệu lớn. –

Trả lời

10

Không, nó không đảm bảo điều này. Nó là hoàn toàn có thể cho một lập trình viên nhầm lẫn tạo ra các đối tượng mà không bao giờ đi ra khỏi phạm vi, do đó tiêu thụ nhiều hơn và nhiều hơn nữa bộ nhớ cho đến khi tất cả heap là kiệt sức.

Trách nhiệm của người lập trình là đảm bảo rằng các đối tượng không còn được sử dụng không còn được tham chiếu bởi ứng dụng. Bằng cách đó, người thu gom rác có thể thực hiện công việc của mình và thu hồi bộ nhớ được sử dụng bởi các đối tượng này.

Ví dụ

public class Main { 
    public static void main(String[] main) { 
    List<String> l = new LinkedList<String>(); 

    // Enter infinite loop which will add a String to 
    // the list: l on each iteration. 
    do { 
     l.add(new String("Hello, World")); 
    } while(true); 
    } 
} 
+0

bạn có thể làm cho bộ nhớ bị chảy máu nhanh hơn nhiều nếu bạn làm cho chuỗi lớn hơn :) – medopal

+0

Thật vậy ... mặc dù tôi đã rõ ràng được gọi là "mới" để tránh tham chiếu cùng một chuỗi chữ. – Adamski

2

số Nếu bạn xây dựng rất nhiều các đối tượng (triệu) và giữ một tham chiếu đến họ để họ không đi ra khỏi phạm vi (ví dụ bằng cách thêm chúng vào một ArrayList), bạn có thể hết bộ nhớ địa chỉ.

4

Không, vẫn còn nhiều cách để hết bộ nhớ. Bộ thu gom rác chỉ có thể lấy lại bộ nhớ cho các đối tượng không còn được tham chiếu nữa - điều đó tùy thuộc vào bạn để đảm bảo rằng bạn không tham chiếu các đối tượng bạn không cần hoặc sử dụng Tham chiếu mềm cho các đối tượng bạn muốn có, nhưng không tâm trí biến mất nếu bộ nhớ bị chặt chẽ.

22

Không, bạn luôn có thể cố gắng cấp phát bộ nhớ nhiều hơn khả dụng.

Thu gom rác tự động chỉ có nghĩa là rác (tức là bộ nhớ không được thu nhận) sẽ tự động được thu thập (tức là, được khai hoang để sử dụng thêm). Nếu bạn giữ tham chiếu đến nó, nó không phải là rác, và không được thu thập.

1

Tuyệt đối không. Ngay cả trong một ngôn ngữ thu thập rác như Java, bạn có thể dễ dàng mất các tham chiếu, có nghĩa là các đối tượng sẽ không bao giờ bị thu gom rác.

Thậm chí sau đó, bạn có thể đơn giản khởi tạo (và giữ tham chiếu đến) quá nhiều đối tượng để hệ thống xử lý.

1

Làm thế nào có thể bất kỳ điều gì đảm bảo một chương trình không hết bộ nhớ để tự ý xóa một mục khỏi bộ nhớ để dành chỗ cho phân bổ mới?

Bây giờ, điều gì sẽ xảy ra nếu bạn thực sự giữ một tham chiếu về (sử dụng) thứ được chọn ngẫu nhiên để được loại bỏ? Bạn sẽ sớm có hành vi không chính xác.

0

Không. Bộ sưu tập rác chỉ bảo vệ chống lại một loại rò rỉ bộ nhớ. Cụ thể, loại xảy ra nếu bạn không giải phóng bộ nhớ một cách rõ ràng khi ứng dụng của bạn không còn cần đến nữa. Nếu ứng dụng của bạn giữ các tham chiếu đến các đối tượng không cần thiết (ví dụ: các Danh sách mai mai), trình thu gom rác không thể xóa chúng và ứng dụng của bạn vẫn có thể hết bộ nhớ.

0

Không, hoàn toàn không.

Trong các ngôn ngữ không thu thập rác, lập trình viên (hoặc thư viện mà anh ta sử dụng) chịu trách nhiệm đưa ra yêu cầu cho bộ nhớ và trả lại bộ nhớ được cấp cho "tái chế". không có đảm bảo rằng bộ nhớ sẽ có sẵn khi nó được yêu cầu. Tuy nhiên, nếu bạn không bao giờ rõ ràng "tái chế", có thể có trường hợp yêu cầu bị từ chối vì không có bộ nhớ, nhưng nếu bộ nhớ được tái chế thì khối đó có thể đã được trả lại cho yêu cầu này.

Việc thu thập rác tự động có nghĩa là hệ thống có thể tái chế cho bạn. Kết quả là, một số yêu cầu sẽ được lấp đầy bằng cách sử dụng bộ nhớ "tái chế". Tuy nhiên, như với các ngôn ngữ không phải GC, một số yêu cầu không thể được lấp đầy. Ví dụ, nếu hệ thống của bạn có 1000 khối có sẵn và bạn cần 1500 cùng một lúc, không GC nào trên thế giới sẽ giúp bạn vì không có gì thực sự có sẵn để tái chế.

0

Không, việc thu thập rác không thể đảm bảo rằng ứng dụng của bạn sẽ không hết bộ nhớ. Nó thậm chí sẽ không đảm bảo rằng ứng dụng của bạn sẽ không hết bộ nhớ khi bộ nhớ có sẵn. Nếu bạn đến gần hết bộ nhớ hoặc đang phân bổ nhiều đối tượng, nó có thể khiến GC bị thrash, ném ra một ngoại lệ bộ nhớ. Chương trình cũng có thể hết bộ nhớ khi nó đã sử dụng tất cả bộ nhớ vật lý (thực tế và ảo) hoặc chương trình vượt quá bộ nhớ tối đa cho phép bởi JVM (xem -Xmx).

0

No. Bộ thu gom rác, giúp bạn tự động giải phóng bộ nhớ không sử dụng.

Cách thức hoạt động là, nếu không thể liên lạc với đối tượng, bộ nhớ cho đối tượng đó có thể là rác được thu thập.

Ví dụ:

public void test() { 
    Object o = new Object(); 
    // the memory used by o may be garbage collected after this line 
} 

Nhưng nếu bạn không bao giờ phát hành tài liệu tham khảo đối tượng, thu gom rác sẽ không bao giờ thu thập bất cứ điều gì và một OutOfMemoryError sẽ được ném ra.

List list = .... 
public void test() { 
    o = new Object(); 
    list.add(o); 
    // the memory used by o WON'T be garbage collected after this line 
    // because its reference is used in the list. 
} 

Nếu bạn sử dụng điều này nhiều lần:

while(true) { 
    test(); 
} 

Danh sách này sẽ tiếp tục tăng trưởng vô thời hạn cho đến khi bạn chạy ra khỏi bộ nhớ

3

Để trả lời câu hỏi của bạn, NO. Thu gom rác không đảm bảo rằng một chương trình sẽ không hết bộ nhớ.

  • Xem xét đối tượng bạn không muốn sử dụng bất kỳ thứ gì khác giống như rác.
  • Tham chiếu đến các đối tượng đó sẽ là giống như có rác trong nhà của bạn.
  • Bộ sưu tập rác giống như xe tải chở rác của thị trấn thu gom rác.
  • Nếu bạn sẽ không tiết lộ những tài liệu tham khảo , nó cũng giống như không dùng rác ra và chẳng mấy chốc ngôi nhà của bạn sẽ be qua đầy rác như kẻ xe tải rác sẽ không đưa ra rác từ ngôi nhà của bạn.

Đối tượng không được xử lý sẽ được thu gom rác tự động bởi bộ thu gom rác. Trong java, hầu hết các tham chiếu đến các đối tượng được phát hành tự động khi bạn thoát khỏi phương thức.

Đối tượng có tham chiếu đến các đối tượng khác, từ đó tham chiếu đến các đối tượng khác tạo đồ thị toàn bộ đối tượng. Vì vậy, như đối tượng như vậy có thể được tham chiếu bởi nhiều hơn một đối tượng.

  • Nếu đối tượng không có tham chiếu bằng không, nó đủ điều kiện để thu gom rác thải .
  • Đối tượng được phân bổ trên heap.
  • Bộ thu gom rác chạy từ thời gian tới thời gian để xóa các đối tượng không được kiểm duyệt từ heap.
  • Nếu bạn liên tục tạo nhiều đối tượng trên đống mà không giải phóng bạn sẽ cuối cùng có được OutOfMemoryError

Ví dụ với thu gom rác thải tại nơi làm việc

public class TestGarbageNoError { 

public static void main(String[] args) { 
    String hugeString; 
    for (int i = 0; i < Integer.MAX_VALUE; i++) { 
    System.out.println("i = " + i); 
    hugeString = getHugeString(); 
    // At each iteration reference variable hugeString 
    // points to new String object. Hence there will be 
    // zero reference to previous string object and will 
    // eventually be garbage collected 
    } 
} 

public static String getHugeString() { 
    StringBuilder sb = new StringBuilder(); 
    for (int x = 0; x < 5000000; x++) { 
    sb.append(x); 
    } 
    return sb.toString(); 
} 
} 

.

Ví dụ với bộ nhớ bị rò rỉ tại nơi làm việc

public class TestGarbageError { 

public static void main(String[] args) { 
    Collection<String> memoryLeak = new ArrayList<String>(); 
    for (int i = 0; i < Integer.MAX_VALUE; i++) { 
    System.out.println("i = " + i); 
    String hugeString = getHugeString(); 
    memoryLeak.add(hugeString); 
    // At each iteration reference variable hugeString 
    // points to new String object. But all objects are added 
    // to memoryLeak Collection and will always have atleast one 
    // reference, i.e. from memoryLeak object. Hence this string 
    // objects will never be garbage collected and program will 
    // eventually run out of memory 
    } 
} 

public static String getHugeString() { 
    StringBuilder sb = new StringBuilder(); 
    for (int x = 0; x < 5000000; x++) { 
    sb.append(x); 
    } 
    return sb.toString(); 
} 
} 
+0

không hiểu nó, trong ví dụ thứ hai String được định nghĩa trong vòng lặp, do đó, với mỗi con trỏ lặp đang bị mất trên stack, có thể ghi đè bằng một cái mới (cách nhìn của tôi về cách mọi thứ đang diễn ra). Vui lòng giải thích những gì xảy ra trên mỗi lần lặp với đối tượng String này .... –

+0

Bạn đã bỏ lỡ dòng "memoryLeak.add (hugeString);". Đây là nơi tham chiếu đến mọi chuỗi được duy trì do bộ nhớ bị rò rỉ. Hãy thử chạy cả hai chương trình, bạn sẽ thấy sự khác biệt trong kết quả. –

+0

ahh ... vâng, bây giờ tôi đã thấy thêm dòng. Offcourse, nếu một nơi nào đó là mã memoryLeak.get (..), objetc phải giữ tham chiếu đến String. Tôi nghĩ rằng một cái gì đó đã được với nơi định nghĩa nơi String bigString được đặt ... –

0

Tuy nhiên, nó được đảm bảo rằng trước khi JVM tuyên bố OutOfMemoryException nó rác sẽ thu thập tất cả các tài liệu tham khảo phải thu và xem xét để sử dụng bộ nhớ bây giờ miễn phí.

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