How to find out where exact young/old gen is located in memory?

℡╲_俬逩灬. 提交于 2019-12-18 13:37:11

问题


Recently I was able to get an object's address using sun.misc.Unsafe class.

And now I am trying to find programmatically an actual generation where my object is located. For this I want to know the starting and ending points of each generation. If Java (Oracle JVM) provides any tools to resolve this issue? I believe not, since even different GCs require different memory structures (e.g. G1), and this makes the task even more interesting :)

What I want to know here is just a couple of numbers representing the borders of generations in memory, like this:

   young gen: start point - 8501702198   
              end point   - 9601256348

Would love to hear even your craziest ideas about a black magic that allows to determine where different generation areas are placed in memory.


回答1:


This is possible with HotSpot JVM though somehow complicated.

The key idea is to use VMStructs - the information about HotSpot internal constants and types embedded right into JVM shared library.

For example, ParallelScavengeHeap::_young_gen VM global variable contains the pointer to PSYoungGen structure that has _virtual_space member with the boundaries of Parallel collector's young generation. Similarly, GenCollectedHeap::_gch global points to the structure describing CMS collector generations.

I've made a proof-of-concept project to demonstrate the usage of VMStructs. It is pure Java, no extra libraries required, but it deeply relies on the undocumented JDK internals and may not work on all Java versions. I've tested this on JDK 8u40 and JDK 7u80 on Windows and Linux.

  • JVM.java - the code for reading VMStructs;
  • HeapInfo.java - the sample program to get addresses of Heap generations.



回答2:


I don't know how to get exactly the borders of young and old generations (not even sure it's possible). In case of G1 it became even more complicated because it's allowed to have more than one old generation region due to unusual heap structure of G1.

But you can use tricky heuristic to determine whether object is in old generation or not without knowing borders of generations.

Let's use some black magic secret knowledge about hotspot internals: every object contains header with all necessary information about locking, identity hashcode, and most important, age. Extracting age will look like this:

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

where 0x78 is corresponding mask in object header for its age (bits from 4th to 7th inclusive).

Obtain MaxTenuringThreshold parameter via 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());

Now you know object's age and tenuring threshold of your application, so you can assume that if age is greater than threshold, it's in old generation.

WARNING: It's heuristic based on magic and secret knowledge.

  1. It will not work, if someone will synchronize on target object while you are reading it's age, because VM will move header to stack and replace header with pointer to stack
  2. It will not work with XX:+UseAdaptiveSizePolicy, so you should explicitly disable it.
  3. Some object can be allocated straight in old generation (e.g. because of it's size)
  4. Type I error prone
  5. This approach is illegal, unsafe and might be incorrect and jvm dependent


来源:https://stackoverflow.com/questions/30599986/how-to-find-out-where-exact-young-old-gen-is-located-in-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!