java.lang.StackOverflowError 和OutofMemoryError解决方案汇总

 在java虚拟机规范中,虚拟机栈和本地方法栈都会出现StackOverflowError和OutofMemoryError,程序计数器是java虚拟机中唯一一块不会产生error的内存区域,StackOverflowError代表的是,当栈深度超过虚拟机分配给线程的栈大小时就会出现此error,OutofMemoryError代表的是,当再申请新的内存时,虚拟机分配给线程的内存大小中无法再分配新的内存,就会出现此error。

现象:对象互相嵌套设置出现StackOverflowError异常,也就是函数调用层级过多导致。比如死递归。

看到这个异常的第一反应,就是检查代码中是否有大量的递归调用,结果发现就是没有。

然后想到的是JVM默认的栈大小,于是想修改JVM参数,这个参数可以在maven的pom.xml文件中进行配置其中,

以下片段为修改栈大小:

<jvmArgs>   
    <jvmArg>-Xss2048K</jvmArg>
</jvmArgs>

其实个人来说,不是很感动xml文件,因为我表示我看不是很懂这个文件中的信息,所有不敢改动。

因此我在hope的配置文件中,稍微改动了一些配置参数:

spark.executor.extraJavaOptions="-Xss3062k"

从原来的-Xss2048k修改为3062,希望这次好用。

还修改了一个参数:

spark.driver.extraJavaOptions="-XX:+UseConcMarkSweepGC  -XX:+UseParNewGC   -XX:+PrintGCDetails  -XX:ThreadStackSize=4m"

将-XX:ThreadStackSize=2m 设置为-XX:ThreadStackSize=4m。

结果:报错了,随后改回原来的hope参数,不过报错不是因为参数设置,是因为我算法里面修改了依据代码,导致我的算法输入数据中有NULL值。

OOM:在scala中,大量使用了将执行结果拉取到driver端的active操作:collect,take,show等,导致OOM

使用collect将数据拉取到driver端,而当数据量超过Driver内存时会报错OOM。所以尽量不要打印太多内容,这样出的bug让人泪奔。
Java常见的几种内存溢出及解决方法【情况一】:
java.lang.OutOfMemoryError:Javaheapspace:这种是java堆内存不够,一个原因是真不够(如递归的层数太多等),另一个原因是程序中有死循环;
如果是java堆内存不够的话,可以通过调整JVM下面的配置来解决:
-Xms3062m
-Xmx3062m
【情况二】
java.lang.OutOfMemoryError:GCoverheadlimitexceeded
【解释】:JDK6新增错误类型,当GC为释放很小空间占用大量时间时抛出;一般是因为堆太小,导致异常的原因,没有足够的内存。
【解决方案】:
1、查看系统是否有使用大内存的代码或死循环;
2、通过添加JVM配置,来限制使用内存:
-XX:-UseGCOverheadLimit
【情况三】:
java.lang.OutOfMemoryError:PermGenspace:这种是P区内存不够,可通过调整JVM的配置:
-XX:MaxPermSize=128m
-XXermSize=128m
【注】:
JVM的Perm区主要用于存放Class和Meta信息的,Class在被Loader时就会被放到PermGenspace,这个区域成为年老代,GC在主程序运行期间不会对年老区进行清理,默认是64M大小,当程序需要加载的对象比较多时,超过64M就会报这部分内存溢出了,需要加大内存分配,一般128m足够。
【情况四】:
java.lang.OutOfMemoryError:Directbuffermemory
调整-XX:MaxDirectMemorySize=参数,如添加JVM配置:
-XX:MaxDirectMemorySize=128m
【情况五】:
java.lang.OutOfMemoryError:unabletocreatenewnativethread
【原因】:Stack空间不足以创建额外的线程,要么是创建的线程过多,要么是Stack空间确实小了。
【解决】:由于JVM没有提供参数设置总的stack空间大小,但可以设置单个线程栈的大小;而系统的用户空间一共是3G,除了Text/Data/BSS/MemoryMapping几个段之外,Heap和Stack空间的总量有限,是此消彼长的。因此遇到这个错误,可以通过两个途径解决:1.通过-Xss启动参数减少单个线程栈大小,这样便能开更多线程(当然不能太小,太小会出现StackOverflowError);2.通过-Xms-Xmx两参数减少Heap大小,将内存让给Stack(前提是保证Heap空间够用)。
【情况六】:
java.lang.StackOverflowError
【原因】:这也内存溢出错误的一种,即线程栈的溢出,要么是方法调用层次过多(比如存在无限递归调用),要么是线程栈太小。
【解决】:优化程序设计,减少方法调用层次;调整-Xss参数增加线程栈大小。
 
 


参考链接:

https://zhidao.baidu.com/question/1695734020620443668.html


猜你喜欢

转载自blog.csdn.net/pearl8899/article/details/80577058
今日推荐