2015-06-02 21 views
5

Gần đây tôi đã có thể nhận được địa chỉ của đối tượng bằng cách sử dụng lớp sun.misc.Unsafe.Làm thế nào để tìm ra nơi chính xác gen trẻ/cũ nằm trong bộ nhớ?

Và bây giờ tôi đang cố gắng tìm một thế hệ thực tế có lập trình mà đối tượng của tôi nằm ở đó. Đối với điều này tôi muốn biết điểm bắt đầu và kết thúc của mỗi thế hệ. Nếu Java (Oracle JVM) cung cấp bất kỳ công cụ nào để giải quyết vấn đề này? Tôi tin rằng không, vì thậm chí các GC khác nhau yêu cầu cấu trúc bộ nhớ khác nhau (ví dụ G1), và điều này làm cho công việc thú vị hơn nữa :)

Điều tôi muốn biết ở đây chỉ là một vài con số đại diện cho biên giới của các thế hệ trong bộ nhớ , như thế này:

young gen: start point - 8501702198 
       end point - 9601256348 

Rất thích nghe thậm chí những ý tưởng điên rồ nhất của bạn về một ma thuật đen cho phép để xác định nơi vùng thế hệ khác nhau được đặt trong bộ nhớ.

+2

Thậm chí nếu bạn có thể nhận thông tin đó, nó sẽ là cũ khi bạn nhận được nó vì GC có thể chạy trong thời gian chờ đợi và di chuyển ranh giới thế hệ (G1 tái chỉ định khu vực, các GC khác có thể di chuyển trẻ/ranh giới cũ). Tương tự như vậy, bất kỳ số học con trỏ nào bạn làm sẽ chỉ là lỗi thời do các đối tượng bị di chuyển. – the8472

+2

Tôi đề nghị bạn có một cái nhìn tại https://github.com/serkan-ozal/jillegal Đây có thể là thư viện tốt nhất để đào xung quanh trong nội bộ của JVM bằng cách sử dụng không an toàn. Thay vì nhìn vào địa chỉ bạn có thể nhận được số lượng GC mà đối tượng đã sống sót. Điều này có thể cho bạn biết vùng đó nằm ở đâu. –

Trả lời

2

Tôi không biết làm thế nào để có được chính xác biên giới của thế hệ trẻ và già (thậm chí không chắc chắn nó có thể). Trong trường hợp G1 nó trở nên phức tạp hơn vì nó được phép có nhiều hơn một khu vực thế hệ cũ do cấu trúc heap đặc biệt của G1.

Nhưng bạn có thể sử dụng phương pháp phỏng đoán khôn lanh để xác định xem đối tượng có ở thế hệ cũ hay không mà không biết biên giới của thế hệ.

Hãy sử dụng một số ma thuật đen kiến ​​thức bí mật về hotspot internals: mọi đối tượng chứa tiêu đề với tất cả các thông tin cần thiết về khóa, hashcode danh tính, và quan trọng nhất, tuổi. tuổi Extracting sẽ trông như thế này:

return unsafe.getByte(targetObject, 0L) & 0x78; 

nơi 0x78 tương ứng mặt nạ trong phần đầu đối tượng so với tuổi của nó (bit từ 4 đến 7 bao gồm).

Lấy MaxTenuringThreshold tham số qua Management API:

MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 
HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
      server, 
      "com.sun.management:type=HotSpotDiagnostic", 
      HotSpotDiagnosticMXBean.class); 
int threshold = Integer.valueOf(bean.getVMOption("MaxTenuringThreshold").getValue()); 

Bây giờ bạn biết tuổi của đối tượng và tenuring ngưỡng của ứng dụng của bạn, vì vậy bạn có thể giả định rằng nếu tuổi lớn hơn ngưỡng, đó là trong thế hệ cũ.

CẢNH BÁO: Đó là phỏng đoán dựa trên kiến ​​thức bí mật và bí mật.

  1. Nó sẽ không làm việc, nếu ai đó sẽ đồng bộ hóa trên đối tượng mục tiêu trong khi bạn đang đọc nó tuổi, bởi vì VM sẽ di chuyển tiêu đề để ngăn xếp và thay thế tiêu đề với con trỏ để ngăn xếp
  2. Nó sẽ không làm việc với XX:+UseAdaptiveSizePolicy, vì vậy bạn nên vô hiệu hóa nó một cách rõ ràng.
  3. Một số đối tượng có thể được phân bổ thẳng vào thế hệ cũ (ví dụ bởi vì kích thước của nó)
  4. Type I error dễ
  5. Cách tiếp cận này là bất hợp pháp, không an toàn và có thể là không chính xác và JVM phụ thuộc
4

này có thể với HotSpot JVM dù bằng cách nào đó phức tạp.

Ý tưởng chính là sử dụng VMStructs - thông tin về HotSpot nội bộ constantstypes được nhúng ngay vào thư viện được chia sẻ của JVM.

Ví dụ: ParallelScavengeHeap::_young_gen Biến toàn cầu của máy ảo chứa con trỏ tới cấu trúc PSYoungGen có thành viên _virtual_space có đường biên của thế hệ trẻ của bộ thu song song. Tương tự, GenCollectedHeap::_gch điểm toàn cầu với cấu trúc mô tả thế hệ bộ thu CMS.

Tôi đã thực hiện proof-of-concept project để chứng minh việc sử dụng VMStructs. Đó là Java thuần túy, không yêu cầu thêm thư viện nào, nhưng nó phụ thuộc rất nhiều vào nội bộ JDK không có giấy tờ và có thể không hoạt động trên tất cả các phiên bản Java. Tôi đã thử nghiệm điều này trên JDK 8u40 và JDK 7u80 trên Windows và Linux.

  • JVM.java - mã để đọc VMStructs;
  • HeapInfo.java - chương trình mẫu để lấy địa chỉ của các thế hệ Heap.
+0

Có thể lấy Vũ trụ :: hằng số theo cách này không? – qwwdfsad

+1

@qwwdfsad Có, mọi thứ được liệt kê [ở đây] (https://gist.github.com/apangin/e182230a048b14468b7b) – apangin

+0

Cảm ơn! Đó là những gì tôi đang tìm kiếm – qwwdfsad

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