For an experienced Java programmer, it is useful to know how much memory one or more Java objects are consuming. You may have heard of the world we live in, storage capacity will no longer be a problem, which may be right for your text editor (however, open a document that contains a lot of pictures and charts, and see how much memory your editor consumes), It may also be right for a dedicated server software (at least until your business grows large enough or before the same server runs other software), it may also be true for cloud-based software, if you are rich enough to spend enough money to buy top-tier server hardware.
However, the reality is that if your software is subject to memory limitations, what needs to be done is to spend money to optimize it instead of trying to get better hardware (original: In the true world your software would once reach a point where it makes Sens E to spend-optimization rather than trying to obtain a even better) (currently you can get the best commercial server is 64G memory), at this time you have to Analyze your application to find out which data structure consumes most of the memory. The best tool for this analysis is a good performance analysis tool, but you can use the inexpensive way to analyze the objects in your code at the beginning. This article describes the use of Classintrospector classes based on Oracle JDK to analyze your application memory consumption.
I have been in the article string wrapper part 1th: Converting characters to bytes refers to the Java object memory structure, for example, I have written that a 28-character string would occupy 104 bytes before java1.7.0_06, in fact, when I was writing this article, The results of my calculations are verified by our own Performance analyzer. We now use the special class Sun.misc.Unsafe in the Oracle JDK to implement a Java object introspection (Introspector) through pure java.
We use the following methods of Sun.misc.Unsafe:
Gets the offset of the non-static method of the byte object (get offset of a non-static field in the bytes public
native Long Objectfieldoffset (java.l Ang.reflect.Field Field);
Gets the offset of the first element within the array (get offset of a, a, in the array) public
native int arraybaseoffset (Java.lang.Class aclass) ;
Gets the size of one element in the array (getting size of an element in the array) public
native int Arrayindexscale (Java.lang.Class aclass);
Gets the address value (get addressing size for your JVM) in the JVM public
native int addresssize ();
There are two additional introspection methods in Sun.misc.Unsafe: Staticfieldbase and Staticfieldoffset, but not used in this article. These two methods are useful for unsafe read-write static methods.
How do we find the memory layout of an object?
1, loop on the analysis class and the parent class call Class.getdeclaredfields, get all the objects of the fields, including its parent class;
2. For non-static fields (via Field.getmodifiers () & Modifiers.static determines the static field by using Unsafe.objectfieldoffset to get the offset of a field in its parent class and the shallow of the field (note: Shallow refers to the size of the current object itself) Size: default value of the underlying type and 4 or 8 words Section object references (see below for more);
3, in the array, call Unsafe.arraybaseoffset and Unsafe.arrayindexscale, the entire shallow size will be the current array offset + the size of each array * array length (original: Offset + Scale * ARRAY.GETLENGTH (array), of course, also includes the size of the reference to the array itself (see above);
4, do not forget the object map of the circular reference, it is necessary to the previous analysis of the object to track records (for these cases, recommend the use of Identityhashmap)
The Java object reference size is a very uncertain value (original: Java object reference size is quite a virtual value), which may be 4 bytes or 8 bytes, depending on your JVM settings and how much memory is given to the JVM, For a heap above 32G, it is always 8 bytes, but for a smaller heap it is 4 bytes unless you turn off setting-xx:-usecompressedoops in the JVM settings (I'm not sure which version of the JVM was added to or turned on by default). The result is that the safe way to get the size of a reference is to find the size of an element in the object[] array: Unsafe.arrayindexscale (Object[].class), Unsafe.addresssize is not practical.
A small note of 4-byte references for the following heap memory in 32G. A normal 4-byte pointer can be positioned to any address in the 4G address space. If we assume that all allocated objects will be aligned through a 8-byte boundary, we will no longer need a minimum of 3 bits in our 32-bit pointer (these bits will always be equal to zero). This means that we can store 35-bit addresses in 32-bit locations. (This section is attached with the following text:
A Small Implementation 4 byte references on under 32G heaps. A Normal 4 byte pointer could addressany byte in 4G address spaces. If we would assume that all allocated objects would be aligned by 8 bytes boundary, we won ' t need 3 lowest bits in our BI T pointers anymore (these bits would always be equal to zeroes). This means so we can store bit addresses in bit value:)
32_bit_reference = (int) (Actual_64_bit_pointer >> 3)
35-bit allows addressing the 32-bit *8=4g*8=32g address space.
Some of the other interesting things that you find when you write this tool
1, to play the contents of the group, you must use Arrays.tostring (including basic types and object array);
2. You have to be careful-introspective methods (introspection method) only accept objects as field values, so you may end up in an infinite loop: an integral type is packaged into integers to pass to the introspective method. Inside you'll find a integer.value field and try to introspect again--look, you're back where you started!
3. To Introspect (introspect) all Non-null values in the object array-this is just the external level of the indirect object graph (original: This is just a extra level of indirection in "object graph")
How do I use the Classintrospector class? Just instantiate it and invoke its instance introspection (Introspect) method in any of your objects, and it returns a Objectinfo object that is related to your root object, which will point to all its subkeys, I think it might be enough to print the results of their toString method and/or invoke the Objectinfo.getdeepsize method (original: I thinking it May is sufficient to print its ToString methods Resul T and/or to called Objectinfo.getdeepsize method), which will return the total memory consumption of all your objects via reference to your "root" object.
Classintrospector is not thread-safe, but you can invoke the introspection (Introspect) method as many times as you want in the same thread.