How to find out where the exact young / old gene is?

I recently managed to get the address of an object using the class sun.misc.Unsafe.

And now I'm trying to find the software real generation, where is my object. For this, I want to know the starting and ending points of each generation. Should Java (Oracle JVM) provide any tools to solve this problem? I believe not, since even different GCs require different memory structures (for example, G1), and this makes the task even more interesting :)

What I want to know here is just a couple of numbers representing the boundaries of generations in memory, for example:

young gen: start point - 8501702198 end point - 9601256348 

I would like to hear even the craziest ideas about black magic, which allow us to determine where in the memory different zones of generation are located.

+5
source share
2 answers

This is possible with the JVM HotSpot, although somehow complicated.

The main idea is to use VMStructs - information about the internal HotSpot constants and types is built directly into the general JVM library.

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

I did a concept proof project to demonstrate the use of VMStructs. This is pure Java, no additional libraries are required, but it is deeply dependent on the undocumented internal components of the JDK and may not work on all versions of Java. I tested this on the JDK 8u40 and the JDK 7u80 on Windows and Linux.

  • JVM.java - code for reading VMStructs;
  • HeapInfo.java is an example program for getting addresses of heap generations.
+4
source

I do not know how to get exactly the boundaries of the young and old generations (I'm not even sure that this is possible). In the case of G1, this became even more complicated because it allowed more than one region of the old generation to be available due to the unusual structure of the G1 heap.

But you can use complex heuristics to determine if an object is in the old generation or not, not knowing the boundaries of generations.

Let us use the secret knowledge of black magic about the inside of hotspot : each object contains a heading with all the necessary information about the lock, the hashcode identifier and the most important, age . Extracting age will look like this:

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

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

Get the MaxTenuringThreshold control API parameter:

 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 the age and life threshold of your application, so you can assume that if age is greater than the threshold, it is in the old generation.

Note: This is a heuristic based on magic and secret knowledge.

  • This will not work if someone synchronizes with the target while you read it, because the VM will move the title onto the stack and replace the title with a pointer to the stack
  • It will not work with XX:+UseAdaptiveSizePolicy , so you must explicitly disable it.
  • Some object can be selected directly in the old generation (for example, because of its size).
  • Type I error .
  • This approach is illegal, unsafe and may be incorrect and jvm dependent
+2
source

All Articles