1.了解JVM
Java虚拟机是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种基于下层的操作系统和硬件平台并利用软件方法来实现的抽象的计算机,可以在上面执行java的字节码程序。
2.JVM内存结构
所有线程共享的内存数据区:方法区,堆。而虚拟机栈,本地方法栈和程序计数器都是线程私有的。
1、存放于栈中的:
a 每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(如变量的名字)。
b每个栈中的数据(基础数据类型和对象引用)都是私有的,其他栈不能访问。
c 方法的形式参数,方法调用完后从栈空间回收。
d 引用对象的地址,引用完后,栈空间地址立即被回收,堆空间等待GC。
2、存放于堆中的:
a 存储的全部是对象,每个对象包含一个与之对应的class信息
b Jvm只有一个堆区(heap)被所有线程共享,堆区中不存放基本类型和对象引用,只存放对象本身
3、存放于方法区中的:
a 存放线程所执行的字节码指令
b 跟堆一样.被所有线程共享.方法区包含:static变量
注意、Class实例在jdk1.6及之前是存放在方法区中, 在jdk1.7及之后存放在堆中。
常量池在jdk1.6及之前是存放在方法区中,在jdk1.7存放在堆中,在jdk1.8存放在元空间中。
3.JVM堆内存溢出
分析堆内存溢出的原因可能如下:
a. 使用了大量的递归或无限递归(递归中用到了大量的新建的对象)
b. 使用了大量循环或死循环(循环中用到了大量的新建的对象)
c. 类中和引用变量过多使用了Static修饰 如public staitc Student s;在类中的属性中使用 static修饰的最好只用基本类型或字符串。如public static int i = 0; //public static String str;
d. 数组,List,Map中存放的是对象的引用而不是对象,因为这些引用会让对应的对象不能被释放,会大量存储在内存中。
4.JVM栈内存溢出
a. 使用了大量的递归或无限递归
b. 使用了大量循环或死循环(如循环中不停调用方法)
c. list,map,数组等长度过大等。