* Tôi đang gặp phải một vấn đề java GC rất lạ khi tôi cố gắng tạo một nút trong JFrame và khi tôi nhấp vào nút, nó hiển thị một JDialog cần phải xử lý và hiển thị một số hình ảnh và cần gần 200 triệu bộ nhớ. Nhưng vấn đề là khi tôi đóng hộp thoại và mở lại nó, đôi khi nó gây ra java.lang.OutOfMemoryError. (không phải mọi lần)Thu gom rác java trong hộp thoại
Cố gắng giải quyết vấn đề, tôi đơn giản hóa vấn đề này và thực hiện một số thử nghiệm, khiến tôi bối rối hơn.
Mã tôi đã sử dụng trong "thử nghiệm" của mình được hiển thị bên dưới. Khi tôi bấm vào một nút trong một khung, tôi cấp phát bộ nhớ 160M cho một mảng số nguyên và hiển thị hộp thoại, Nhưng nếu tôi đóng hộp thoại và mở lại, thì OutOfMemoryError sẽ xuất hiện. Tôi điều chỉnh mã và kết quả là:
- Nếu tôi không tạo hộp thoại và hiển thị nó, không có vấn đề về bộ nhớ.
- Nếu tôi thêm một cửa sổCloseListener gọi System.gc() vào hộp thoại, không có vấn đề về bộ nhớ.
Nếu tôi gọi System.gc() trong phương thức run(), vấn đề bộ nhớ sẽ hiển thị.
public class TestController { int[] tmp; class TDialog extends JDialog { public TDialog() { super(); this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); // If I uncommment this code, OutOfMemoryError seems to dispear in this situation // But I'm sure it not a acceptable solution /* this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.out.println("windowsclose"); TDialog.this.dispose(); System.gc(); } }); */ } } TDialog dia; public void run() { // If I do System.gc() here, OutOfMemoryError still exist // System.gc(); tmp = new int[40000000]; for (int i = 0; i < tmp.length; i += 10) tmp[i] = new Random().nextInt(); dia = new TDialog(); dia.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { final JFrame frame = new JFrame("test"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setSize(200, 200); JButton button = new JButton("button"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { TestController controller = new TestController(); controller.run(); controller = null; } }); frame.add(button); frame.setVisible(true); } }); } }
Tôi đã đọc về một bài viết rất nhiều trong đó mô tả cách làm việc GC java của. Tôi nghĩ rằng nếu java cố gắng phân bổ một số không gian trong heap và nó không có đủ không gian trống, java sẽ làm gc, và nếu một đối tượng không thể được truy cập từ gốc gc thông qua "đồ thị GC", trong đó một cạnh từ u để v đại diện cho u có một tham chiếu đến v, root là một cái gì đó trong một ngăn xếp thread làm việc, hoặc nguồn gốc, Nó vô dụng và đủ điều kiện để được thu thập bởi GC của java.
Bây giờ vấn đề là Khi tôi nhấp vào nút và cố gắng tạo mảng Integer, mảng Integer tôi tạo lần trước chắc chắn đủ điều kiện để được thu thập bởi GC của java. Vậy tại sao nó gây ra lỗi.
Xin lỗi cho mô tả dài như vậy ... Tôi không có nhiều chiến thuật trong việc đặt vấn đề, vì vậy chỉ cần cố gắng làm rõ.
Bên cạnh đó, Các thông số tôi sử dụng để bắt đầu JVM là “java -Xmx256m”
1+ cho những nỗ lực của bạn khi gỡ lỗi, để tạo ra một sscce và dành nỗ lực vào câu hỏi của bạn. Tôi không có thời gian trong công việc để chạy hoặc gỡ lỗi chương trình của bạn, nhưng tôi tự hỏi liệu bạn có gặp sự cố với sự kiên trì các tham chiếu mềm do người nghe đưa ra hay không. –
Điều gì sẽ xảy ra nếu bạn thực hiện hộp thoại * phương thức *, và sau đó trong mã gọi hộp thoại, hủy bỏ hộp thoại sau khi sử dụng bằng cách gọi 'dispose()' trên đó. –