先看几个JVM参数:
1. -Xmx 设置应用程序(不是JVM)内存可用大小 ( 如果程序要花很大内存的话,可以修改缺省配置,但是不能超过机器的内存),即最大可用Heap的大小。
2. -Xms 设置初始Heap的大小 (设置这个值启动性能会提高,也会受到机器内存的限制和最大Heap的限制)
很多情况下,一般-Xmx和-Xms 大小设置成一样大,因为不一样的话,在程序内存变化的情况下,每次垃圾回收后,都会重新分配内存。
3. -Xss 规定了每个线程堆栈的大小。一般情况下256K是足够了。影响了此进程中并发线程数大小。
2.4.1 Java堆溢出
package outofmemory; import java.util.ArrayList; import java.util.List; public class OutOfMemoryTest { static class OOMObject { } public static void main(String[] args) { List<OOMObject> list = new ArrayList<>(); int i = 0; while(true) { list.add(new OOMObject()); System.out.println(i++); } } }
2.4.2 虚拟机栈和本地方法栈溢出
package vmstacksof; public class JavaVMStackSOF { private int stackLenght = 1; public void stackLeak() { stackLenght++; stackLeak(); } public static void main(String[] args) { JavaVMStackSOF oom = new JavaVMStackSOF(); try { oom.stackLeak(); } catch (Throwable e) { System.out.println("stack length:" + oom.stackLenght); throw e; } } }
2.4.3 方法区和运行时常量池溢出
String::intern() : 是一个本地方法。new String都是在堆上创建字符串对象。当调用 intern() 方法时,编译器会将字符串添加到常量池中(stringTable维护),并返回指向该常量的引用。
String a5 = new String("A") + new String("A");//只在堆上创建对象
a5.intern();//在常量池上创建引用
String a6 = "AA";//此时不会再在常量池上创建常量AA,而是将a5的引用返回给a6
System.out.println(a5 == a6); //true
Java 8里, 字符串常量池是在堆中,而不像以前的JDK那样,在方法区。
2.4.4 本机直接内存溢出