Java内存故障?只是因为你不够帅!

Java 8 内存管理原理解析及内存故障排查实践 本文介绍了Java程序中的内存模型,内存模型划分多份内存区域,不同区域的作用介绍及不同区域的线程之间的内存共享范围,可以帮助开发人员更加理解Java 中内存管理的机制和原理。堆是内存模型中最大的一块内存区域,以堆的空间划分详细的介绍了内存分代,部分垃圾收集器即是物理分代和逻辑分代,G1收集器则物理不分代逻辑保留了以前分代,讲述了不同收集器的原理实现和优缺点,可以根据项目的业务属性,机器配置等因素选择最优的收集器,帮助程序使用最you的收集器可以使得程序的吞吐量和响应速度达到最jia状态。 阅读详情

不羡鸳鸯不羡仙,一行代码调半天。原创:小姐姐味道,欢迎分享,转载请保留出处。

从小我就对Java有着深厚的感情,算下来有几十年的Java经验了。当年的Java还是Sun公司的,我有着多年的Servlet经验,CURD经验,在现在已经被自我革新,转而研究人生的哲学。罢了,不吹了。本文是关于Java故障排查的,属上篇。

为了保证文章的流畅性,我决定一口气把它写完。因为相关方面的培训做的多了,就不需要在写的时候参考资料、翻源代码。掐指一算,本文一个小时没花掉,但篇幅已经较长了。

长了,那就割断。本篇就定为内存排查的上篇,主要讲一些原理。为什么要讲原理?开车还需要了解汽车结构么?

这还真不能相比。

汽车很少坏,出了问题你会花钱给拖车公司、4S店。你还会每年给它买上保险。

反观Java,三天两头出问题,找人解决还找不到人,给钱都不一定能解决问题。能比么?盘点来盘点去,最后只能靠自己。

1.内存里都有啥
2.操作系统内存
3.JVM内存划分
4.一图解千愁,jvm内存从来没有这么简单过!
5.为什么会有内存问题
6.垃圾回收器
7.重要概念GC Roots
8.对象的提升
1.内存里都有啥
要想排查内存问题,我们就需要看一下内存里都有啥。我们先来看一下操作系统内存的划分,然后在来看一下JVM内存的划分。由于JVM本身是作为一个正常的应用运行在操作系统上的,所以它的行为同时会受到操作系统的限制。

2.操作系统内存

我们首先从操作系统的实现来说起。通常情况下,我们写了一个C语言程序,编译后,会发现里面的内存地址是固定的。其实我们的应用程序在编译之后,这些地址都是虚拟地址。它需要经过一层翻译之后,才能映射到真正的物理内存,MMU就是负责地址转换的硬件。

那我们操作系统的可用内存到底是多少呢?它其实是分为两部分的。一部分是物理内存,指的是我们插的那根内存条;另一部分就是使用磁盘模拟的虚拟内存,在Linux通常称做swap分区。所以,可用内存 = 物理内存 + 虚拟内存。如果你的系统开了swap,可用内存就比物理内存大。

通过top命令和free命令都可以看到内存的使用情况。

top命令可以看到每一个进程的内存使用情况,我们平常关注的是RES这一列,它代表的是进程实际的内存占用,我们平常在搭建监控系统的时候,监控的也是这个数值。

我们再来看一下free命令的展示。它的展示其实是有一些混乱的,具体的关系可以看上面的图。通常情况下,free显示的数值都是比较小的,但这并不等于系统的可用内存就那么一点点。Linux操作系统启动后,随着机器的运行,剩余内存会迅速被buffer和cache这些缓冲区和缓存迅速占满,而这些内存再应用的内存空间不足时,是可以释放的。可用内存 = free + buffers + cached。

具体每一个区域的内存使用情况,可以通过/proc/meminfo进行查看的。

cat /proc/meminfo

MemTotal: 3881692 kB
MemFree: 249248 kB
MemAvailable: 1510048 kB
Buffers: 92384 kB
Cached: 1340716 kB
40+ more …
3.JVM内存划分
接下来,我们才来看一下JVM的内存区域划分。

在JVM中,最大的内存区域就是堆,我们平常创建的大部分对象,都会存放在这里。所谓的垃圾回收,也主要针对的是这一部分。

多本JVM书籍描述:JVM中,除了程序计数器,其他区域都是可能溢出的。我们这里依然同意这个结论。下面仅对这些内存区域做简要的介绍,因为有些知识对我们的内存排查无益。

