Python实战社群

Java实战社群

长按识别下方二维码,按需求添加

扫码关注添加客服

进Python社群▲

扫码关注添加客服

进Java社群

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。任何不保留此声明的转载都是抄袭。

Java进程突然不见了,日志里并没有任何它们的信息,它们就那么凭空蒸发了。日志、OOM的一些配置参数,根本就不顶用。

不要惊慌。进程没有灵魂。一个restart,会让这些程序活蹦乱跳again。

问题是那些restart也无法解决的问题,还有默默在背后运作的墨菲定律。

是谁杀死了心爱的Java进程?

不要太绝情,在死之前,起码要让进程发表一点遗言吧。本小篇将分析几种常见的Java进程消失之谜,让你气定神闲看花开花落。

它们有可能:

  • 被操作系统审判了

  • 执行了上帝函数,被队友埋坑了

  • 使用了错误的启动方式

  • 日志系统配置错误

1. 被操作系统审判了

以下问题已经不止一个小伙伴遇到了:我的java进程没了,什么都没留下,直接蒸发不见了

why?是因为太多情,对象太多了么?

这是趣味性和技巧性非常突出的一个问题。

执行dmesg命令,大概率会看到你的进程崩溃信息躺尸在那里。

为了能看到发生的时间,我们习惯性加上参数T

dmesg -T

明显是操作系统看你的进程不顺眼,给Kill了。

这个现象,和Linux的内存管理有关。

由于Linux系统采用的是虚拟内存分配方式,JVM的代码的使用都会消耗内存,但是申请出来的内存,只要没真正access过,是不算的,因为没有真正为之分配物理页面。

随着使用内存越用越多。第一层防护墙就是SWAP;当SWAP也用的差不多了,会尝试释放cache;当这两者资源都耗尽,杀手就出现了。oom killer会在系统内存耗尽的情况下跳出来,选择性的干掉一些进程以求释放一点内存。

所以这时候我们的Java进程,是操作系统“主动”终结的,JVM连发表遗言的机会都没有。这个信息,只能在操作系统日志里找。

要解决这种问题,首先不能太贪婪。比如一共8GB的机器,你把整整7.5GB分配给了JVM。当操作系统内存不足,你的JVM就可能成为oom-killer的猎物。

不过,通过下面的命令,可以让进程避免被审判。

echo -17 > /proc/[PID]/oom_adj

这是因为,oom_adj文件,就是进程被oom killer杀掉的权重,一般介于 [-17,15]之间。越高的权重,意味着更可能被oom killer选中。

一旦你这么做,你的Java进程就是特权阶层了,可以无视规则。

2. 执行了上帝函数

xjjdog对这个函数的评价是:比你起认识它,还不如你不认识它。

这位函数你不要瞅我。说的就是你,System.exit。

这个函数危险得很,它将强制终止我们的应用,而且什么都不会留下。你应该扫描你的代码,确保这样的逻辑不会存在。

相信我,你并没有需要用程序判断来立即结束进程的需求,业务系统尤其没有。如果有,那大概率是不合理的。除非你把Java当脚本用了。

这个函数,是一个非常高级的埋坑技能,尤其是在Android之类的应用中。应用程序崩溃,你将什么原因都分析不到,哪怕你做了ShutdownHook。

buyaoluanyongwo

使用exit函数,一定要心存善意。

当然我们并不是对此束手无策。下面这段代码,就可以阻止exit的执行,霸道非凡。上帝的那只手,也给掰回去。

import java.security.Permission;public class S {private static class ExitTrappedException extends SecurityException {}private static void forbidSystemExitCall() {final SecurityManager securityManager = new SecurityManager() {public void checkPermission(Permission permission) {if (permission.getName().startsWith("exitVM")) {throw new ExitTrappedException();}}};System.setSecurityManager(securityManager);}private static void enableSystemExitCall() {System.setSecurityManager(null);}public static void main(String[] args) {forbidSystemExitCall();try {System.exit(0);}catch (Exception ex){ex.printStackTrace();}System.out.println("谢谢xjjjdog, 我依然能够执行");}
}

