一、堆参数调优入门
(1)
-Xms:JVM Heap 初始化大小
-Xmx:JVM Heap 最大化大小
-Xmn:JVM Heap 新生区的大小
(2)java8
在java8中,永久代已经被移除,被一个称为元空间的区域所取代。元空间的本质和永久代类似。
元空间与永久代之间最大的区别在于:
永久代使用的JVM的堆内存,但是java8以后的元空间并不在虚拟机中而是使用本机物理内存。
因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入native memory,字符串常量池和类的静态变量放入java堆中,这样可以加载多少类的元数据就不在由MaxPermSize控制,而由系统的实际可以空间来控制。
(3)堆内存调优简介
1.
我们可以用程序来证明:
我们可以看到笔者的内存为15.9G,那么理论上-Xms=248.4M,-Xmx=3975M
public static void main(String[] args) {
long maxMemory = Runtime.getRuntime().maxMemory() ;//返回 Java 虚拟机试图使用的最大内存量。
long totalMemory = Runtime.getRuntime().totalMemory() ;//返回 Java 虚拟机中的内存总量。
System.out.println("MAX_MEMORY = " + maxMemory + "(字节)、" + (maxMemory / (double)1024 / 1024) + "MB");
System.out.println("TOTAL_MEMORY = " + totalMemory + "(字节)、" + (totalMemory / (double)1024 / 1024) + "MB");
}
可以看到结果和理论值相差无几。
2.我们可以在Intellij idea中调正堆的初始化大小和最大大小,并打印GC详情。
我们在运行程序,就会出现以下结果
我们可以从上面的结果可以证明堆物理上由新生区和老年区组成。
(4)java.lang.OutOfMemoryError异常
public class OutOfMemory {
public static void main(String[] args) {
String str = "Hello World!" ;
while(true)
{
str += str + new Random().nextInt(88888888) + new Random().nextInt(999999999) ;
}
}
}
而上面的打印的信息是什么意思呢?请看下图
[GC (Allocation Failure) [PSYoungGen: 2044K->504K(2560K)] 2044K->700K(9728K), 0.0011234 secs]
[Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure)[GC类型:YoungGC前新生代内存占用->YoungGC后新生代内存占用(新生代总共大小)]YoungGC前JVM堆内存占用->YoungGC后JVM堆内存占用(JVM堆总大小),YoungGC耗时][YoungGC用户耗时 YoungGC系统耗时 YoungGC实际耗时]
[Full GC (Ergonomics) [PSYoungGen: 472K->0K(1536K)] [ParOldGen: 5859K->1672K(7168K)] 6331K->1672K(8704K), [Metaspace: 3453K->3453K(1056768K)], 0.0059530 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full Gc(System)[Young区:GC前Young区内存占用->GC后Young区内存占用(Young区总大小)][Old区:GC前Old区内存占用->GC后Old区内存占用(Old区总大小)] GC前堆内存占用->GC后堆内存占用(JVM堆内存总大小),[元空间:GC前所占内存->GC后所占内存(元空间总大小)],GC耗时]
[GC用户耗时 GC系统耗时 GC实际耗时]