JAVA 聚焦 OutOfMemoryError 异常问题记录

 更新时间:2025年04月27日 11:20:15   作者:小窦总  
在 Java 开发中,内存溢出异常是影响程序稳定性的关键问题,了解其原理和应对方法,对开发者至关重要,这篇文章主要介绍了JAVA聚焦 OutOfMemoryError 异常,需要的朋友可以参考下

在 Java 开发中,内存溢出异常是影响程序稳定性的关键问题。了解其原理和应对方法,对开发者至关重要。

一、Java 堆溢出

原理

Java 堆用于存储对象实例。不断创建对象,且阻止垃圾回收器回收,对象数量超出堆容量时,就会引发堆溢出。

示例代码

// VM Args: -Xmx20m -Xms20m -XX:+HeapDumpOnOutOfMemoryError
public class HeapOOM {
    static class OOMObject {}
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        while (true) {
            list.add(new OOMObject());
        }
    }
}

解决思路

  • 利用内存映像分析工具(如 Eclipse Memory Analyzer )分析堆转储快照。
  • 区分内存泄漏和内存溢出:若存在无用对象长期占用内存,是内存泄漏;若对象都有用但堆空间不足,可调整堆参数(-Xmx 与 - Xms ),并优化代码减少内存占用。

二、虚拟机栈和本地方法栈溢出

原理

  • 线程请求栈深度超虚拟机允许值,抛出StackOverflowError 。
  • 虚拟机栈若支持动态扩展,扩展时内存申请失败,抛出OutOfMemoryError (HotSpot 不支持栈动态扩展 )。

示例代码

测试StackOverflowError

// VM Args: -Xss128k
public class JavaVMStackSOF {
    private int stackLength = 1;
    public void stackLeak() {
        stackLength++;
        stackLeak();
    }
    public static void main(String[] args) throws Throwable {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Exception e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}

测试大量线程导致内存溢出

// VM Args: -Xss2M
public class JavaVMStackOOM {
    private void dontStop() {
        while (true) {}
    }
    public void stackLeakByThread() {
        while (true) {
            Thread thread = new Thread(() -> dontStop());
            thread.start();
        }
    }
    public static void main(String[] args) throws Throwable {
        JavaVMStackOOM oom = new JavaVMStackOOM();
        oom.stackLeakByThread();
    }
}

解决思路

  • 出现StackOverflowError 时,可根据错误堆栈分析递归调用等问题代码。
  • 对于大量线程导致的内存溢出,可减少线程数量、调整栈内存大小(-Xss ),或升级 64 位虚拟机以获取更多内存。

三、方法区和运行时常量池溢出

原理

  • 方法区存储类信息、常量池等。运行时动态生成大量类(如使用 CGLib ),会耗尽方法区空间。
  • 运行时常量池是方法区一部分,字符串操作(如String.intern() )不当,可能导致常量池溢出。

示例代码

方法区溢出测试(借助 CGLib )

// VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class JavaMethodAreaOOM {
    static class OOMObject {}
    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    return proxy.invokeSuper(obj, args);
                }
            });
            enhancer.create();
        }
    }
}

运行时常量池溢出测试(String.intern()

// JDK 6 运行:-XX:PermSize=6M -XX:MaxPermSize=6M
// JDK 7及以上运行:-Xmx6M
public class RuntimeConstantPoolOOM {
    public static void main(String[] args) {
        String str1 = new StringBuilder("计算机").append("软件").toString();
        System.out.println(str1.intern() == str1); 
        String str2 = new StringBuilder("ja").append("va").toString();
        System.out.println(str2.intern() == str2); 
    }
}

解决思路

  • 方法区溢出时,调整方法区相关参数(如 JDK 8 前的 - XX:PermSize 和 - XX:MaxPermSize ,JDK 8 及以后的 - XX:MetaspaceSize 等 ),优化代码减少动态类生成。
  • 针对常量池溢出,合理使用String.intern() 方法,避免无意义的字符串入池操作。

四、直接内存溢出

原理

直接内存容量由-XX:MaxDirectMemorySize 参数控制,默认与 Java 堆最大值相同。直接或间接使用DirectByteBufferUnsafe 等分配内存超出限制,会引发溢出。

示例代码

// VM Args: -Xmx20M -XX:MaxDirectMemorySize=10M
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);
        }
    }
}

解决思路

  • 合理设置-XX:MaxDirectMemorySize 参数。
  • 排查代码中直接内存分配操作,如 NIO 相关代码,确保内存分配合理。
ld.get(null);
while (true) {
unsafe.allocateMemory(_1MB);
}
}
}

解决思路

- 合理设置`-XX:MaxDirectMemorySize` 参数。
- 排查代码中直接内存分配操作,如 NIO 相关代码,确保内存分配合理。

通过深入理解 Java 内存溢出异常原理,结合具体代码示例和解决思路,开发者能更好地定位和解决内存问题,保障 Java 程序稳定运行。

到此这篇关于JAVA 聚焦 OutOfMemoryError 异常问题记录的文章就介绍到这了,更多相关java OutOfMemoryError 异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mybatis的mapper特殊字符转移及动态SQL条件查询小结

    mybatis的mapper特殊字符转移及动态SQL条件查询小结

    mybatis mapper文件中条件查询符,如>=,<,之类是不能直接写的会报错的需要转移一下,本文给大家介绍了常见的条件查询操作,对mybatis的mapper特殊字符及动态SQL条件查询相关知识感兴趣的朋友一起看看吧
    2021-09-09
  • SWT(JFace)体验之StackLayout布局

    SWT(JFace)体验之StackLayout布局

    SWT(JFace)体验之StackLayout布局实现代码。
    2009-06-06
  • java导出数据库中Excel表格数据的方法

    java导出数据库中Excel表格数据的方法

    这篇文章主要为大家详细介绍了java导出数据库中Excel表格数据的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • 关于eclipse中运行tomcat提示端口被占用的4种解决

    关于eclipse中运行tomcat提示端口被占用的4种解决

    这篇文章主要介绍了关于eclipse中运行tomcat提示端口被占用的4种解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • SpringBoot favicon Chrome设置问题解决方案

    SpringBoot favicon Chrome设置问题解决方案

    在本篇文章里小编给大家分享的是关于SpringBoot favicon Chrome设置问题实例内容,小的朋友们可以参考学习下。
    2020-02-02
  • Spring创建Bean的关键流程分享

    Spring创建Bean的关键流程分享

    Spring中的Bean生命周期从创建到销毁分为多个阶段,包括实例化、属性填充、Aware回调、初始化前处理、初始化处理、初始化后处理、Bean就绪和销毁,每个阶段都有特定的任务,例如属性注入、初始化方法调用和资源释放等,Spring通过三级缓存机制解决循环依赖问题
    2026-04-04
  • Java语言实现简单FTP软件 辅助功能模块FTP站点管理实现(12)

    Java语言实现简单FTP软件 辅助功能模块FTP站点管理实现(12)

    这篇文章主要为大家详细介绍了Java语言实现简单FTP软,辅助功能模块FTP站点管理的实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • Spring IOC容器启动示例分析

    Spring IOC容器启动示例分析

    这篇文章主要给大家介绍了Spring IOC基于注解启动的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2023-02-02
  • Java基础教程之static五大应用场景

    Java基础教程之static五大应用场景

    这篇文章主要给大家介绍了关于Java基础教程之static五大应用场景的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • springboot集成mybatis-plus遇到的问题及解决方法

    springboot集成mybatis-plus遇到的问题及解决方法

    这篇文章主要介绍了springboot集成mybatis-plus遇到的问题及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11

最新评论