如果你用尽千方百计,都找不到异常终止的原因,试试挂上这段代码吧。有可能是救命的哦。

3. 错误的启动方式

再聊一种最初级最常见还经常发生的一种情况,会造成应用程序的意外死亡:那就是对Java程序错误的启动方式。

很多同学对Linux不是很熟悉,使用XShell登陆之后,调用下面的命令进行启动。

java com.cn.AA &

这位同学还算有点意识,在最后使用了&号,以期望进程在后台运行。但可惜的是,很多情况下,随着XShell Tab页的关闭,或者等待超时,后面的Java进程就随着一块停止了,很让人困惑。

正确的启动方式,就是使用nohup关键字,或者阻塞在其他更加长命的进程里(比如docker)。

nohup java com.cn.AA &

所以,当你登录上终端tty的时候,一定要闹明白当前执行的父进程是谁。你可能是所有接下来要运行的所有进程的祖先哦。

4.日志配置错误

如果上面的原因都不是,那大概率是你的项目里面日志框架的配置错误了。Java中的日志框架繁多,配置方式多样,一不小心,就会踩坑。即使你用的是SpringBoot,也会因为依赖包的问题,造成启动问题。

日志配置错误+异常情况,当然是什么都不会留下。

使用下面的命令,可以将依赖树转移到log文件里进行分析。

mvn dependency:tree > dep.log

如果是SpringBoot项目,是可以给main类加点代码的。

public static void main(String[] args) {try {SpringApplication.run(LinkpowerDtulockApplication.class, args);} catch (Exception e) {System.out.println(e);}
}

这样有什么异常情况,就可以早点发现。

End

另外,还有一些千奇百怪的原因。比如磁盘满了,句柄不够了,这些情况都很隐蔽,需要你精确把控系统的细节。

进程这种静悄悄的死亡方式,通常会给我们的问题排查带来更多的困难。

通常,我们在关闭服务的时候,会使用“kill -15”,而不是“kill -9”,以便让服务在临死之前喘口气。但并不总是有效,因为程序压根就没有机会发表遗言,有更高级别的存在阻止了它。Java进程横死,我们只能寻找其他手段。

