2012-01-09 21 views
5

Đối với một dự án, chúng ta cần một cách để chạy tập lệnh người dùng có thể đi kèm với các tệp JAR đính kèm với các lớp bổ sung.Tôi có thể kiểm tra GC bằng cách nào?

Tùy chọn của tôi là gì khi tôi muốn viết một vài bài kiểm tra để đảm bảo tập lệnh thông thường không để lại bất kỳ điều gì lơ lửng phía sau?

Tôi đặc biệt cần biết: Có phải tất cả các lớp từ các tệp JAR đính kèm "chưa được tải" không?

Lưu ý: Tôi không tìm kiếm giải pháp siêu kín 100% hoạt động trên tất cả các phiên bản Java từ 1.0 đến 7. Ngay bây giờ, tôi chỉ cần tốt hơn "Tôi không có ý tưởng".

+0

Tại sao họ sẽ được bốc dỡ? Bạn có nghĩa là trường hợp của họ sẽ được GCed, tức là, mã và thư viện của các kịch bản người dùng không có rò rỉ bộ nhớ? Bạn đang tải chúng với trình nạp lớp mới? –

+0

Có. Những gì tôi muốn là một cách để hỏi GC "bạn có thể GC dụ này ngay bây giờ?" Hoặc có thể "cho tôi biết có bao nhiêu tài liệu tham khảo tồn tại cho ví dụ' foo' "Làm thế nào để profilers làm điều đó? –

Trả lời

3

Tùy chọn tốt nhất có thể là để đảm bảo các bình nạp của bạn được nạp bởi một trình nạp lớp cụ thể và sau đó loại bỏ trình nạp lớp đó (sau khi loại bỏ tất cả các đối tượng). Theo như đơn vị kiểm tra dỡ hàng, nếu bạn đi với tùy chọn này, bạn cần phải mở rộng khung kiểm tra của bạn và trình nạp lớp tùy chỉnh để có cờ "tạo lớp tải theo yêu cầu". Sau đó, bạn tải lớp một lần với cờ trên, loại bỏ bộ nạp lớp, và cố gắng tải lớp một lần nữa với cờ tắt. Nếu lớp học thực sự không thể truy cập được, lần thử thứ hai sẽ ném một lớp ngoại lệ không tìm thấy. Sau đó bạn quấn các bài kiểm tra đơn vị của mình để vượt qua nếu chúng rơi vào ngoại lệ, và thất bại nếu chúng thành công trong việc nhấn vào dòng sau lần thử tải thứ hai.

Nếu bạn bị xử lý để sử dụng nhiều hơn các công cụ thuần Java, một thùng chứa OSGi có thể được xem xét. Hầu hết các triển khai vùng chứa OSGi được thiết lập rõ ràng kiểm tra việc dỡ lớp.

+0

+1 cho tùy chọn thứ hai.Để chắc chắn 100% (mà tôi biết không phải là yêu cầu), có thể bạn sẽ cần chạy trình nạp lớp với trình quản lý bảo mật (để đảm bảo rằng các tập lệnh không tạo chủ đề, v.v.). –

+0

@Sean Reilly, Cảm ơn. Các tùy chọn khác trở thành tiếng ồn, vì vậy tôi đã chuyển thông điệp đến gần đầu hơn. –

+0

Điểm của câu hỏi có vẻ là Aaron đã làm những gì bạn mô tả trong đoạn đầu tiên, nhưng vì bạn không thể loại bỏ một cách rõ ràng các đối tượng Java, nên anh ta muốn một cách để kiểm tra xem nó có thực sự xảy ra ngầm hay không. –

3

Tôi sẽ không cố gắng kiểm tra đơn vị này. Thay vào đó, tôi sẽ chạy JVM với -XX: -TraceClassUnloading và tìm xem các lớp trong câu hỏi có xuất hiện trong đầu ra dấu vết hay không.

1

Điều này phụ thuộc hoàn toàn vào cách bạn cho phép tập lệnh chạy. Họ có quyền truy cập vào các lớp của phần còn lại của ứng dụng không?

Cách thông thường để rò rỉ bộ nhớ trong Java là có tham chiếu tĩnh. Một tham chiếu tĩnh chỉ tĩnh trong ClassLoader của lớp có chứa nó. Vì vậy, nếu bạn tải các kịch bản người dùng bằng cách sử dụng một ClassLoader bạn quản lý chính mình (và bạn nên làm điều này anyway), sau đó các tài liệu tham khảo (tĩnh hoặc không) bên trong sẽ được eligable cho GC ngay sau khi classloader của bạn chính nó.

Cách duy nhất họ có thể giải quyết vấn đề này là thêm một tham chiếu đến một trong các đối tượng của họ vào một trong các đối tượng của bạn. Vì vậy, bạn phải rất cẩn thận với API bạn vạch trần. Một cách khác là nếu họ sẽ thực hiện một tham chiếu tĩnh đến lớp của họ trong một lớp học từ một ClassLoader khác.

Tôi không thấy cách hoàn toàn tự động kiểm tra cho việc này. Nhưng tôi cho rằng bạn có thể theo dõi các lớp dỡ hàng với bất kỳ profiler phong nha.

2

Có vẻ như những gì bạn muốn kiểm tra là các tập lệnh ống không có số classloader leak.

Để làm điều đó, tôi muốn tạo ra một WeakReference đến ClassLoader sử dụng để tải JAR, sau đó chạy kịch bản, sau đó gọi System.gc() và sau đó assertNull(reference.get())

+0

một giải pháp thay thế có thể là tạo một thể hiện của URLClassLoader trên mỗi JAR có lẽ và sử dụng nó để tải các lớp. Thùng rác nó (thiết lập để null) sau khi thực hiện. – aishwarya

+1

@aishwarya: đó không phải là "thay thế" chút nào. Bạn không thể "thùng rác" đối tượng java. Đặt tham chiếu thành null chỉ cho phép đối tượng được thu thập rác nếu không có tham chiếu nào khác. Những gì tôi mô tả là làm thế nào để kiểm tra rằng các đối tượng * đã * thực sự thu gom rác thải. Classloader nổi tiếng là khó loại bỏ vì một tham chiếu đến một đối tượng của bất kỳ lớp được nạp nào ẩn trong một bộ sưu tập ở đâu đó là đủ để ngăn chặn trình nạp lớp và tất cả các lớp được nạp thông qua nó. –