Table of contents
Article directory
- Table of contents
- 01-tool overview
- 02-JConsole
- 03-Visual VM
- 04-Eclipse MAT
- Supplement 1 Talking about memory leaks again
- JProfile
- 06-Arthas
- 07-Java Mission Control
- 08-Other tools
01-tool overview
Basic information related to the performance of the target Java application can be obtained using the command-line tools or combinations from the previous chapter, but they have the following limitations:
- Method-level analysis data cannot be obtained, such as the call relationship between methods, the number of calls and call time of each method, etc. (this is critical for locating application performance bottlenecks).
- The user is required to log in to the host machine where the target Java application is located, which is not very convenient to use.
- The analysis data passes through the terminal data, and the result display is not intuitive enough.
To this end, JDK provides some memory leak analysis tools, such as jconsole, jvisualvm, etc., to assist developers in locating problems, but these tools often do not meet the needs of quick locating. So here we introduce relatively more and richer tools.
Graphical Comprehensive Diagnostic Tool
- JDK comes with tools
- jconsole: Visual monitoring tool that comes with JDK. View the running profile of Java applications, monitor heap information, permanent generation (or metaspace) usage, class loading, etc. Location: jdk\bin\jconsole.exe
- Visual VM: Visual VM is a tool that provides a visual interface for viewing detailed information about Java technology-based applications running on a Java virtual machine. Location: jdk\bin\jvisualvm.exe
- JMC: Java Mission Control, built-in Java Flight Recorder. It can collect performance data of Java Virtual Machine with extremely low performance overhead.
- third party tools
- MAT: MAT (Memory Analyzer Tool) is an Eclipse-based memory analysis tool. It is a fast, feature-rich Java heap analysis tool that can help us find memory leaks and reduce memory consumption.
- JProfiler: commercial software, need to pay. Powerful.
- Arthas: Alibaba's open source Java diagnostic space. Loved by developers.
- Btrace: Java runtime tracing tool. Information such as specified method calls, constructor calls, and system memory can be traced without downtime.
02-JConsole
Basic overview
- Starting from Java5, the Java monitoring and management console that comes with the JDK.
- It is a GUI performance monitoring tool based on JMX (Java management extensions) for monitoring memory, threads and classes in the JVM.
Official tutorial: https://docs.oracle.com/javase/7/docs/technotes/guides/management/jconsole.html
start up
- In the jdk/bin directory, start the jconsole.exe command
- Open the DOS window and directly enter jconsole
three connection methods
Local
Use JConsole to connect to a JVM running on the local system, and the user who executes the program and runs JConsole needs to be the same user. JConsole uses filesystem authorization to connect to the server via RMI that is linked to the platform's MBeans. This ability to monitor from a local connection is only available in Sun's JDK.
Remote
Connect to a JMX agent through the RMI connector using the following URL, service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi. In order to establish a connection, JConsole needs to set mx.remote.credentials in the environment variable to specify the user name and password for authorization.
Advanced
Use a special URL to connect to the JMX agent. In general, use your own custom connector instead of the connector provided by RMI to connect to the JMX agent, or an application that implements JMX and JMX Rmote using JDK1.4
main effect
1. Overview
2. Memory
3. Thread
4, Overview
03-Visual VM
The difference between jvisualvm and visual vm
There is no difference, except that visual vm is downloaded separately, and jvisualvm comes with JDK
Basic overview
- Visual VM is a powerful all-in-one visualization tool for troubleshooting and performance monitoring.
- It integrates multiple JDk command-line tools, using Visual VM can be used to display the virtual machine process and process configuration and environment information (jps, jinfo), monitor the application's CPU, GC, heap, method area and thread information (jstat , jstack), etc., even instead of JConsole
- After JDK 6 Update 7, Visual VM is released as part of JDK (VisualVM is in the JDK/bin directory)
- Alternatively, Visual VM can also be installed as a standalone software:
Home page: https://visualvm.github.io/index.html
interface:
plugin installation
A major feature of Visual VM is that it supports plug-in expansion, and plug-in installation is very convenient. We can download the plug-in file *.nbm offline, and then add the downloaded plug-in under the downloaded interface in the Plugin dialog box. Plugins can also be installed online under the Available Plugins page. (It is recommended to install: VisualGC)
Plug-in address: https://visualvm.github.io/pluginscenters.html
It can also be installed directly in Visual VM, Tools -> Plugins -> Available Plugins -> Select Plugins to Install
connection method
local connection
Monitor the CPU, class, thread, etc. of the local Java process
Remote Connection
1- Determine the ip address of the remote server
2-Add JMX (specifically monitor which Java process of the remote server through JMX technology)
3- Modify the bin/catalina.sh file to connect to the remote tomcat
4- Add jmxremote.access and jmxremote.password files in .../conf
5- Change the server address to the public network ip address
6-Set Alibaba Cloud security policy and firewall policy
7-Start tomcat, view tomcat startup log and port monitoring
8-Enter the port number, user name, and password in JMX to log in
The main function
1. Generate/read heap memory snapshot
Note: When the process stops, the snapshot will be lost. If you want to save it, you need to save the snapshot.
Save the dump file:
2. View JVM parameters and system properties
3. View the running virtual machine process
4. Generate/read thread snapshot
5. Real-time monitoring of program resources
6. Other functions
- JMX proxy connection
- Remote Environmental Monitoring
- CPU analysis and memory analysis
04-Eclipse MAT
Basic overview
MAT (Memory Analyzer Tool) tool is a powerful Java heap memory analyzer. Can be used to find memory leaks and view memory consumption.
MAT is developed based on Eclipse, not only can be used alone, but also can be embedded in Eclipse as a plug-in. It is a free performance analysis tool that is very convenient to use.
Download address: https://www.eclipse.org/mat/previousReleases.php
You can download version 1.11.0
Just make sure that JDK is installed on the machine and relevant environment variables are configured, MAT can start normally.
Get the dump file
dump file content
MAT can analyze heap dump files. When performing memory analysis, as long as the hprof file reflecting the memory image of the current device is obtained, the current memory information can be visually seen through MAT development.
Generally speaking, these memory information include:
- All object information, including object instances, member variables, basic type values stored in the stack, and reference values of other objects stored in the heap.
- All class information, including classloader, class name, parent class, static variables, etc.
- GCRoot to all reference paths of these objects
- Thread information, including the call stack of the thread and the thread local variable (TLS) of this thread
two points
Note 1: Disadvantages
MAT is not a universal tool, it cannot handle all types of heap storage files. However, the more mainstream manufacturers and formats, such as the HPROF binary heap dump files used by Sun, HP, and SAP, and the PHD heap storage files of IBM, can all be parsed very well.
Description 2:
The most attractive thing is that it can quickly generate a memory leak table for developers , which is convenient for locating and analyzing problems. Although MAT has such a powerful function, memory analysis is not as simple as one-click completion. Many memory problems still need to be discovered through experience and intuition from the information displayed to us by MAT.
Get the dump file
- via jmap
- By configuring JVM parameters
- -XX:+HeapDumpOnOutOfMemoryError: When the program OOM occurs, export the current heap snapshot of the application.
- -XX:HeapDumpPath=<filename.hprof>: You can specify the save location of the heap snapshot.
- Dump files can be exported through VisualVM
It is almost impossible to analyze it online in a production environment, and most of them use offline analysis, so using jmap+MAT tools is the most common combination.
Analyze the heap dump file
file in the upper left corner -> Open Heap Dump -> select the dump file
Leak Suspects Report
- Automatically analyze the main causes of current memory leaks through MAT
Component Report
- Component report, which analyzes objects belonging to a common root package or class loader
Re-open previouslu run reports
- Reopen previous analysis results
Main interface:
[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-WkOr8xkl-1665851221026) (C:\Users\86156\AppData\Roaming\Typora\typora-user-images\ image-20221003191740377.png)]
histogram
MAT's histogram is the same as jmap's -histo subcommand, which can display the number of instances of each class and the sum of Shallow heap of these instances. However, the histogram of MAT can also calculate retained heap, and supports sorting based on the number of instances or retained heap (the default is shallow heap).
In addition, MAT can also group the classes in the histogram by superclass, class loader or package name.
When a class is selected, the Instpector window in the upper left corner of the MAT interface will display information about the Class instance of the class, such as the class loader.
Shows the number of instances of each class and the sum of Shallow heap or Retained heap of these instances
use:
Specific content:
View GC Roots to exclude virtual/soft/weak references
thread overview
- View the Java threads in the system
- View information about local variables
View by:
Get the relationship between objects that apply to each other
-
with outgoing references to see which objects are referenced
-
Which objects are referenced by with incoming references
Shallow and Deep Heaps
shallow pile
Shallow Heap refers to the memory consumed by an object. In a 32-bit system, an object reference will occupy 4 bytes, an int type will occupy 4 bytes, a long type variable will occupy 8 bytes, and each object header will occupy 8 bytes. Depending on the format of the heap snapshot, the size of the object may be aligned to 8 bytes.
Taking String as an example, 2 int values occupy 8 bytes in total, object reference occupies 4 bytes, and object header occupies 8 bytes, totaling 20 bytes, and aligns with 8 bytes, so it occupies 24 bytes. (in jdk7)
int | hash32 | 0 |
---|---|---|
int | hash | 0 |
ref | value | “” |
These 24 bytes are the shallow heap size for String objects. It has nothing to do with the actual value of String, regardless of the length of the string, the shallow heap size is always 24 bytes.
The object header represents the object header of the object created according to the class, and the size of the object must be aligned to 8 bytes
Deep heap (retained heap)
Retained Set:
The retained set of object A refers to all object combinations (including object A itself) that can be released after object A is garbage collected, that is, the retained set of object A can be artificially accessed only directly or indirectly through object A A collection of all objects to . In layman's terms, it refers to the collection of objects held only by object A.
Deep heap (retained heap):
Deep heap refers to the sum of the shallow heap sizes of all objects in the object's retain set.
Note: The memory occupied by the shallow heap object itself does not include the size of its internal reference objects. The deep heap of an object refers to the sum of the shallow heaps of all objects that can only be accessed (directly or indirectly) through the object, that is, the real space that can be released after the object is recycled .
Supplement: the actual size of the object
Another commonly used concept is the actual size of an object. Here, the actual size of an object is defined as the shallow stack size of all objects that an object can touch, which is what we call the object size in the usual sense. Compared with deep heap, it seems that this is more intuitive and accepted in daily development, but in fact, this concept has nothing to do with garbage collection
The figure below shows a simple object reference diagram, object A references C and D, and object B references C and E. Then the shallow heap size of object A is only A itself, excluding C and D, and the time size of A is the sum of A, C, and D. However, the sum of the deep heap size of A and A and D is not within the deep heap range of object A because object C can also be accessed through object B.
practise
Look at the picture to understand Retained Size
In the figure above, GC Roots directly references two objects, A and B.
A's shallow heap: A
A's deep heap: A
B's shallow heap: B
B's deep heap: B, C, does not contain D objects, because D objects are directly referenced by GC Roots.
What if GC Roots do not refer to D objects?
B's deep heap: B, C, D, because D is not directly referenced by GC Roots
Case Study: StudentTrace
code:
/**
* -XX:+HeapDumpBeforeFullGC -XX:HeapDumpPath=d:\student.hprof
*/
public class StudentTrace {
static List<WebPage> webPages = new ArrayList<>();
public static void createWebPages() {
for (int i = 0; i < 100; i++) {
WebPage wp = new WebPage();
wp.setUrl("http://www." + Integer.toString(i) + ".com");
wp.setContent(Integer.toString(i));
webPages.add(wp);
}
}
public static void main(String[] args) {
createWebPages(); // 创建了100个网页
// 创建3个学生对象
Student st3 = new Student(3, "Tom");
Student st5 = new Student(5, "Jerry");
Student st7 = new Student(7, "Lily");
for (int i = 0; i < webPages.size(); i++) {
if (i % st3.getId() == 0) {
st3.visit(webPages.get(i));
}
if (i % st5.getId() == 0) {
st5.visit(webPages.get(i));
}
if (i % st7.getId() == 0) {
st7.visit(webPages.get(i));
}
}
webPages.clear();
System.gc();
}
}
class Student {
private int id;
private String name;
private List<WebPage> history = new ArrayList<>();
public int getId() {
return id;
}
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public void visit(WebPage wp) {
if (wp != null) {
history.add(wp);
}
}
}
class WebPage{
private String url;
private String content;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
The shallow heaps of the three objects are all 24
Analyzing a shallow heap size of 24 Source:
private int id; // 4
private String name; // 4
private List<WebPage> history = new ArrayList<>(); // 4
int occupies 4 bytes, two references 4+4 occupy 8 bytes, object header occupies 8 bytes, a total of 20 bytes are aligned to 8, and a total of 24 bytes are occupied
Analyze the source of the elementData deep heap size 1288 of "Lily"'s history (I feel that there is a problem with what I said, and I need to confirm it again)
15 webpages
The total size of the webpage is: 144 + 14 *152 = 2272 bytes -> is the actual size of elementData.
How is the deep heap size of elementData 1288 bytes calculated?
There are 7 numbers that are divisible by 7 and divisible by 3, and divisible by 7 and divisible by 5: 0, 21, 42, 63, 84, 35, and 70.
2272 - 144 (the size of index 0 is 144) - 6 * 152 = 1216 (bytes)
Calculating 1288 - 1216 is still 72 bytes short.
What are these 72 bytes?
15 elements of elementData * 4 bytes = 60 bytes
60 + 8 bytes of the object header + 4 (occupancy of the array itself) = 72 bytes
Dominator Tree
The concept of a dominator tree comes from graph theory.
MAT provides an object graph called a dominator tree. The dominance tree reflects the dominance relationship between object instances. Object A is said to dominate object B if all paths to object B pass through object A in the object reference graph . Object A is considered to be the immediate dominator of object B if object A is the closest dominator to object B. The dominator tree is based on the references between objects, and it has the following basic properties.
- The subtree of object A (the collection of all objects dominated by object A) represents the retained set of object A (retained set), that is, the deep heap.
- If object A dominates object B, then the immediate dominator of object A also dominates object B.
- The edges of the dominator tree and the edges of the object reference graph are not direct objects.
As shown in the figure below: the graph represents the object reference graph, and the right graph represents the dominator tree corresponding to the left graph. Objects A and B are directly dominated by root objects. Since the path to object C can pass through A or B, the direct dominator of object C is also the root object. Object F and object D refer to each other, because all paths to object F must pass through object D, so object D is the direct dominator of object F. All paths to object D must pass through object C. Even if the reference from object F to object D is triggered from the root node, it also passes through object C. Therefore, the direct dominator of object D is object C.
Similarly, object E dominates object G. Those who reach object H can pass through object D or object E, so neither object D nor E can dominate object H, but can reach both D and E through object C, so object C is the direct dominator of object H.
In MAT, click the object dominator tree button on the toolbar to open the object dominator tree view
view thread
There are only 8 Lily sites that can be cleared, which means that if Lily's objects are recycled, only these 8 sites can be recycled
Case: Tomcat heap overflow analysis
illustrate
Analysis process
Supplement 1 Talking about memory leaks again
Understanding and classification of memory leaks
What is a memory leak
The reachability analysis algorithm to determine whether an object is no longer used is essentially to determine whether an object is still referenced. So in this case, due to the different implementation of the code, there will be many kinds of memory leak problems (making the JVM mistakenly think that the object is still in reference and cannot be recycled, resulting in memory leaks).
Understanding of memory leaks
Strictly speaking, only when the objects are no longer used by the program, but the GC cannot reclaim them, is it called a memory leak.
But in the actual situation, in many cases, some bad timing (or negligence) will cause the life cycle of the object to become very long and even lead to OOM, which can also be called "memory leak" in a broad sense
Object X refers to object Y, and the life cycle of X is longer than that of Y;
Then when the life cycle of Y ends, X still refers to Y. At this time, the garbage collector will not recycle the object Y;
If object X still refers to objects A, B, and C with relatively short life cycles, and object A also refers to objects a, b, and c, this may cause a large number of useless objects that cannot be recycled, and then occupy memory resources, resulting in memory loss. Memory leaks until out of memory.
The relationship between memory leaks and memory overflow
(1) Memory leak (memory leak)
If the memory is used up and not released, for example, there is a total of 1024M of memory, and the allocated memory of 512M has not been reclaimed, so the usable memory is only 521M, as if part of it has been leaked;
(2) Memory overflow (out of memory)
When applying for memory, there is not enough memory available;
It can be seen that the relationship between memory leaks and memory overflow: the increase of memory leaks will eventually lead to memory overflow.
Classification of leaks
Occurs often : the code with the memory leak will be executed multiple times, and each time it is executed, a block of memory will be leaked;
**occasional:** will only happen under certain circumstances;
**One-off:**The method with a memory leak will only be executed once;
**Implicit leak:** It keeps occupying the memory and does not release it until the execution ends; strictly speaking, this is not considered a memory leak, because it is finally released.
8 Situations of Memory Leaks in Java
1. Static collection class
Static collection classes, such as HashMap, LinkedList, etc. If these containers are static, then their life cycle is the same as that of the JVM program, and the objects in the container will not be released before the program ends, causing memory leaks. Simply put, long-lived objects hold references to short-lived objects. Although short-lived objects are no longer used, they cannot be recycled because long-lived objects hold references to them.
public class MemoryLeak {
static List list = new ArrayKList();
public void oomTest() {
Object obj = new Object(); // 局部变量
list.add(obj);
}
}
2. Singleton mode
The singleton mode is similar to the reason why static collections cause memory leaks. Because of the static nature of singletons, its life cycle is as long as the life cycle of the JVM, so if the singleton object holds a reference to an external object, then the external The object will not be recycled, which will cause a memory leak.
3. The inner class holds the outer class
The inner class holds the outer class, if a method of an instance object of the outer class returns an instance object of the inner class.
This memory class object has been referenced for a long time, even if the external instance object is no longer used, but because the internal class holds the instance object of the external class, the external class object will not be garbage collected, which will also cause a memory leak.
4. Various connections, such as database connection, network connection and IO connection, etc.
In the process of operating the database, you first need to establish a connection to the database. When it is no longer in use, you need to call the close method to release the connection to the database. Only after the connection is closed, the garbage collector will reclaim the corresponding object.
Otherwise, if the Connection, Statement or ResultSet is not explicitly closed during the process of accessing the database, a large number of objects will not be reclaimed, resulting in memory leaks.
5. Unreasonable scope of variables
Generally speaking, the scope of a variable's definition is greater than its scope of use, which is likely to cause memory leaks. On the other hand, if the object is not set to null in time, it is likely to cause a memory leak.
6. Change the hash value
Change the hash value. After an object is stored in the HashSet collection, the fields in the object that participate in the calculation of the hash value cannot be modified.
Otherwise, the hash value after the object is modified is different from the hash value when it was originally stored in the HashSet collection. In this case, use the current reference of the object as a parameter in the contains method to retrieve the object in the HashSet collection in time , will also return the result that the object cannot be found, which will also result in the inability to delete the current object from the HashSet collection alone, resulting in a memory leak.
This is why String is set as an immutable type. We can safely store String in HashSet, or use String as the key value of HashMap;
7. Cache leaks
Another common source of memory leaks is caches. Once an object reference is placed in the cache, it is easy to forget. For example: when the previous project was launched for the first time, the application startup was extremely slow, because the code would load the data of a table into the cache (memory), the test environment only had a few hundred pieces of data, but the production environment had millions of data .
For this problem, WeakHashMap can be used to represent the cache. The characteristic of this kind of Map is that when the key has no other references except its own reference to the Key, the map will automatically lose this value.
8. Listeners and callbacks
A third common source of memory leaks is listeners and other callbacks, which can accumulate if clients register callbacks in your implemented API without explicit cancellation.
The best way to ensure that the callback is immediately garbage collected is to save only weak references to it, e.g. save them as keys in a WeakHashMap.
Supplement 1 Case Analysis of Memory Leaks
the case
Case code:
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
return elements[--size];
}
private void ensureCapacity() {
if (elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
analyze
The above program has no obvious errors, but this program has a memory leak. As the GC activity increases, or the memory usage continues to increase, the performance of the program will decrease. In severe cases, it can lead to memory leaks, but Such failures are relatively rare.
The main problem of the code is the pop function, which is shown below through this diagram
Assume that the stack has been growing, as shown in the figure below
When a large number of pop operations are performed, because the reference is not emptied, the gc will not release it, as shown in the figure below
As can be seen from the above figure, if the stack grows first and then shrinks, the objects popped from the stack will not be garbage collected. Even if the program no longer uses these objects in the stack, they will not be recycled. Because there are still references to these objects in the stack, commonly known as expired references , this memory leak is very hidden.
Solution
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null;
return result;
}
Once no longer used, clear these references and make the references empty
Supplement 2 Support querying object information using OQL language
SELECT clause
MAT supports a SQL-like query language OQL (Object Query Language). OQL uses SQL-like syntax to search and filter objects in the heap.
select * from java.util.ArrayList
Use the "OBJECTS" keyword to display the items in the returned result set as objects.
SELECT v.elementData FROM java.util.ArrayList v
SELECT objects v.elementData FROM java.util.ArrayList v
In the Select clause, use the "AS RETAINED SET" keyword to get a retained set of the resulting object.
SELECT AS RETAINED SET * FROM com.atguigu.mat.Student
The "DISTINCT" keyword is used to remove duplicate objects in the result set.
SELECT DISTINCT OBJECTS classof(s) FROM java.lang.String s
FROM clause
The From clause is used to specify the scope of the query, which can specify a class name, a regular expression, or an object address.
SELECT * FROM java.lang.String s
Use regular expressions to limit the search scope and output all instances of all classes under the com.atguigu package
SELECT * FROM "com\.atguigu\..*"
Search using the address of the class. The advantage of using the address of the class is that it can distinguish the same type loaded by different ClassLoaders.
select * from 0x37a0b4d
WHERE child clause
Where clause is used to specify the query condition of OQL. OQL queries will only return objects that satisfy the conditions specified in the Where clause. The format of the Where clause is very similar to traditional SQL.
Returns a char array of length greater than 10.
SELECT *FROM Ichar[] s WHERE s.@length>10
Returns all strings that contain a substring of "java", using the "LIKE" operator whose operation parameter is a regular expression.
SELECT * FROM java.lang.String s WHERE toString(s) LIKE ".*java.*"
Returns all strings whose value fields are not null, using the "=" operator.
SELECT * FROM java.lang.String s where s.value!=null
Returns all Vector objects whose array length is greater than 15 and whose deep heap is greater than 1000 bytes.
SELECT * FROM java.util.Vector v WHERE v.elementData.@length>15 AND v.@retainedHeapSize>1000
Built-in Objects and Methods
In OQL, you can access the properties of objects in the heap, and you can also access the properties of proxy objects in the heap. When accessing the properties of objects in the heap, the format is as follows, where alias is the object name:
[ . ] . .
Access the path property of the java.io.File object, and further access the value property of path:
SELECT toString(f.path.value) FROM java.io.File f
Displays the contents, objectid, and objectAddress of a String object.
SELECT s.toString(),s.@objectId, s.@objectAddress FROM java.lang.String s
Displays the length of the java.util.Vector internal array.
SELECT v.elementData.@length FROM java.util.Vector v
Display all java.util.Vector objects and their subtypes
select * from INSTANCEOF java.util.Vector
Display all java.util.Vector objects and their subtypes
select * from INSTANCEOF java.util.Vector
JProfile
Basic overview
When running Java, sometimes you want to test the memory usage during runtime. At this time, you need to use the test tool to check. There is an Eclipse Memory Analyzer tool (MAT) plug-in in eclipse that can be tested, and there is also such a plug-in in IDEA, which is JProfiler.
JProfiler is a Java application performance diagnostic tool developed by ej-technologies. Powerful, but charges.
Official download address: https://www.ej-technologies.com/download/jprofiler/files
Features:
- Easy to use, friendly interface operation (simple and powerful)
- Small impact on the application being analyzed (template provided)
- CPU, Thread, Memory analysis functions are especially powerful
- Supports analysis of jdbc, noSql, jsp, servlet, socket, etc.
- Support analysis in multiple modes (offline, online)
- Support monitoring local and remote JVM
- Cross-platform, with multiple operating system installation versions
The main function
1. Method call
Analysis of method calls can help you understand what your application is doing and find ways to improve its performance
2- Memory allocation
By analyzing objects on the heap, reference chains and garbage collection, it can help you fix memory leaks and optimize memory usage
3- Threads and locks
JProfiler provides a variety of analysis views for threads and locks to help you find multi-threading problems
4- Advanced Subsystem
Many performance problems occur at a higher semantic level. For example, for a JDBC call, you might want to find out which SQL statement executes the slowest. JProfiler supports integrated analysis of these subsystems
Installation and configuration (omitted)
Specific use
Data collection method
JProfier data collection methods are divided into two types: Sampling (sample collection) and Instrumentation (reconstruction mode)
- Instrumentation : This is the full-featured mode of JProfiler. Before the class is loaded, JProfier writes the relevant function code into the bytecode of the class to be analyzed, which has a certain impact on the running jvm.
- Advantages: powerful. In this setup, the call stack information is accurate.
- Disadvantage: If there are many classes to be analyzed, it will have a great impact on the performance of the application, and the CPU overhead may be high (depending on the control of Filter). Therefore, this mode is generally used in conjunction with Filter to analyze only specific classes or packages
- Sampling : Similar to sample statistics, the information in the method stack in each thread stack is counted every certain time (5ms).
- Advantages: The CPU overhead is very low, and the application has little impact (even if you do not configure any Filter)
- Disadvantages: Some data/features cannot be provided (eg: method call times, execution time)
Note: JProfiler itself does not indicate the data collection type, the collection type here is the collection type for method calls. Because most of the core functions of JProfiler rely on the data collected by method calls, it can be directly considered as the data collection type of JProfiler.
Remote Sensing Monitoring Telemetries
Memory View Live Memory
Live memory memory analysis: information about class/class instance. For example, the number and size of objects, the method execution stack of object creation, and the hotspots of object creation.
-
All Objects All Objects
Displays a list of all loaded classes and the number of instances allocated on the heap. Only Java 1.5 (JVMTI) will display this view.
-
Recorded Objects Recorded Objects
View allocations of objects over a specific time period and record the call stack of the allocation.
-
Allocation Access Tree Allocation Call Tree
Displays a request tree or method, class, package or J2EE component with annotated allocation information for a selected class.
-
Allocation Hot Spots
Displays a list of methods, classes, packages, or J2EE components assigned to the selected class. You can label the current value and display the difference value. For each hotspot, its trace tree can be displayed.
-
Class Tracker Class Tracker
The class trace view can contain any number of graphs showing instances and times of selected classes and packages
Analysis: what happens to objects in memory
- Frequent creation of Java objects: infinite loop, too many loops
- There are large objects: when reading a file, byte[] should be written while reading. If it is not written out for a long time, the byte[] will be too large
- There is a memory leak
Notice:
- The Size behind All Objects is the shallow heap size
Heap traversal heap walker
View Diagram Reference Relationships
Main interface
CPU view cpu views
JProfier provides different ways to record access trees to optimize performance and details. Threads or thread groups and thread states can be selected by all views. All views can be aggregated to different layers such as methods, classes, packages or J2EE components.
Access Tree Call Tree
Displays a cumulative top-down tree of all access queues recorded in the JVM. JDBC, JMS and JNDI service requests are annotated in the request tree. The request tree can be split according to the different needs of Servlet and JSP on the URL.
Hot SpotsHot Spots
Displays a list of methods that are consuming the most time. A backtracking tree can be displayed for each hotspot. The hotspot can be calculated in terms of method requests, JDBC, JMS and JNDI service requests, and in terms of URL requests.
Access graph Call Graph
Displays a graph of the access queue starting from the selected method, class, package or J2EE component.
Method Statistics Method Statistics
Displays call time details for recorded methods over time.
thread view threads
JProfiler judges its running status through the monitoring of thread history, and monitors whether there is thread blocking. It can also display the methods managed by a thread in a tree display and analyze the thread.
Thread History Thread History
Displays a timeline of activity along with thread activity and thread state.
Thread Monitor Thread Monitor
Displays a list of all active threads and their current status.
Thread Dumps Thread Dumps
Show stack traces for all threads
Thread analysis is primarily concerned with three areas:
- The maximum number of threads for the web container. For example: Tomcat's thread capacity should be slightly greater than the maximum number of concurrency.
- thread blocking
- thread deadlock
Monitors & locks Monitors & locks
All threads hold locks and lock information
Watch the JVM's internal threads and view the status:
- Deadlock detection graph Current Locking Graph: Displays the current deadlock graph in the JVM
- Currently used detectors Current Monitors: Displays currently used detectors and includes their associated threads.
- Locking History Graph Locking History Graph: Displays the locking history recorded in the JVM.
- Historical monitoring records Monitor History: Displays the historical records of major waiting events and blocking events.
- Monitor usage statistics Monitor Usage Statistics: Displays statistical monitoring data of group monitoring, threads and monitoring classes.
case analysis
Case 1
public class JProfilerTest {
public static void main(String[] args) {
while (true){
ArrayList list = new ArrayList();
for (int i = 0; i < 500; i++) {
Data data = new Data();
list.add(data);
}
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Data{
private int size = 10;
private byte[] buffer = new byte[1024 * 1024];//1mb
private String info = "hello,atguigu";
}
Case 2
public class MemoryLeak {
public static void main(String[] args) {
while (true) {
ArrayList beanList = new ArrayList();
for (int i = 0; i < 500; i++) {
Bean data = new Bean();
data.list.add(new byte[1024 * 10]);//10kb
beanList.add(data);
}
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Bean {
int size = 10;
String info = "hello,atguigu";
static ArrayList list = new ArrayList();
}
Mark the running instance to determine what object caused it
found the reason
Use images to show
You can see that the byte array is finally referenced by the Bean
06-Arthas
Basic overview
background
These two tools, Jvisualvm and Jprofile, are also relatively well-known in the industry. Their advantage is that they can see the performance data of each dimension on the graphical interface, and use them to conduct comprehensive analysis based on these data, and then determine where performance problems occur.
But these two tools also have shortcomings, and both of them must configure relevant monitoring parameters during the server-side project process. The tool then connects remotely to the project process to obtain relevant data. This will bring some inconvenience, for example, the network of the online environment is isolated, and the local monitoring tools cannot connect to the online environment at all. And commercial tools like JProfiler require payment.
So is there a tool that does not require remote connections, does not require configuration of monitoring parameters, and also provides rich performance monitoring data?
The answer is Alibaba's open source performance analysis magic Arthas (Alsace)
overview
Artha (Alsace) is Alibaba's open source Java diagnostic tool, which is very popular among developers. Troubleshoot problems online without restarting; dynamically track Java code: monitor JVM status in real time.
Arthas
Supports JDK 6+, supports Linux/Mac/Windows, adopts command line interactive mode, and provides rich Tab
auto- completion functions to further facilitate problem location and diagnosis.
When you encounter a similar problem and feel helpless, Arthas can help you:
- Which jar package is this class loaded from? Why are various types of related Exception reported?
- Why is the code I changed not executed? Could it be that I didn't commit? Branching wrong?
- If you encounter a problem and cannot debug online, can you only republish it by adding a log?
- I encountered a problem with the data processing of a certain user online, but it also cannot be debugged online, and cannot be reproduced offline!
- Is there a global view into the health of the system?
- Is there any way to monitor the real-time running status of the JVM?
- How to quickly locate application hotspots and generate flame graphs?
- How to find an instance of a class directly from within the JVM?
Official address: https://arthas.aliyun.com/
Installation and use
start command
java -jar arthas-boot.jar
Because there are Chinese documents, the main learning is to refer to the official documents.
07-Java Mission Control
history
Before Oracle acquired Sun, Oracle's JRockit virtual machine provided a virtual machine diagnostic tool called JRockit Mission Control.
After Oracle acquired sun, Oracle owned both Hotspot and JRockit virtual machines. According to Oracle's strategy for Java, in the future development, the excellent features of JRokit will be ported to Hotspot. One of the important improvements is the addition of JRockit support to Sun's JDK.
After Oracle JDK 7u40, the tool Mission Control has been bundled in Oracle JDK.
Since Java11, the JFR introduced in this section has been open sourced. But in the previous Java version, JFR belonged to the Commercial Feature and was enabled through the Java virtual machine parameter -XX:+UnlockCommercialFeatures.
Java Mission Control (JMC for short), a powerful tool officially provided by Java, is a tool suite for managing, monitoring, profiling and troubleshooting Java applications. It includes a GUI client and many plug-ins used to collect Java virtual machine performance data, such as JMX Console (which can access MXBeans used to store virtual machine data in the system) and the efficient profiling tool Java Flight Recorder built into the virtual machine ( JFR).
Another advantage of JMC is that it uses sampling instead of traditional code implantation technology, which has very little impact on application performance, and it is completely possible to run JMC for stress testing (the only impact may be that there are too many full gcs).
Official address: https://github.com/JDKMissionControl/jmc
start up
overview
Java Mission Control (JMC for short), a powerful tool officially provided by Java. It is a tool for managing, monitoring, profiling and troubleshooting Java applications.
It includes a GUI client, and many plug-ins for collecting Java virtual machine performance data, such as JMX Console (which can access MXBeans used to store the running data of each subsystem of the virtual machine), and the built-in efficient profiling tool Java Filght Recorder (JFR).
Another advantage of JMC is that it adopts sampling instead of traditional code implantation technology, which has very little impact on application performance. After completion, JMC can be turned on for stress testing (the only impact may be that there are too many full gcs).
Function: Real-time monitoring of the status of JVM runtime
add another item
Java Flight Recorder
event type
When started, JFR will record a series of events that occur during the run. These include events at the Java level. Such as thread events, lock time, and time inside the Java virtual machine, such as creating new objects, garbage collection, and just-in-time compilation time.
Divided according to the timing and duration of occurrence, there are four types of JFR time, and they are as follows:
- Instantaneous events (Instant Event), users are concerned about whether they occur or not, such as exceptions and thread start events.
- Continuous events (Duration Event), users care about their duration, such as garbage collection events.
- A Timed Event is a persistent event whose duration exceeds a specified threshold.
- Sample Event is a periodic sampling event.
One of the common examples of sampling events is method sampling (Method Sampling), which counts the stack traces of each thread at regular intervals. If there is a recurring method among these sampled traces, then we can infer that method is the hotspot method.
start up
Method 1: Use -XX:StartFlightRecording= parameter
Method 2: Use the JFR.* subcommand of jcmd
Method 3: JMC's JFR plug-in
Java Flight Recorder Sampling Analysis
1. General Information
2. Memory
3. Code
4. Thread
5、I/O
6. System
7. Events:
08-Other tools
Flame Graphs flame graph
In the scenario of pursuing mechanism performance, to understand what the CPU is doing during the running of your program, the flame graph is a very intuitive tool to display the event distribution of the CPU during the entire life cycle of the program.
The flame graph should not be unfamiliar to modern programmers. This tool can very intuitively show the CPU consumption bottleneck in the call stack.
Most of the online explanations about java flame graphs come from Brendan Gregg's blog: https://brendangregg.com/flamegraphs.html
The flame graph simply measures the time index through the width of the bar on the x-axis, and the y-axis represents the level of the thread stack.
Tprofiler (no one has maintained it for a long time)
- case:
Using the tools provided by the JDK itself for JVM tuning can increase the TPS from 2.5 to 20 (a 7-fold increase) and accurately locate system bottlenecks.
System bottlenecks include: there are not too many static objects in the application, a large number of business threads frequently create some temporary objects with a long life cycle, and there are problems in the code.
So, how to accurately locate these performance codes in the massive business codes? Here, Ali open source tool TProfiler is used to locate these performance codes, which successfully solved the performance bottleneck of too frequent GC, and finally increased the TPS by 4 more on the basis of the last optimization, that is, to 100.
- TProfiler configuration deployment, remote operation, and log reading are not too complicated, and the operation is still very simple. But it can indeed have a sharp and immediate effect, helping us solve the performance bottleneck of too frequent GC.
- The most important feature of TProfiler is the ability to count the top methods of the JVM within a specified period of time. These top methods are most likely the culprits that cause JVM performance bottlenecks. This is not available in most other JVM tuning tools, including JRockit Mission Control.
- Download address: https://github.com/alibaba/TProfiler
Btrace
Java runtime tracing tool. It is a secure dynamic tracking tool for the Java platform. Can be used to dynamically track a running Java program.
BTrace dynamically adjusts the target application's classes to inject trace code ("bytecode trace").