1. Overview
1.概述
In this article, we’ll discuss the APIs provided by Java that can help us understand the several aspects related to Java heap space.
在本文中,我们将讨论Java提供的API,这些API可以帮助我们理解与Java堆空间有关的几个方面。
This can be useful in understanding the current memory status of the JVM and outsourcing it to monitoring services such as StatsD and Datadog which can then be configured to take pre-emptive action and avoid application failures.
这对于了解JVM当前的内存状态并将其外包给诸如StatsD和Datadog等监控服务非常有用,然后可以将其配置为采取抢先行动并避免应用程序出现故障。
2. Accessing Memory Parameters
2.访问内存参数
Every Java application has a single instance of java.lang.Runtime that can help us understand the current memory status of the application. The Runtime#getRuntime static method can be called to get the singleton Runtime instance.
每个Java应用程序都有一个java.lang.Runtime的单例,它可以帮助我们了解应用程序的当前内存状态。可以调用Runtime#getRuntime静态方法来获取单例Runtime实例。
2.1. Total Memory
2.1.总内存
The Runtime#getTotalMemory method returns the total heap space currently reserved by the JVM in bytes. It includes the memory reserved for current and future objects. Hence, it isn’t guaranteed to be constant during the program execution since the Java heap space can be expanded or reduced as more objects are allocated.
Runtime#getTotalMemory方法返回JVM当前保留的总堆空间,单位为字节。它包括为当前和未来对象保留的内存。因此,它不能保证在程序执行期间是恒定的,因为随着更多对象的分配,Java堆空间可能会扩大或缩小。
Also, this value isn’t necessarily what is in use or the maximum memory available.
此外,该值不一定是正在使用的或可用的最大内存。
2.2. Free Memory
2.2.免费内存
The Runtime#freeMemory method returns the free heap space available for new object allocations in bytes. It may increase as a result of a garbage collection operation where more free memory is available after.
Runtime#freeMemory方法返回可用于新对象分配的自由堆空间,单位为字节。它可能会因为垃圾收集操作而增加,因为在垃圾收集后有更多的空闲内存可用。
2.3. Maximum Memory
2.3 最大内存
The Runtime#maxMemory method returns the maximum memory that the JVM will attempt to use. Once the JVM memory usage reaches this value, then it will not allocate more memory and instead, and it will garbage collect more frequently.
Runtime#maxMemory方法返回JVM将尝试使用的最大内存。一旦JVM的内存使用量达到这个值,那么它将不会分配更多的内存,相反,它将更频繁地进行垃圾回收。
If the JVM objects still need more memory even after the garbage collector is run then the JVM may throw a java.lang.OutOfMemoryError runtime exception.
如果JVM对象在运行垃圾收集器后仍然需要更多的内存,那么JVM可能会抛出一个java.lang.OutOfMemoryError运行时异常。
3. Example
3.例子
In the below example, we initialize an ArrayList and add elements to it while keeping track of the JVM heap space using the above three methods:
在下面的例子中,我们初始化一个ArrayList,并向其添加元素,同时使用上述三种方法跟踪JVM的堆空间。
ArrayList<Integer> arrayList = new ArrayList<>();
System.out.println("i \t Free Memory \t Total Memory \t Max Memory");
for (int i = 0; i < 1000000; i++) {
arrayList.add(i);
System.out.println(i + " \t " + Runtime.getRuntime().freeMemory() +
" \t \t " + Runtime.getRuntime().totalMemory() +
" \t \t " + Runtime.getRuntime().maxMemory());
}
// ...
Output:
i Free Memory Total Memory Max Memory
0 254741016 257425408 3817865216
1 254741016 257425408 3817865216
...
1498 254741016 257425408 3817865216
1499 253398840 257425408 3817865216
1500 253398840 257425408 3817865216
...
900079 179608120 260046848 3817865216
900080 302140152 324534272 3817865216
900081 302140152 324534272 3817865216
...
- Row 1498: The Runtime#freeMemory value decreases when enough objects are allocated space in the Java heap.
- Row 900080: At this point, the JVM has more space available as GC has run hence the values of Runtime#freeMemory and Runtime#totalMemory increase.
The values shown above are expected to be different on every run of a Java application.
上面显示的值预计在Java应用程序的每次运行中都会有所不同。
4. Customizing Memory Parameters
4.定制内存参数
We can override the default values for the JVM memory parameters by setting custom values to certain flags when running our Java program in order to achieve the required memory performance:
我们可以通过在运行我们的Java程序时为某些标志设置自定义值来覆盖JVM内存参数的默认值,以便达到所需的内存性能。
- -Xms: The value assigned to -Xms flag sets the initial and minimum value of the Java heap. It can be used in cases where our application requires more memory than the default minimum when starting the JVM
- -Xmx: Likewise, we can set the maximum value for the heap space by assigning it to -Xmx flag. It can be used when we want to limit the amount of memory that our application will use, on purpose.
Please also note that the -Xms value needs to be equal or smaller than the -Xmx value.
还请注意,-Xms值需要等于或小于-Xmx值。
4.1. Usage
4.1.使用情况
java -Xms32M -Xmx64M Main
Free Memory : 31792664 bytes
Total Memory : 32505856 bytes
Max Memory : 59768832 bytes
java -Xms64M -Xmx64M Main
Free Memory : 63480640 bytes
Total Memory : 64487424 bytes
Max Memory : 64487424 bytes
java -Xms64M -Xmx32M Main
Error occurred during initialization of VM
Initial heap size set to a larger value than the maximum heap size
5. Conclusion
5.总结
In this article, we’ve seen how to retrieve JVM memory metrics via the Runtime class. These methods can be useful when investigating JVM memory leaks and other JVM memory performance-related issues.
在本文中,我们看到了如何通过Runtime类检索JVM内存指标。这些方法在调查JVM 内存泄漏和其他 JVM 内存性能相关问题时非常有用。
We’ve also shown how to assign custom values for certain flags leading to different JVM memory behavior for different scenarios.
我们还展示了如何为某些标志分配自定义值,导致不同场景下的JVM内存行为不同。