文档章节

Java执行Runtime.exec(shell)报Cannot allocate memory

山哥
 山哥
发布于 2014/06/05 17:05
字数 1118
阅读 4820
收藏 10
点赞 0
评论 0

在Linux下用java的Runtime.getRuntime().exec(cmd)方式,执行shell脚本时,遇到“Cannot allocate memory”的错误。

网上查询资料整理如下:

Cannot allocate memory

在Linux上调试一个比较复杂的Java程序,称为JavaA吧,JavaA会频繁的通过Process proc = Runtime.getRuntime().exec(cmd);调用一些外部程序。在系统负载和该程序占用内存都比较大的情况下,会出现调用失败的情况,错误信息是:"Cannot allocate memory"。


overcommit_memory

通过top发现,Java A大部分时间占用的内存实际并不多,但是占用的虚拟内存很大。马上修改该程序启动时的JVM参数,将最大内存调的小一些,果然就不出错了。由于JavaA必须在内存中处理大量的数据,内存太小了就可能处理不了,因此这么改是不可行的。

上网查的过程中,发现一些有趣的东西。Linux内核中可以设置内存的overcommit_memory属性(设置方法:echo 1 > /proc/sys/vm/overcommit_memory),意思是Linux内核认为有些程序很保守,总是申请较多的内存,但实际并不使用,因此在设置overcommit后,内核将不检查剩余内存是否够用,直接允许所有的内存分配。可能大部分情况下没问题,但是仔细想想,还是有很大的问题,最严重的是改变了malloc的语义,调用者不能通过返回值来判断内存是否分配成功了。另外一个问题是,万一内存真的不够了怎么办?Linux中有个特殊的进程,OOM(out-of-memory)进程终止者,其功能就是在内存真的不够时,随机或者根据某些原则杀掉一些进程。选择进程的原则好像不能精确控制,那将是一件很恐怖的事情。。。


Runtime.getRuntime().exec(cmd) 的执行流程分析

继续上网查,大概意思是Java程序调用外部程序时可能需要分配跟父进程同等大小的内存。这就奇怪了,比如说,我随便调用一下ls命令,也需要很多内存吗?肯定是Java调用外部程序的接口里处理比较特殊。嗯,刚好JDK也开源,看看源码去。

分析SUN JDK 1.5 SRC,找到Runtime.getRuntime().exec(cmd)的执行流程:

java.lang.Runtime.exec(cmd);

--java.lang.ProcessBuilder.start();

----java.lang.ProcessImpl.start();

------Java_java_lang_UNIXProcess_forkAndExec() in j2se/src/solaris/native/java/lang/UNIXProcess_md.c

--------1). fork(); 2). execvp();

man fork知道,fork产生的子进程需要复制父进程在内存中的所有数据内容(代码段、数据段、堆栈段),由于全部复制开销较大,因此Linux已经采用copy-on-write机制,即只是复制页表,共享内容,在有改变的时候再去申请内存和复制数据。

因此我分析,问题的原因可能是这样的,虽然Linux早已在fork()中采用copy-on-write机制,但是JVM调用fork()后,Java进程里的其它线程往往会被调度回来继续执行,修改了自己的内存,而这个时候execvp()还没有执行,于是悲剧就发生了,内存都要重新复制一遍。

 

解决办法

方法一(不推荐):修改 overcommit_memory值:echo 1 > /proc/sys/vm/overcommit_memory

方法二: 既然问题出在可能会申请分配跟父进程同等大小的内存,那么我限制父进程使用的内存就可以了。前面说了我们正在开发的JavaA必须使用比较大的内存,可是JavaA不一定是父进程呀,我可以单独运行一个Java程序,称为JavaB吧,由它负责调用外部程序,JavaA调用我们封装后的接口与之通信,等待外部程序结束,从而与 Runtime.getRuntime().exec(cmd) 的语义保持一致。这个单独运行的JavaB只需要很小很小的内存,因此不太可能出现无法分配内存,进而无法执行外部程序的问题了。

方法三:针对Tomcat的Web应用,我们习惯在catalina.sh中进行JVM的内存优化配置:

JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms256m -Xmx1024m -XX:NewSize=64m -XX:MaxNewSize=512m -XX:PermSize=64m -XX:MaxPermSize=512m -XX:+DisableExplicitGC"

注意,我们要把 -Xms, -XX:NewSize, -XX:PermSize 的内存大小设置一个较小的值,这样才能保证不出现 Cannot allocate memory 异常。

本文转载自:http://blog.csdn.net/vernonzheng/article/details/8644936

共有 人打赏支持
山哥

山哥

粉丝 242
博文 350
码字总数 136465
作品 0
南京
程序员
执行Runtime.exec异常: error=12,Cannot allocate memory

Exception Trace: In the Linux circumstance, when the program executes till this place: Process p = Runtime.getRuntime().exec(cmdArr); it throws an exception like this: java.i......

疯狂的艺术家
2012/02/06
0
1
Linux 环境下安装 elasticsearch 5.x、6.x 问题汇总

