JAVA进程突然挂掉

JVM内存不足导致进程死掉. Native memory allocation (mmap) failed to map

一台服务器上部署很多JAVA进程已经是微服务的常态,但也有些坑。

背景,测试服务器上的一些JAVA进程突然挂掉,查看call back的日志发现如下:

# There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (mmap) failed to map 1786867712 bytes for committing reserved memory. # Possible reasons: # The system is out of physical RAM or swap space # In 32 bit mode, the process size limit was hit # Possible solutions: # Reduce memory load on the system # Increase physical memory or swap space # Check if swap backing store is full # Use 64 bit Java on a 64 bit OS # Decrease Java heap size (-Xmx/-Xms) # Decrease number of Java threads # Decrease Java thread stack sizes (-Xss) # Set larger code cache with -XX:ReservedCodeCacheSize= # This output file may be truncated or incomplete. # # Out of Memory Error (os_linux.cpp:2673), pid=28610, tid=139813184919296 # # JRE version: Java(TM) SE Runtime Environment (8.0_40-b26) (build 1.8.0_40-b26) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.40-b25 mixed mode linux-amd64 compressed oops) #

很明显是由于服务器的内存不足造成

内存不够用分两种情况

推测:内存不够用分两种情况

推测 1, JAVA程序使用的内存申请超出了JVM分配的, 此类只会抛出

java.lang.OutOfMemoryError: Java heap space,JAVA进程是不会有影响,下次也可以继续接受请求提供服务

推测 2, JVM尝试去像操作系统申请一块内存超出系统的可使用(RSS)内存时, 此时linux会结束JAVA进程,并抛出如上错误。

这种场景也常见: 如在一台16G内存的服务器上跑着两个服务,两个服务同时启动各自分配10G内存,因为JVM的垃圾回收机制一般情况下是不会有问题,能正常服务,当两个服务同时需要用到的内存超出16G时,将会被linux干掉一个服务.

(注: JVM启动时,通过-Xmx等参数分配的内存只会影响到VIRT ,详见上一篇博客《JAVA进程和linux内存间的大小关系》

证实:

去证实是最重要的, 上面的都是我的推测

一台内存是1G的linux服务器

total used free shared buffers cached Mem: 984 119 864 0 2 20 -/+ buffers/cache: 97 886 Swap: 2044 45 1999

物理内存+swap内存 在 3G左右 (886+1999)

加入JAVA程序,因为是要观察JAVA的内存超出是否会终止JAVA的进程,故思路如下设计

1,用一个线程去申请分配内存

2,主线程不停报告存活状态

程序如下

/** * 用于演示内存不足导致JAVA进程退出, 注意:输入的size勿导致超出int (1024 * 1024 * size) * * */ 

public class TestClass {
    public static void main(String[] args) throws IOException, InterruptedException { 
        Thread t1 = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                    try {
                        //接收测试内存的大小,单位m 
                        byte[] byteSize = new byte[50]; 
                        System.out.print("input want to allocation memory:");
                        int temp = System.in.read(byteSize); 
                        String sizeStr = new String(byteSize, 0, temp); 
                        int size = Integer.parseInt(sizeStr.trim()); 
                        System.out.println(1024 * 1024 * size); 
                        byte[] bt = new byte[1024 * 1024 * size]; 
                        System.out.println("succ..allocation: " + size + "m"); 
                        //阻30分,防止垃圾回收 
                        Thread.sleep(1000 * 60 * 3);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } 
                }
            });
        t1.start(); 
        while (true) {
            Thread.sleep(1000 * 20); 
            System.out.println(Thread.currentThread().getId() + ": i'm alive");
        }
     }

证实推测1:

运行程序,输入1000 (这里只要超过了年龄代内存其实就会抛出异常)

Exception in thread "Thread-0" java.lang.NegativeArraySizeException
    at com.pp.TestClass$1.run(TestClass.java:19)
    at java.lang.Thread.run(Thread.java:662)

1: i'm alive

1: i'm alive

输出 alive, 证明了推测1,使用内存超出了并不会导致JAVA进程死掉

证实推测2:

打开窗口1 , 运行,输入

root@ubuntu:/home/hejinbin# java -Xmx3048m -Xms3048m org.hejinbin.memory.test.Test

input want to allocation memory:

打开窗口2 , 运行,输入

然后在窗口1输入1500

运行如下:

input want to allocation memory:1500

succ..allocation: 1500m

然后在窗口2,输入1500

此时发现窗口1的JAVA进程被杀掉了,完整如下

succ..allocation: 1500m

Killed

证实了推测2

结论: 如今微服务流行(趁点热度)。很多进程同时在一台服务器上跑, 必须注意,分配给JAVA的内存只和一定在服务器的可用内存之内。不然很有可能突然被linux干掉一个进程

转载于:https://my.oschina.net/u/1054538/blog/832272

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值