作者简介:小姐姐味道  (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。

程序员专栏 扫码关注填加客服 长按识别下方二维码进群

近期精彩内容推荐:  

 肝了一晚上搞出来一个微信订阅号鉴黄机器人

 不允许程序员透露薪资!!!凭啥?

 程序员带娃有多“恐怖” ?!

 有个大神级女朋友是什么体验

在看点这里好文分享给更多人↓↓

解析Java横死之谜,气定神闲看花开花落相关推荐

  1. java 快死了_如果Java快死了,那么它肯定看起来非常健康

    java 快死了 Java快要死了的奇怪但流行的断言只能在没有证据的情况下提出,而不是因为它. 在酷孩子闲逛的论坛(Hacker News,Reddit等)中反复出现的偏见与Java语言背道而驰. 人 ...

  2. 如果Java快死了,那么它肯定看起来非常健康

    Java快要死了的奇怪但流行的断言只能在没有证据的情况下提出,而不是因为它. 在酷孩子闲逛的论坛(Hacker News,Reddit等)中反复出现的偏见与Java语言背道而驰. 人们常常反复感叹 J ...

  3. 转 : 深入解析Java锁机制

    深入解析Java锁机制 https://mp.weixin.qq.com/s?__biz=MzU0OTE4MzYzMw%3D%3D&mid=2247485524&idx=1&s ...

  4. JAVA 实习面试题大全必看

    JAVA 实习面试题大全必看 JavaSE 88 基础语法 9 Q1:简单说说Java有哪些数据类型 答:①分为基本数据类型和引用数据类型.②基本数据类型包括:数值型(byte.short.int.l ...

  5. 深入解析Java OutOfMemoryError

    在Java中,所有对象都存储在堆中.他们通过new关键字来进行分配,JVM会检查是否所有线程都无法在访问他们了,并且会将他们进行回收.在大多数时候程序员都不会有一丝一毫的察觉,这些工作都被静悄悄的执行 ...

  6. 深入解析Java AtomicInteger 原子类型

    深入解析Java AtomicInteger原子类型 在进行并发编程的时候我们需要确保程序在被多个线程并发访问时可以得到正确的结果,也就是实现线程安全.线程安全的定义如下: 当多个线程访问某个类时,不 ...

  7. 聊聊高并发(二十一)解析java.util.concurrent各个组件(三) 深入理解AQS(一)

    AQS是AbstractQueuedSynchronizer的缩写,AQS是Java并包里大部分同步器的基础构件,利用AQS可以很方便的创建锁和同步器.它封装了一个状态,提供了一系列的获取和释放操作, ...

  8. java 日期 解析_Java日期解析(Java DATE Parsing)

    Java日期解析(Java DATE Parsing) 我有一个java.util.Date的愚蠢问题. 我有这一行代码,但我不明白为什么这个日期是用这种格式无法解析的. public class T ...

  9. go python java_一文助你搞懂参数传递原理解析(java、go、python、c++)

    前言 最近一年多的时间陆续接触了一些对我来说陌生的语言,主要就是 Python 和 Go,期间为了快速实现需求只是依葫芦画瓢的撸代码:并没有深究一些细节与原理. 就拿参数传递一事来说各个语言的实现细节 ...

最新文章

  1. c语言是非结构化程序设计语言,第章_结构化程序设计基础和C语言的控制结构(fb).ppt...
  2. 信号与系统matlab课设报告,MATLAB信号与系统实验报告
  3. nacicat for mysql查询_navicat for mysql怎么用
  4. db h2 数据类型_H2数据库函数及数据类型概述-阿里云开发者社区
  5. 董明珠:10个亿不要了,还想再赌五年 雷军:可以试一下
  6. xmapp_mysql端口冲突解决
  7. IDEA - 如何安装Statistic代码统计插件?
  8. 计算机类应届毕业生的求职历程
  9. 乔布斯往事:游戏之神卡马克眼中的“英雄和傻瓜”
  10. 公司测试用例写得乱七八糟,直到制定了这份《测试用例编写规范》
  11. 为什么要在完成电子邮件后存档(Archive)电子邮件
  12. AutoJs学习-高斯模糊
  13. tar命令功能及选项
  14. 三种代码版本控制系统的简介 以及 SVN的安装
  15. 常见的三维人体模型有哪些?如SMPL
  16. PrestaShop - 技术百科 - PrestaShop是一个100%免费的外贸跨境电子商务购物车平台,中文支持非常友好且面向国际化
  17. Java一个16进制字符占多少个字节
  18. 【 Task03:复杂查询方法-视图、子查询、函数等】
  19. 3d游戏建模制作流程详解 丨漫威宇宙【万磁王】
  20. 太牛了!淘宝十年架构变迁

热门文章

  1. PXI/CPCI板卡 PCI协议 9054 原理图PCB 可直接打板
  2. 从UQ、3Q大战看当今互联网格局
  3. redhat9如何安装gcc
  4. 亿点点概述Android基础必会的四五六【四大组件 五大存储 六大布局】
  5. 张墨千鸿蒙秘境,连接四界精魂之力 镇魔曲手游鸿蒙境副本展开新篇
  6. 北京内推 | 腾讯IEG内容推荐中心计算广告算法组招聘算法实习生
  7. 大白话 从零开始学Java(一)
  8. 显卡光线追踪是什么?怎么判断性能高低?
  9. 监听Redis 缓存过期(Key 失效)事件
  10. Web前端之网页导航----手把手教你做导航(图,代码)