can not run elasticsearch as root [o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main] org.elasticsearch.bootstrap.StartupException: java.lang.Ru......

BeckJin
05/19
0
0
bytebuffer vs c++ malloc

Java equivalents of malloc(), new, free() and delete (ctd) Continued from our introduction to memory management operators in C/C++ and Java. A Java equivalent of the malloc() fu......

不道归来
2017/10/23
0
0
It's all about buffers: zero-copy, mmap and Java NIO

Sep 10, 2016 in OS There are use cases where data need to be read from source to a sink without modification. In code this might look quite simple: for example in Java, you may ......

不道归来
2017/10/23
0
0
Android Out Of Memory(OOM) 的详细研究

基于Android开发多媒体和游戏应用时,可能会挺经常出现Out Of Memory 异常 ,顾名思义这个异常是说你的内存不够用或者耗尽了。 在Android中,一个Process 只能使用16M内存,如果超过了这个限...

caikezhan
2013/10/15
0
0
研究java.lang.Runtime类

一、概述 Runtime类封装了运行时的环境。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。 一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Ru...

五大三粗
2015/06/15
0
0
利用“进程注入”实现无文件复活 WebShell

  * 本文作者:rebeyond,本文属FreeBuf原创奖励计划,未经许可禁止转载   引子   上周末,一个好兄弟找我说一个很重要的目标shell丢了,这个shell之前是通过一个S2代码执行的漏洞拿到...

FreeBuf
05/30
0
0
关于JVM直接内存触发Full GC

今天在研究JVM的直接内存溢出时发现直接内存和堆内存一样,在直接内存快满时会触发full gc,full gc会将未被引用的对象及其指向的直接内存释放掉,如下为测试代码: package test.oom; impo...

囚兔
2015/08/04
0
0
Ubuntu笔记--软件安装篇

不想看书复习时,写写笔记。进入主题。 目前接触到的程序安装格式有.deb,.bin,还有可执行类型(后缀看不到,查看属性时显示类型为executable )。知道的有以下几种方式: 1、通过源安装。 打...

Cycle_C
2012/08/23
0
0
JAVA虚拟机起步-虚拟机调优

JAVA虚拟机起步OutOfMemory问题解决记录。 问题: JAVA虚拟机报错 # java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space? # # Internal Error......

飓风2000
2014/03/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

shell中的函数、shell中的数组、告警系统需求分析

shell中的函数 格式: 格式: function f_name() { command } 函数必须要放在最前面 示例1(用来打印参数) 示例2(用于定义加法) 示例3(用于显示IP) shell中的数组 shell中的数组1 定义数...

Zhouliang6
55分钟前
2
0
用 Scikit-Learn 和 Pandas 学习线性回归

      对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了。 1. 获取数据,定义问题     没有...

wangxuwei
今天
1
0
MAC安装MAVEN

一:下载maven压缩包(Zip或tar可选),解压压缩包 二:打开终端输入:vim ~/.bash_profile(如果找不到该文件新建一个:touch ./bash_profile) 三:输入i 四:输入maven环境变量配置 MAVEN_HO...

WALK_MAN
今天
0
0
33.iptables备份与恢复 firewalld的9个zone以及操作 service的操作

10.19 iptables规则备份和恢复 10.20 firewalld的9个zone 10.21 firewalld关于zone的操作 10.22 firewalld关于service的操作 10.19 iptables规则备份和恢复: ~1. 保存和备份iptables规则 ~2...

王鑫linux
今天
2
0
大数据教程(2.11):keeperalived+nginx高可用集群搭建教程

上一章节博主为大家介绍了目前大型互联网项目的系统架构体系,相信大家应该注意到其中很重要的一块知识nginx技术,在本节博主将为大家分享nginx的相关技术以及配置过程。 一、nginx相关概念 ...

em_aaron
今天
1
0
Apache Directory Studio连接Weblogic内置LDAP

OBIEE默认使用Weblogic内置LDAP管理用户及组。 要整理已存在的用户及组,此前办法是导出安全数据,文本编辑器打开认证文件,使用正则表达式获取用户及组的信息。 后来想到直接用Apache Dire...

wffger
今天
2
0
HFS

FS,它是一种上传文件的软件。 专为个人用户所设计的 HTTP 档案系统 - Http File Server,如果您觉得架设 FTP Server 太麻烦,那么这个软件可以提供您更方便的档案传输系统,下载后无须安装,...

garkey
今天
1
0
Java IO类库之BufferedInputStream

一、BufferedInputStream介绍 /** * A <code>BufferedInputStream</code> adds * functionality to another input stream-namely, * the ability to buffer the input and to * sup......

老韭菜
今天
0
0
STM 32 窗口看门狗

http://bbs.elecfans.com/jishu_805708_1_1.html https://blog.csdn.net/a1985831055/article/details/77404131...

whoisliang
昨天
1
0
Dubbo解析(六)-服务调用

当dubbo消费方和提供方都发布和引用完成后,第四步就是消费方调用提供方。 还是以dubbo的DemoService举例 -- 提供方<dubbo:application name="demo-provider"/><dubbo:registry address="z...

青离
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部