Tôi đang đọc một tệp rất lớn và trích xuất một số phần văn bản nhỏ từ mỗi dòng. Tuy nhiên vào cuối của hoạt động, tôi còn lại với rất ít bộ nhớ để làm việc với. Dường như bộ thu gom rác không giải phóng được bộ nhớ sau khi đọc trong tệp.Java không thu thập bộ nhớ rác
Câu hỏi của tôi là: Có cách nào để giải phóng bộ nhớ này không? Hay đây là lỗi JVM?
Tôi đã tạo SSCCE để chứng minh điều này. Nó đọc trong một tệp 1 mb (2 mb trong Java do mã hóa 16 bit) và trích xuất một ký tự từ mỗi dòng (~ 4000 dòng, vì vậy phải khoảng 8 kb). Vào cuối thử nghiệm, 2 mb đầy đủ vẫn được sử dụng!
Việc sử dụng bộ nhớ ban đầu:
Allocated: 93847.55 kb
Free: 93357.23 kb
Ngay sau khi đọc trong file (trước khi bất kỳ thu gom rác thải thủ công):
Allocated: 93847.55 kb
Free: 77613.45 kb (~16mb used)
Đây là để được mong đợi kể từ khi chương trình được sử dụng rất nhiều tài nguyên để đọc trong tệp.
Tuy nhiên sau đó tôi rác thu thập, nhưng không phải tất cả các bộ nhớ được giải phóng:
Allocated: 93847.55 kb
Free: 91214.78 kb (~2 mb used! That's the entire file!)
Tôi biết rằng bằng tay gọi thu rác không cung cấp cho bạn bất kỳ đảm bảo (trong một số trường hợp nó là lười biếng). Tuy nhiên điều này đã xảy ra trong ứng dụng lớn hơn của tôi, nơi tập tin chiếm hầu như tất cả bộ nhớ có sẵn, và làm cho phần còn lại của chương trình hết bộ nhớ mặc dù cần thiết. Ví dụ này xác nhận sự nghi ngờ của tôi rằng dữ liệu thừa đọc từ tệp không được giải phóng.
Đây là SSCCE để tạo ra các bài kiểm tra:
import java.io.*;
import java.util.*;
public class Test {
public static void main(String[] args) throws Throwable {
Runtime rt = Runtime.getRuntime();
double alloc = rt.totalMemory()/1000.0;
double free = rt.freeMemory()/1000.0;
System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);
Scanner in = new Scanner(new File("my_file.txt"));
ArrayList<String> al = new ArrayList<String>();
while(in.hasNextLine()) {
String s = in.nextLine();
al.add(s.substring(0,1)); // extracts first 1 character
}
alloc = rt.totalMemory()/1000.0;
free = rt.freeMemory()/1000.0;
System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);
in.close();
System.gc();
alloc = rt.totalMemory()/1000.0;
free = rt.freeMemory()/1000.0;
System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);
}
}
Trừ khi bạn đang làm điều gì đó rất bất thường mà không ai khác có khả năng làm, "lỗi jvm" không nên là giả định đầu tiên của bạn. –
Đặc biệt liên quan đến gc. –
Bạn mong đợi System.gc() để giải phóng toàn bộ bộ nhớ như thế nào? Bạn vẫn đang sử dụng các chuỗi trong al, vì vậy chúng không thể được giải phóng. –