1、Java 堆溢出
下面的程中我们限制Java 堆的大小为20MB,不可扩展(将堆的最小值-Xms 参
数与最大值-Xmx 参数设置为一样即可避免堆自动扩展),通过参数-XX:+HeapDump
OnOutOfMemoryError 可以让虚拟机在出现内存溢出异常时Dump 出当前的内存堆转储
快照以便事后进行分析。
参数设置如下
package com.yhj.jvm.memory.heap;
import java.util.ArrayList;
import java.util.List;
/**
* @Described:堆溢出测试
* @VM args:-verbose:gc -Xms20M -Xmx20M -XX:+PrintGCDetails
* @author YHJ create at 2011-11-12 下午07:52:22
* @FileNmae com.yhj.jvm.memory.heap.HeapOutOfMemory.java
*/
public class HeapOutOfMemory {
/**
* @param args
* @Author YHJ create at 2011-11-12 下午07:52:18
*/
public static void main(String[] args) {
List<TestCase> cases = new ArrayList<TestCase>();
while(true){
cases.add(new TestCase());
}
}
}
/**
* @Described:测试用例
* @author YHJ create at 2011-11-12 下午07:55:50
* @FileNmae com.yhj.jvm.memory.heap.HeapOutOfMemory.java
*/
class TestCase{
}

存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟着进一步提示“Java heap
space”。
要解决这个区域的异常,一般的手段是首先通过内存映像分析工具(如Eclipse
Memory Analyzer)对dump 出来的堆转储快照进行分析,重点是确认内存中的对象是
否是必要的,也就是要先分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢
出(Memory Overflow)。图2-5 显示了使用Eclipse Memory Analyzer 打开的堆转储快
照文件。
如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots 的引用链。于是就
能找到泄漏对象是通过怎样的路径与GC Roots 相关联并导致垃圾收集器无法自动回收
它们的。掌握了泄漏对象的类型信息,以及GC Roots 引用链的信息,就可以比较准确
地定位出泄漏代码的位置。
如果不存在泄漏,换句话说就是内存中的对象确实都还必须存活着,那就应当检查
虚拟机的堆参数(-Xmx 与-Xms),与机器物理内存对比看是否还可以调大,从代码上
检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期
的内存消耗。
以上是处理Java 堆内存问题的简略思路,处理这些问题所需要的知识、工具与经验
在后面的几次分享中我会做一些额外的分析。
2、java栈溢出
package com.yhj.jvm.memory.stack;
/**
* @Described:栈层级不足探究
* @VM args:-Xss128k
* @author YHJ create at 2011-11-12 下午08:19:28
* @FileNmae com.yhj.jvm.memory.stack.StackOverFlow.java
*/
public class StackOverFlow {
private int i ;
public void plus() {
i++;
plus();
}
/**
* @param args
* @Author YHJ create at 2011-11-12 下午08:19:21
*/
public static void main(String[] args) {
StackOverFlow stackOverFlow = new StackOverFlow();
try {
stackOverFlow.plus();
} catch (Exception e) {
System.out.println("Exception:stack length:"+stackOverFlow.i);
e.printStackTrace();
} catch (Error e) {
System.out.println("Error:stack length:"+stackOverFlow.i);
e.printStackTrace();
}
}
}
3、常量池溢出(常量池都有哪些信息,我们在后续的JVM类文件结构中详细描述)
package com.yhj.jvm.memory.constant;
import java.util.ArrayList;
import java.util.List;
/**
* @Described:常量池内存溢出探究
* @VM args : -XX:PermSize=10M -XX:MaxPermSize=10M
* @author YHJ create at 2011-10-30 下午04:28:30
* @FileNmae com.yhj.jvm.memory.constant.ConstantOutOfMemory.java
*/
public class ConstantOutOfMemory {
/**
* @param args
* @throws Exception
* @Author YHJ create at 2011-10-30 下午04:28:25
*/
public static void main(String[] args) throws Exception {
try {
List<String> strings = new ArrayList<String>();
int i = 0;
while(true){
strings.add(String.valueOf(i++).intern());
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
4、方法去溢出
package com.yhj.jvm.memory.methodArea;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* @Described:方法区溢出测试
* 使用技术 CBlib
* @VM args : -XX:PermSize=10M -XX:MaxPermSize=10M
* @author YHJ create at 2011-11-12 下午08:47:55
* @FileNmae com.yhj.jvm.memory.methodArea.MethodAreaOutOfMemory.java
*/
public class MethodAreaOutOfMemory {
/**
* @param args
* @Author YHJ create at 2011-11-12 下午08:47:51
*/
public static void main(String[] args) {
while(true){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestCase.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
return arg3.invokeSuper(arg0, arg2);
}
});
enhancer.create();
}
}
}
/**
* @Described:测试用例
* @author YHJ create at 2011-11-12 下午08:53:09
* @FileNmae com.yhj.jvm.memory.methodArea.MethodAreaOutOfMemory.java
*/
class TestCase{
}
5、直接内存溢出
package com.yhj.jvm.memory.directoryMemory;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
/**
* @Described:直接内存溢出测试
* @VM args: -Xmx20M -XX:MaxDirectMemorySize=10M
* @author YHJ create at 2011-11-12 下午09:06:10
* @FileNmae com.yhj.jvm.memory.directoryMemory.DirectoryMemoryOutOfmemory.java
*/
public class DirectoryMemoryOutOfmemory {
private static final int ONE_MB = 1024*1024;
private static int count = 1;
/**
* @param args
* @Author YHJ create at 2011-11-12 下午09:05:54
*/
public static void main(String[] args) {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
while (true) {
unsafe.allocateMemory(ONE_MB);
count++;
}
} catch (Exception e) {
System.out.println("Exception:instance created "+count);
e.printStackTrace();
} catch (Error e) {
System.out.println("Error:instance created "+count);
e.printStackTrace();
}
}
}