1. Overview
1.概述
Simply put, the JVM takes care of freeing up memory when objects are no longer being used. This process is called Garbage Collection (GC).
简单地说,当对象不再被使用时,JVM会负责释放内存。这个过程被称为垃圾收集(GC)。
The GC Overhead Limit Exceeded error is one from the java.lang.OutOfMemoryError family, and it’s an indication of a resource (memory) exhaustion.
GC Overhead Limit Exceeded错误是来自java.lang.OutOfMemoryError家族的一个错误,它是资源(内存)耗尽的一个指示。
In this quick tutorial, we’ll look at what causes the java.lang.OutOfMemoryError: GC Overhead Limit Exceeded error and how it can be solved.
在这个快速教程中,我们将了解导致java.lang.OutOfMemoryError:GC Overhead Limit Exceeded错误以及如何解决这个问题。
2. GC Overhead Limit Exceeded Error
2.超过GC开销限制的错误
OutOfMemoryError is a subclass of java.lang.VirtualMachineError. It’s thrown by the JVM when it encounters a problem related to utilizing resources. More specifically, the error occurs when the JVM spent too much time performing Garbage Collection and was only able to reclaim very little heap space.
OutOfMemoryError是java.lang.VirtualMachineError的一个子类。当JVM遇到与利用资源有关的问题时,它就会被抛出。更具体地说,当JVM花了太多的时间进行垃圾回收时,只能回收很少的堆空间时,就会发生这个错误。
According to Java docs, by default, the JVM is configured to throw this error if the Java process spends more than 98% of its time doing GC and when only less than 2% of the heap is recovered in each run. In other words, this means that our application has exhausted nearly all the available memory, and the Garbage Collector has spent too much time trying to clean it and failed repeatedly.
根据Java文档,默认情况下,如果Java进程花了98%以上的时间做GC,而每次运行中只恢复了不到2%的堆,JVM就会被配置为抛出这个错误。换句话说,这意味着我们的应用程序已经用尽了几乎所有的可用内存,而垃圾收集器花了太多的时间试图清理它,并屡屡失败。
In this situation, users experience extreme slowness of the application. Certain operations, which usually complete in milliseconds, take more time to complete. This is because the CPU is using its entire capacity for Garbage Collection and therefore cannot perform any other tasks.
在这种情况下,用户体验到应用程序的极端缓慢。某些通常在几毫秒内完成的操作,需要更多时间才能完成。这是因为CPU正在将其全部容量用于垃圾收集,因此无法执行任何其他任务。
3. Error in Action
3.行动中的错误
Let’s look at a piece of code that throws java.lang.OutOfMemoryError: GC Overhead Limit Exceeded.
让我们看看一段抛出java.lang.OutOfMemoryError的代码。GC Overhead Limit Exceeded。
We can achieve that, for example, by adding key-value pairs in an unterminated loop:
例如,我们可以通过在未结束的循环中添加键值对来实现这一点。
public class OutOfMemoryGCLimitExceed {
public static void addRandomDataToMap() {
Map<Integer, String> dataMap = new HashMap<>();
Random r = new Random();
while (true) {
dataMap.put(r.nextInt(), String.valueOf(r.nextInt()));
}
}
}
When this method is invoked, with the JVM arguments as -Xmx100m -XX:+UseParallelGC (Java heap size is set to 100 MB and the GC Algorithm is ParallelGC), we get a java.lang.OutOfMemoryError: GC Overhead Limit Exceeded error. To get a better understanding of different Garbage Collection Algorithms, check out Oracle’s Java Garbage Collection Basics tutorial.
当这个方法被调用时,JVM参数为-Xmx100m -XX:+UseParallelGC (Java堆大小被设置为100MB,GC算法为ParallelGC),我们得到一个java.lang.OutOfMemoryError。GC Overhead Limit Exceeded错误。要更好地了解不同的垃圾收集算法,请查看Oracle的Java垃圾收集基础知识教程。
We’ll get a java.lang.OutOfMemoryError: GC Overhead Limit Exceeded error very quickly by running the following command from the root of the project:
我们会得到一个java.lang.OutOfMemoryError。从项目的根部运行以下命令,很快就会得到java.lang.OutOfMemoryError: GC Overhead Limit Exceeded 的错误。
mvn exec:exec
It should also be noted that in some situations we might encounter a heap space error before encountering the GC Overhead Limit Exceeded error.
还应该注意的是,在某些情况下,我们可能会在遇到GC Overhead Limit Exceeded错误之前遇到堆空间错误。
4. Solving GC Overhead Limit Exceeded Error
4.解决超过GC开销限制的错误
The ideal solution is to find the underlying problem with the application by examining the code for any memory leaks.
理想的解决方案是通过检查代码中的任何内存泄漏,找到应用程序的根本问题。
These questions need to be addressed:
这些问题需要得到解决。
- What are the objects in the application that occupy large portions of the heap?
- In which parts of the source code are these objects being allocated?
We can also use automated graphical tools such as JConsole, which helps to detect performance problems in the code including java.lang.OutOfMemoryErrors.
我们还可以使用自动化的图形工具,如JConsole,它有助于检测代码中的性能问题,包括java.lang.OutOfMemoryErrors。
The last resort would be to increase the heap size by altering the JVM launch configuration.
最后的办法是通过改变JVM启动配置来增加堆的大小。
For example, this gives 1 GB heap space for the Java application:
例如,这为Java应用程序提供了1GB的堆空间。
java -Xmx1024m com.xyz.TheClassName
However, this will not solve the problem if there are memory leaks in the actual application code. Instead, we will just postpone the error. So, it is more advisable to thoroughly reassess the memory usage of the application.
然而,如果在实际的应用程序代码中存在内存泄漏,这将不能解决问题。相反,我们将只是推迟错误的发生。因此,更明智的做法是彻底重新评估应用程序的内存使用情况。
5. Conclusion
5.结论
In this article, we examined the java.lang.OutOfMemoryError: GC Overhead Limit Exceeded and the reasons behind it.
在这篇文章中,我们研究了java.lang.OutOfMemoryError:GC Overhead Limit Exceeded以及其背后的原因。
As always, the source code related to this article can be found over on GitHub.
像往常一样,与本文有关的源代码可以在GitHub上找到。