1.string.intern
从常量池返回字符串常量或将字符串常量放入常量池中
2.JVM内存分区
虚拟机栈(栈大小/栈深度)、程序计数器、方法区、堆(分代)
3.编写内存泄露代码
vm options:-Xms10M -Xmx10M -Xmn5M -verbose:gc -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m -XX:+HeapDumpOnOutOfMemoryError
public class TestLeak {
private static final int _1MB = 2*1024*1024;
public static void main(String[] args) {
System.out.println("start");
int i =0;
while (true) {
System.out.println(i++);
ObjectA objectA = new ObjectA();
ObjectB objectB = new ObjectB();
objectA.objectB = objectB;
objectB.objectA = objectA;
}
}
static class ObjectA {
ObjectB objectB;
byte[] allocation1 = new byte[2 * _1MB];
}
static class ObjectB {
ObjectA objectA;
byte[] allocation1 = new byte[2 * _1MB];
}
}
4.编写代码测试Metaspace和永久代溢出验证
永久代是对虚拟机规范方法区的实现,只是作为堆的逻辑部分,目的是为了避免单独编写内存管理代码
jdk 1.6中需要设置permspace maxpermspace来限制永久代(或方法区)内存大小
jdk 1.7中开始将字符串常量迁移出永久代(或方法区),具体是迁移到堆中,使用string.intern()可以验证?
jdk 1.8中已经彻底移除永久代?用metaspace替换,metaspace直接从本地内存分配,也需要通过MetaspaceSize或MaxMetaspaceSize来限制大小
针对字符串常量的测验
在jdk 1.6中,报错Perm space OOM
在jdk 1.7中,报错Heap space OOM
在jdk 1.8中,报错Heap space OOM(不同版本表现不一样?字符串常量可能还在堆中分配?)
在jdk 1.8中,使用Cglib产生大量动态类,限制MetaspaceSize大小,可以报错Metaspace OOM
5.使用Eclipse MAT插件
查看各个线程以及线程中的对象个数、占用内存情况
查看占用内存多的大对象排行
辅助进行Memory Leak分析