堆:JVM堆中的数据,是共享的,是占用内存最大的一块区域
虚拟机栈:Java虚拟机栈,是基于线程的,用来服务字节码指令的运行
程序计数器:当前线程所执行的字节码的行号指示器
元空间:方法区就在这里,非堆 本地内存:其他的内存占用空间

类比上面这张图,我们可以归位一些常用对象的分配位置。不要纠结什么栈上分配逃逸分析,也不用关注栈帧和操作数栈这种双层的结构,这些小细节对于对象的汪洋大海来说,影响实在是太小。我们关注的内存区域,其实就只有堆内内存和堆外内存两个概念。

4.一图解千愁,jvm内存从来没有这么简单过!
下面这篇文章,详细的讲解了每个区域。本来想要揉在一块,但怕突出不了它的重要性。所以开始直接读原文吧。

明星文章:《一图解千愁,jvm内存从来没有这么简单过!》

5.为什么会有内存问题
统计显示,我们平常的工作中,OOM/ML问题占比5%左右,平均处理时间却达到40天左右。这就可以看出这种问题的排查,是非常的困难的。

但让人无语的是,遇到内存问题,工程师们的现场保护意识往往不足,特别的不足。只知道一个内存溢出的结果,但什么都没留下。监控没有,日志没有,甚至连发生的时间点都不清楚。这样的问题,鬼才知道原因。

6.垃圾回收器
内存问题有两种模式,一种是内存溢出,一种是内存泄漏。

内存溢出 OutOfMemoryError,简称OOM,堆是最常见的情况,堆外内存排查困难。
内存泄漏 Memory Leak,简称ML,主要指的是分配的内存没有得到释放。内存一直在增长,有OOM风险;GC时该回收的回收不掉;或者能够回收掉但很快又占满,产生压力。
内存问题影响也是非常大的,比如下面这三种场景。

发生OOM Error,应用停止(最严重)
频繁GC,GC时间长,GC线程时间片占用高
服务卡顿,请求响应时间变长
说到这卡顿问题,就不得不提一嘴垃圾回收器。

很多同学一看上面的图,就知道我们要说G1垃圾回收器了,这也是我的推荐。CMS等垃圾回收器,回收时间不可控,如果你有条件,当然要避免使用,CMS也将要在Java14中被移除,我也真心不希望你掌握一些即将过时的经验。ZGC虽然厉害,但还太新,几乎没有人敢吃螃蟹,那剩下的就是G1了。

G1通过三个简单的配置参数,大部分情况下即可获取优异的性能,工程师幸福了很多。三个参数如下:

MaxGCPauseMillis 预定目标,自动调整。
G1HeapRegionSize 小堆区大小。
InitiatingHeapOccupancyPercent 堆内存比例阈值,启动并发标记。
如果你还是不放心,想要了解一下G1的原理,那我们也可以捎带提上两嘴。G1其实还是有年轻代老年代的概念的,只不过它的内存是不连续的。

如图所示,G1将内存切分成大小相等的区域,这些区域叫做小堆区,是垃圾回收的最小单位。以前的垃圾回收器都是整代回收,而G1是部分回收,那就可以根据配置的最小延迟时间合理的选取小堆区的数量,回收过程就显得智能了很多。

7.重要概念GC Roots
如图所示,要确定哪些是垃圾,就需要有一种找到垃圾的方法。其实,我们上一句的表述是不正确的。在JVM中,找垃圾的方法和我们理解的正好相反:它是首先找到存活的对象,对存活的对象做标记,然后把其他对象一股脑的回收掉。

JVM在垃圾回收时,关心的是不要把不是垃圾的对象给回收了,而不是把垃圾对象给清理的干干净净。

要找到哪些是存活对象,就需要从源头上追溯。在JVM中,常见的GC Roots就有静态的成员变量等,比如一个静态的HashMap。

另外一部分,就是线程所关联的虚拟机栈和本地方法栈里面的内容。

我们说了这老半天,其实这种追溯方式有一个专有的名词:可达性分析法。与之类似的还有引用计数法,但由于有环形依赖的问题,所以几乎没有回收器使用这种形式。

并不是说只要是和GC Roots有一条联系(Reference Chain),对象就是存活的,它还与对象的引用级别有关。

强引用:属于最普通最强硬的一种存在,只有在和GC Roots断绝关系时,才会被消灭掉
软引用:只有在内存不足时,系统则会回收软引用对象
弱引用:当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象
虚引用:虚引用主要用来跟踪对象被垃圾回收的活动
平常情况下,我们使用的对象就是强引用。软引用和弱引用在一些缓存框架中用的比较广泛,对象的重要程度也比较弱。

