内存溢出的产生和解决方案

为什么会发生OOM(内存溢出)

a、JVM设置的内存过小,而业务运行却需要较多的内存(这样会导致程序运行不起来,或者是运行一段时间后就挂了)。

b、GC回收内存的速度赶不上程序运行消耗内存的速度(大量数据往集合里面插)。

c、存在内存泄漏,时间一久就出现内存溢出。

OOM场景一:Java heap space

JVM参数设置堆大小:-Xmx100m -Xms100m 

// 大对象导致堆内存溢出例子

   @GetMapping("/t")
    public Result test() throws Exception{
        //初始化一个大对象数组
        byte[] array=new byte[1024*1024*80];
        return Result.ok("12313");
    }

 解决方案:

 提供更多的 Java 堆空间,这样是治标不治本。正确的方式是分析一下的两个问题:

a、哪些对象占据堆的大部分

b、 在源代码中分配这些对象的位置

OOM场景二 : GC overhead limit exceeded

你的应用程序花费太多的时间做垃圾收集太少的结果JVM的方式。默认情况下,如果 JVM 花费超过98% 的总时间进行 GC 并且在 GC 之后仅回收不到 2% 的堆,则JVM 被配置为抛出此错误。

解决方案:

a、哪些对象占据堆的大部分

b、 在源代码中分配这些对象的位置

ps:使用 -XX:-UseGCOverheadLimit,使用这个选项——而不是解决问题,你只是推迟不可避免的问题:应用程序内存不足,需要修复。指定此选项只会用更熟悉的消息java.lang.OutOfMemoryError: Java heap space掩盖原始java.lang.OutOfMemoryError: GC 开销限制超出错误。

OOM场景三: PermGen space 永久空间

这异常代表永久代的内存区域被耗尽。永久代主要由加载并存储到 PermGen 中的类声明组成。

解决方案:

a、解决初始化时OutOfMemoryError

当应用程序启动时触发由于 PermGen 耗尽导致的 OutOfMemoryError 时,解决方案很简单。应用程序只需要更多空间将所有类加载到 PermGen 区域,所以我们只需要增加它的大小。为此,请更改您的应用程序启动配置并添加(或增加(如果存在))类似于以下示例的-XX:MaxPermSize参数:

java -XX:MaxPermSize=512m 

b、解决重新部署时OutOfMemoryError

当您重新部署应用程序后立即发生 OutOfMemoryError 时,您的应用程序会遭受类加载器泄漏。在这种情况下,解决问题的最简单,最直接的方式就是用工具排查,找到有问题的代码,并解决它以分钟为单位。对于那些不能使用 Plumbr 或决定不使用的人,也可以使用替代方法。为此,您应该继续进行堆转储分析 - 在重新部署后使用类似于以下命令的命令进行堆转储:

jmap -dump:format=b,file=dump.hprof <process-id>

c、解决运行时OutOfMemoryError

对于那些再次无法使用 Plumbr 的人,也可以使用另一种方法。在这种情况下,第一步是检查是否允许 GC 从 PermGen 卸载类。标准的 JVM 在这方面相当保守——类天生就是为了永生。所以一旦加载,即使没有代码再使用它们,类也会留在内存中。当应用程序动态创建大量类并且长时间不需要生成的类时,这可能会成为一个问题。在这种情况下,允许 JVM 卸载类定义会很有帮助。这可以通过向启动脚本添加一个配置参数来实现:

-XX:+CMSClassUnloadingEnabled

默认情况下,它设置为 false,因此要启用它,您需要在 Java 选项中显式设置以下选项。如果您启用CMSClassUnloadingEnabledGC 也会清除PermGen 并删除不再使用的类。请记住,此选项仅在使用以下选项启用UseConcMarkSweepGC时才有效。因此,当运行ParallelGC或,上帝保佑,Serial GC 时,请确保您已通过指定将 GC 设置为CMS

-XX:+UseConcMarkSweepGC

在确保可以卸载类并且问题仍然存在后,您应该继续进行堆转储分析 - 使用类似于以下的命令进行堆转储:

jmap -dump:file=dump.hprof,format=b <process-id>

对dump出来的文件可以是用jprofiler 或者Eclipse MAT进行解析定位排除问题

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当使用多进程时,每个进程都会独立分配一部分内存。如果每个进程占的内存过多,可能会导致整个系统的内存溢出。在这种情况下,可以考虑以下几种解决方案: 1. 减少进程的内存占用:检查每个进程的内存占用情况,确认是否存在大量内存占用的操作或对象创建。可以优化代码,减少内存使用量。例如,使用生成器、迭代器等方式避免一次性加载大量数据到内存中。 2. 调整并发进程数:降低同时运行的进程数量,减少内存占用。可以通过调整进程池大小、限制并发任务数量或者使用队列来控制并发进程数。 3. 使用进程池管理内存:使用`multiprocessing.Pool`来管理进程池,控制并发进程数。这样可以避免一次性启动过多进程导致内存溢出。 4. 增加内存资源:如果系统内存不足以支持多进程运行,可以考虑增加内存资源。这可以通过升级硬件、增加虚拟机实例等方式来实现。 5. 使用分布式处理:如果单机资源无法满足需求,可以考虑使用分布式处理方式,将任务分发到多台机器上进行处理,以减轻单机的压力。 6. 使用内存管理工具:可以使用Python中的内存管理工具,如`memory_profiler`和`objgraph`等,来定位内存占用较高的地方,并进行优化。 7. 调整系统参数:在某些情况下,可以通过调整操作系统的参数来增加进程的可用内存。例如,对于Linux系统,可以增加`vm.overcommit_memory`参数的值。 请根据具体情况选择适合的解决方案,如果问题仍然存在,可能需要进一步分析代码和系统环境以找到更准确的解决方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值