当前位置: 首页 > 科技观察

为什么一个运行良好的Java进程会突然瘫痪?

时间:2023-03-12 08:26:00 科技观察

Java能成为使用最广泛的语言,离不开它的内存管理机制。在很多人眼里,Java虚拟机是透明的。只要知道核心API的用法,就可以专注于具体服务的实现,然后依赖Java虚拟机来运行甚至优化应用。你是否有过这样的经历,一个运行良好的Java进程突然瘫痪了。过于依赖Java虚拟机导致我们无法处理问题,反复出现问题影响开发效率。其实造成java进程瘫痪的原因,大部分都可以从java虚拟机层面找到。本文列出了Java进程瘫痪的一些常见原因,供大家交流学习。1、内存回收一直是java的痛点。用Java做Redis这样的产品是不可能的。Java的内存回收机制使得我们在写代码的时候不需要关注对象的回收,同时增加了内存回收的消耗。标记复制需要内存复制,标记清除算法需要停止世界。所以我们在使用缓存的时候,如果量稍微大一点,就需要使用像Redis这样的中间件来帮我们处理。作为一名Javaer,我们享受着内存自动回收带来的舒适,但我们也需要更多地了解内存优化的方法。二、为什么fgc停不下来1、gc在什么情况下会发生?为了理解为什么我们的系统会停止fgc,我们需要了解系统在什么情况下会gc。在jvm层面,当我们创建一个新的对象时,jvm会先在堆区分配该对象所需的内存。这时候如果内存不够,就需要gc,gc的返回结果就是对象的空间地址。jvm首先会进行ygc,也就是我们通常所说的标记复制。如果ygc之后还是没有空间可以申请,就会进行fgc。同样,如果fgc之后仍然没有足够的空间,fgc会循环执行,直到申请到足够的空间。2.不停fgc的原因上面说了,你的代码每一行都可能会出现fgc。如果fgc后空间还是不够,它会一直fgc直到申请到足够的空间。同时JVM会限制VM在抛出OutOfMemory错误之前花费在GC上的时间比例。系统频繁FGC的情况大致有五种:内存泄漏请求处理变慢,导致太多线程同时申请内存metaspace耗尽常量池并占用堆区,耗尽1w堆外内存。通常情况下,处理一个请求的时间是1ms,同时并行的请求数只有10个。4、异常流量监控:防止长尾请求拖累系统我们在监控系统的时候,通常会关注99%的数据。一个长尾数据开始了。一些长尾数据会对系统产生很大的影响。试想一下,如果一个put请求传输几十兆的数据,对java极其不友好,极有可能产生fgc,导致请求变慢,引发一系列问题。总之,磨刀不误砍柴工。当我们的系统因为fgc而一次又一次重启的时候,不如花点时间去了解一下系统性能问题的原因,把导致问题的针拔掉,晚上安心睡觉,更起劲地挖新坑白天。希望每个程序员手里都有一个稳定的系统。参考资料:jvm调优总结:https://hllvm-group.iteye.com/group/wiki/?category_id=301诺亚(Noah)自适应限流稳定工具:https://www.atatech.org/articles/149208【本文为专栏作者《阿里巴巴官方技术》原创稿件,转载请联系原作者】点此查看该作者更多好文