8.对象的提升
大多数垃圾回收器都是分代垃圾回收,我们从上面对G1的描述就能够看出来。

如图所示,是典型的分代回收内存模型。对象从年轻代提升到老年代,有四种方式。

常规提升,对象够老。比如从from到to转了15圈还没有被回收掉。控制参数就是-XX:MaxTenuringThreshold。这个值在CMS下默认为6,G1下默认为15
分配担保 Survivor 空间不够,老年代担保。
大对象直接在老年代分配
动态对象年龄判定。比如在G1里的TenuringThreshold会随着堆内对象的分布而变化
对于垃圾回收器的优化,就是要确保尽量多的对象在年轻代里分配,减少对象提升到老年代的可能。虽然这种思想在G1里弱化了许多。

End
了解了操作系统的内存里都有啥,又了解了JVM的内存里都有啥,我们就可以淡定纵容的针对于每一种出现问题的情况,进行针对性排查和优化。

文章到这里戛然而止。下一篇,我们以几个实际的案例,来看一下Java的内存问题排查的具体过程。

故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题 背景起因: 记起以前的另一次也是关于内存的调优分享下 有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡。 我按经验开始调优,在每个关键步骤的加入如下代码耗时统计进行压测: long startTime = System.currentTimeMillis(); callRpc();   //这里比如调用RPC伪代码,当然还在插入数据库,中间 阅读详情

相关推荐

使用JAVA 的 POI 库 将DOC文件转为DOCX文件

java使用POI库,将doc文件转为docx文件

qq_45808266的博客 5702

Java 每半年就会更新一次新特性,再不掌握就要落伍了:Java14 的新特性

本文讲解一下 Java14 的特性,这个版本带来了不少新特性、功能实用性的增强、GC 的尝试、性能优化等:JEP 305:instanceof 模式匹配 (预览版);JEP 343:打包工具 (孵化);JEP 345:G1 的可识别 NUMA 系统的内存分配;JEP 349:JFR 事件流;JEP 352:非原子性的字节缓冲区映射;JEP 358:NullPointerException 的友好提示信息;JEP 359:Record 声明 (预览版);JEP 361:Switch 表达式转正 (第二版预览)

沉潜飞动 1950

Qt OpenGL 3D 点云数据显示

在Qt中使用OpenGL显示3D点云数据是一个常见的需求,特别是在计算机视觉、机器人学和三维重建等领域。下面我将介绍一个基本的实现方案。

深之JohnChen的专栏 1238

我1万字,也讲Java不清内存排查。1万不行来2万~.~

本篇文章是《Java内存故障?只是因为你不够帅!》(opens new window)这篇文章的续篇。上篇侧重于理论,本篇侧重于实践。对于内存问题排查来说,搞理论的痛苦,搞实践的也痛苦,没有一片清净之地。 why?因为内存溢出是Java码农永远的伤。 溢出有很多种解释,有精满自溢,有缓冲区溢出攻击,还有另外一种叫做领导的溢出。不知道什么叫作溢出理论。 内存溢出什么最重要? 其实,内存溢出就像是一场交通事故。事故的发生方,就是具体的服务;事故的处理方,就是相关的程序员。其中有一个最重要的环节,...

LeZiJie的博客 243

Python实战:用MOOTDX库轻松抓取股票分时数据并绘制专业图表(附完整代码)

本文详细介绍了如何使用Python的MOOTDX库获取股票分时数据,并通过Pandas进行数据清洗与VWAP计算,最后利用Matplotlib绘制包含价格线、均线和成交量的专业分时图。文章提供了从环境搭建、数据获取到可视化呈现的完整代码,帮助读者快速构建本地化的股票分时数据分析工具。

weixin_29041195的博客 472

《iOS之一起进大厂》系列-秒杀面试官的RunLoop底层原理面试题

Runloop是iOS面试中的必考题,不管大厂小厂都会问到。 这里包括了Runloop几乎所有的面试题,还有中肯完整的答案解释。

空杯子 1151

Java应用部署时报错内存不足_故障重现, JAVA进程内存不够时突然挂掉模拟

背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下:# 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, t...

weixin_42620340的博客 1651

YOLOv8缺陷检测可视化界面实战:PyQt5布局设计与代码实现

本文详细介绍了如何利用PyQt5为YOLOv8缺陷检测模型构建一个专业、易用的可视化界面。通过实战讲解PyQt5的布局管理器设计、信号槽机制与YOLOv8核心的集成,帮助开发者快速将AI模型部署为直观的桌面应用,提升工业质检等场景的落地效率。

