
为了更直接的了解各区域,下面我们来看几个示例。
1、Java 堆溢出
下面的程中我们限制Java 堆的大小为20MB,不可扩展(将堆的最小值-Xms 参
数与最大值-Xmx 参数设置为一样即可避免堆自动扩展),通过参数-XX:+HeapDump
OnOutOfMemoryError 可以让虚拟机在出现内存溢出异常时Dump 出当前的内存堆转储
快照以便事后进行分析。
参数设置如下



Java 堆内存的OutOfMemoryError异常是实际应用中最常见的内存溢出异常情况。出现Java 堆内存溢出时,异常堆栈信息“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;
- public class StackOverFlow {
- private int i ;
- public void plus() {
- i++;
- plus();
- }
-
- 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();
- }
- }
- }
- 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;
- public class MethodAreaOutOfMemory {
-
- 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();
- }
- }
- }
- class TestCase{
-
- }