redis7keeper的博客 755

故障重现, JAVA进程内存不够时突然挂掉模拟

很简单,但很容易忽略,因为在启动JAVA进程时,服务器检查的是当前内存,并不是可用额度。如,服务器有1G内存,而启动了两个1G内存的JAVA服务是不会报错的,但当内存紧张时,linux会kill任意JAVA服务,造成影响。答: 因为日志是再进程尝试重启后产生, 当系统内存不足,系统kill掉进程,此时守护进程又尝试拉起进程,故产生了err日志。也是存活的,而且等待下一次垃圾回收,死去线程的内存将被回收,系统恢复。观察后发现, 知道JVM内存被榨干,这条JAVA线程已经被停止,但JAVA进程。

lmrylll的博客 1954

泛微Ecology9单点登录实战指南:从Token获取到页面跳转

本文提供了一份详尽的泛微Ecology9单点登录实战指南,重点解析了Token跳转式SSO的核心流程。内容涵盖从理解关键参数(如appid、loginid)与一次性Token机制,到通过代码示例演示如何正确调用接口获取Token,并详细说明了拼接不同场景跳转地址的完整规则与安全实践,旨在帮助开发者高效、稳定地实现业务系统与OA门户的无缝集成。

ol789012345的博客 1064

RT-DETR算法优化改进:Backbone改进 | HGBlock完美结合PPHGNetV2 GhostConv

GhostConv助力RT-DETR ,HGBlock与PPHGNetV2 GhostConv完美结合

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 2909

java内存满卡死_故障重现(内存篇1), JAVA进程内存不够时突然挂掉模拟

背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下:# 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=...

weixin_36270006的博客 1493

信贷模型域——清收阶段模型(贷后模型)

本文深入探讨了信贷模型域中的清收阶段模型(贷后模型),涵盖早期催收模型(C卡)、晚期催收模型、Best Time to Contact模型和回收模型。这些模型通过多维度数据输入,运用分类、回归和生存分析等建模方法,输出关键指标如还款概率、回收率等,广泛应用于银行、资产管理公司和催收外包公司,助力提升回款率、优化资源分配、降低催收成本,并融入贷后风控体系。

庄小焱 652

linux下java高内存故障排查

 搞Java开发的,经常会碰到下面两种异常: 1、java.lang.OutOfMemoryError: PermGen space 2、java.lang.OutOfMemoryError: Java heap space 要详细解释这两种异常,需要简单重提下Java内存模型。 (友情提示:本博文章欢迎转载,但请注明出处:hankchen,http://www.blogjava

God is Coder 585

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Java线上应用故障排查之一:高内存占用

Java线上应用故障排查之一:高内存占用 转载地址:http://www.blogjava.net/hankchen 搞Java开发的,经常会碰到下面两种异常: 1、java.lang.OutOfMemoryError: PermGen space 2、java.lang.OutOfMemoryError: Java heap space Java内存模型是描述Java程序中各变...

ja.rome 1万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

C++求解组原习题:IEEE754单精度浮点数32位表示与转换

IEEE754单精度浮点数采用1位符号、8位阶码和23位尾数的结构,通过偏移量127实现指数映射,并区分规格化、非规格化及特殊值。理解其二进制表示原理,有助于掌握计算机中浮点数的存储与精度特性。在C++中,利用union或memcpy进行类型双关,可高效提取符号、阶码和尾数,实现浮点数与32位整数的互转。这一技术广泛应用于计算机组成原理习题求解、底层调试及数值精度分析。本文围绕组原习题中Float型数据的IEEE754表示,提供完整的C++实现与手工验证方法。

weixin_34344403的博客 685

Java内存溢出故障案例及Linux内存机制探究

Java内存溢出故障案例及Linux内存机制探究

阳某的博客 1625

JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC 一条龙!

无论是哪家公司,都很重视高并发高可用的技术,重视基础,重视JVM。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。其实我写了这么多,只是我自己的总结,并不一定适用于所有人,相信经过一些面试,大家都会有这些感触。最后我整理了一些面试真题资料,技术知识点剖析教程,还有和广大同仁一起交流学习共同进步,还有一些职业经验的分享。《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》

2301_79655576的博客 1177
上一篇: 有的人还在玩 JDK7,JDK 15 却马上要来了!|新特性尝鲜
下一篇: 基于SpringBoot的车牌识别系统(附项目地址)
程序媛月下
博客等级 码龄7年 5262粉丝 462原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值