线上故障分析
1 生产故障分级规范概要1.1 开篇1.2 事故等级定义1.2.1 故障等级定义1.2.2 故障报告模板示例1.2.3 故障响应处理机制1.2.4 思考2 生产故障原因和分类2.1 故障分类2.2 bug是可以完全避免的么?-了解2.3 经典故障示例-了解2.4 混沌工程简介3 生产故障定位和解决流程3.1 影响服务质量的因素3.1.1我们常常面对如下的业务场景3.1.2 资源依赖3.1.3 流量3.2 故障发现3.2.1 监控体系汇总3.3 线上排除故障3.3.1故障排除方法3.3.2 故障排除一般需要掌握的技能-工具篇3.3.2.1 IDEA 断点高阶1.window快捷键:2.断点类型与设置3.断点控制4.断点属性配置5.断点状态6.断点窗口操作7.stream流调试8.远程调试9.生产力建议1 生产故障分级规范概要
1.1 开篇
计算机是当今世界的命脉,你能看到的任何地方,计算机都在改变着世界,不论是传统的制造生产,医疗通讯。还是新兴的虚拟现实,无人驾驶汽车 等领域。过去的几十年,计算机硬件飞速发展,软件领域也是不断刷新着人们的想象。可以说,计算机学科复杂而且庞大,甚至有人说,不亚于物理学。
今天我们讨论的话题,线上事故分析,只是其中的一部分,一小部分,为了说清楚这一点,我们简单了解一下软件工程学科。
玛格丽特·希菲尔德·汉密尔顿(英语:Margaret Heafield Hamilton,1936年8月17日-[ 1])被认为发明了软件工程一词。
她帮助了NASA在阿波罗计划中避免了严重问题。她曾这样说:“有点像牙根管治疗:你总是拖到最后才做,但有些事可以预先做好,有点像预防性体验,只不过是预防软件出错”。
我们不妨简单总结如何开发一个大型的软件项目下:
1-基于面向对象的编程语言
2-容易使用的集成开发环境
3-文档和注释(程序员最讨厌的两件事,写注释给别人读,阅读别人没有写注释的代码😃)
4-构建管理和版本控制
5-质量保证测试(QUALITY ASSURANCE-QA)
每个软件从业者从写下第一行代码开始,就一刻不停地 和软件中的错误做斗争 开发和维护(修复缺
陷、确保资源充 足等保障软件运行的活动)是一对伴随软件运行而产生的双 热爱从零到一开发软件是
开发者的天性 看着自己编写的 软件完美运行,为其他 提供服务,一直是驱动开发者前进的动力。为了
更快更好地开发软件,我们不断改进开发方法和软件架构,但是开发者在使用新的方法和更复杂的架构
时,往往也会低估潜在的风险。
本课程话题,主要讨论质量测试上线后,运营环节期间的一些问题,当然,我们暂时并不界定事故的产
生到底是因为测试覆盖不全还是操作不当等,这某种程度体现着管理的方式问题。
1.2 事故等级定义
业务和产品的线上质量、是研发团队的生命线,也是支撑业务快速是错,小步跑的前置条件。
1.2.1 故障等级定义
故障等级定义,不同的业务形态,不同的公司团队,有不一样的划分标准,下表列举了一般常见的维度和标准
【1】核心数据定义
个人敏感信息:姓名、出生日期、身份证件号码、个人生物识别信息、住址、通信通讯联系方式、通信记录和内容、账号密码、财产信息、征信信息、行踪轨迹、住宿信息、健康生理信息、交易信息等。
用户画像:职业、经济、健康、教育、个人喜好、信用、行为等。
【2】系统级别定义
零级系统(P0):为公司核心业务服务的核心系统,一旦发生不可用会直接影响公司核心业务的业务连续性,对所有系统用户造成影响。
一级系统(P1):重点的业务系统,一旦发生不可用,影响核心业务的连续型,并造成大部分内部用户或外部用户不可使用此系统。
二级系统(P2):重要的业务系统,一旦发生不可用存在一定的业务可用性问题,但不会影响核心业务的业务连续性。
三级系统(P3):非核心的支撑系统,一旦发生故障不直接产生业务影响,但会影响少部分内部用户使用此系统。
【3】影响范围与故障等级
1.2.2 故障报告模板示例
模板参考
1.2.3 故障响应处理机制
如图所示,大体描述了一般生产故障的处理机制
故障发现:
1-客户投诉或者业务反馈,研发自我发现
2-监控报警:技术监控,业务监控
1.2.4 思考
为什么会发生这个问题?为什么测试阶段没有发现?为什么系统不能容错?能不能更早发现问题?解决过程能不能更快?怎样防止类似的事情发现?2 生产故障原因和分类
2.1 故障分类
代码bug:上线代码逻辑有问题,遇到特殊情况下,导致故障的情况操作不当:线上配置或资源配置错误,操作不当,比如启动顺序不合理,初始化脚本不对,语法生产数据隔离混用等系统级别软件bug:技术架构中使用到的任何OS,第三方类库,软件在特殊场景下,bug被处罚导致故障的情况。突发流量:热点或突发事件,引发的瞬时流量超过日常峰值或成倍增长,造成性能下降或功能不可用问题资源使用不均:整体产品线利用率不达标,但有些业务冗余度不足,导致资源不能正确合理使用容量预估不足:对个别业务核心池预估不足网络类:公网拥堵、丢包、专线、网络设备故障、ip被攻击(包括DNS被攻击)、IP被封、域名被封、网络软件BUG、业务部门使用不当、未及时扩容等安全类:被攻击,漏洞被利用等问题,均归为此类局方故障:ISP,根域名服务,电力,空调,光缆等外部单位故障导致的问题。硬件故障:任何硬件非人为原因损坏导致的故障均归为此类第三方合作公司或接口故障:项目依赖的第三方公司或接口故障2.2 bug是可以完全避免的么?-了解
日常项目里中,站在开发者的角度:
大多数程序员会花费70%-80%时间调试,而不是在写代码,虽然现在有很好的工具能极大帮助程 序员防止和解决错误另一个重要部分 给代码写文档
由于现在的需求越来越复杂,依赖的外部条件,技术组件也是越来越多,很多bug在所难免。但也有一些bug是不能被原谅的,所以养成良好的开发习惯,很重要。
【bug起源】:1945年9月9日,格蕾丝·赫柏(Grace Murray Hopper) 使用的Mark Ⅱ出现故障,导致工作无法进行。经过了近一天的检查,格蕾丝找到了故障的原因:继电器中有一只死掉的蛾子。蛾子被夹了出来。后来,”bug” (小虫) 和”debug” (除虫) 这两个本来普普通通的词汇成了计算机领域中特指莫明其妙的“错误”和“排除错误”的专用词汇而流传至今,而格蕾丝·赫柏也因此成了第一个发现“bug”的人。
另一方面,大名鼎鼎的 "千年虫"bug,也是由她带来的。当然,这也不全完全算作bug。
2.3 经典故障示例-了解
由软件Bug引发的18次重大事故 | 程序师 - 程序员、编程语言、软件开发、编程技术 ()
近年的CSDN600万用户信息泄露事件:CSDN网站六百万用户信息外泄-月光博客 (williamlong.info)
github服务中断24小时11分钟事件:GitHub服务中断24小时11分钟事故分析报告 ()
2.4 混沌工程简介
观念和思想来源于:【混沌工程】一书
说起混沌工程一次,也许你听过阿里的红蓝军对抗。
混沌工程是一种通过实验探究的方式来让我们理解系统行为的方法,就像科学家通过实验来研究物理和社会现象一样,混沌工程通过实验来了解特定的系统 如何使用混沌工程提高系统弹性呢?混沌工程通过设计 和执行一系列实验,帮助我们发现系统中潜在的、可以导致灾难的或让我们的用户受损的脆弱环节,推动我主动解决这些环节存在的问题 和现在各大公司主流的被动式故障响应流程相比,混沌工程向前迈进了一大步。
混沌工程解决的问题:
要设计良好的系统需要考虑很多因素,比如可靠性、安全 性、可扩展性、可定制化、可伸缩性、可维护性、用户体验等。 为了更高效地支撑业务发展,越来越多的企业选择基于云服务 或云原生理念来构建平台。采用新思路和新技术必然会带来系统架构和组织结构的变革,引入风险因素。
如何通过实验证明生产环境下的分布式系统在面对失控条件的时候依然具备较强的“可观测性”和故障恢复能力呢?这就是混沌工程要解决的问题。
混沌工程和测试的区别:
混沌工程故障注入和故障测试在侧重点和工具集的使用上有些重叠 举个例子, Netflix 的很多混沌工程实验的研究对象都是基于故障注入来引入的。
混沌工程和其他测试方法的主要区别在于,混沌工程是发现新信息的实践过程,而故障注 入则是基于一个特定的条件、变址的验证方法。
混沌工程和故障注人本质上是思维方式上的不同 。故障 注人首先要知道会发生什么故障,然后一个一个地注人, 而在 复杂分布式系统中,想要穷举所有可能的故障,本身就是奢望 混沌工程的思维方式是主动去找故障,是探索性的,你不知道摘 掉一个节点、关掉一个服务会发生什么故障,虽然按计划做好了 降级预案,但是关闭节点时却引发了上游服务异常,进而引发雪崩,这不是靠故障注人或预先计划能发现的
一些混沌实验的输入样例:
模拟整个云服务区域或整个数据中心的故障
部分删除各种实例上的Kafka主题。
重新创建生产中发生的问题。
针对特定百分比的交易服务之间注入一段预期的访问延迟。
基于函数的混乱(运行时注入):随机导致抛出异常的函数。
代码插入:向目标程序添加指令和允许在某些指令之前进行故障注入。
时间旅行:强制系统时钟彼此不同步。
在模拟I/O错误的驱动程序代码中执行例程。
在 Elasticsearch 集群上最大化CPU核心。
混沌工程实验的机会是无限的,可能会根据分布式系统的架构和组织的核心业务价值而有所不同
混沌工程实现的四个步骤:
1.定义并测量系统的“稳定状态”。
首先精确定义指标,表明您的系统按照应有的方式运行。 Netflix使用客户点击视频流设备上播放按钮的速率作为指标,称为“每秒流量”。请注意,这更像是商业指标而非技术指标;事实上,在混沌工程中,业务指标通常比技术指标更有用,因为它们更适合衡量用户体验或运营。
2.创建假设。与任何实验一样,您需要一个假设来进行测试。
因为你试图破坏系统正常运行时的稳定状态,你的假设将是这样的,“当我们做X时,这个系统的稳定状态应该没有变化。”为什么用这种方式表达?如果你的期望是你的动作会破坏系统的稳定状态,那么你会做的第一件事会是修复问题。混沌工程应该包括真正的实验,涉及真正的未知数。
3.模拟现实世界中可能发生的事情,目前有如下混沌工程实践方法:模拟数据中心的故障、强制系统时钟不同步、在驱动程序代码中模拟I/O异常、模拟服务之间的延迟、随机引发函数抛异常。通常,您希望模拟可能导致系统不可用或导致其性能降低的场景。首先考虑可能出现什么问题,然后进行模拟。一定要优先考虑潜在的错误。 “当你拥有非常复杂的系统时,很容易引起出乎意料的下游效应,这是混沌工程寻找的结果之一,”
“因此,系统越复杂,越重要,它就越有可能成为混沌工程的候选对象。”
4.证明或反驳你的假设。将稳态指标与干扰注入系统后收集的指标进行比较。如果您发现测量结果存在差异,那么您的混沌工程实验已经成功 - 您现在可以继续加固系统,以便现实世界中的类似事件不会导致大问题。或者,如果您发现稳定状态可以保持,那么你对该系统的稳定性大可放心。
引入混沌工程的一些建议:来源于-周洋(花名:中亭)-阿里巴巴高可用架构团队高级技术专家
第一,引入混沌工程,需要建立进行面向失败设计(可以 使系统暴露出已有问题的设计)和拥抱失败的技术文化
第二,实施混沌工程,需要定义一个清晰可衡量的目标。
第三,推广混沌工程,要在控制风险的前提下不断提升效率。
混沌工程是一种实践思想,其本身是不绑定任何技术或工具的。
减少问题的最好方法就是让问题经常性地发生,通过不断 重复失败过程并找出解决方案,来持续提升系统的容错能力和 弹性。
混沌工程工具
chaosblade-io/chaosblade: An easy to use and powerful chaos engineering experiment
toolkit.(阿里巴巴开源的一款简单易用、功能强大的混沌实验注入工具) ()
3 生产故障定位和解决流程
3.1 影响服务质量的因素
3.1.1我们常常面对如下的业务场景
大量无用业务逻辑sleep循环里写查询磁盘满了、影响到有磁盘写操作的接口慢查询的SQLRedis中存在大key,带宽打满不知是哪些接口影响与被影响队列堆积却不知哪些接口影响流量放大系数评估全靠经验和看代码3.1.2 资源依赖
接口依赖(内部服务、外部服务)无法整体查看服务、接口、资源之间的依赖关系
没有很好的外部服务监控机制、无法统计依赖的服务质量数据资源依赖(DB、Redis、Memcached、队列)
无法整体查看服务、接口、资源之间的依赖关系
容量评估及扩容标准全靠经验
出问题后仅能凭经验逐一排查、无法迅速定位到代码层面
完全依赖dba帮忙排查服务器资源依赖 (负载、内存、网络 ······)
资源指标上升后、无法判断数值是常规上升还是资源异常
3.1.3 流量
大流量来袭时、无法整体感知流量状况流量多大算大?
核心业务是否收到影响?
单一接口流量增加却未达到整体的告警线、导致无法感知
可视化是否实时无法直观统计流量分布、无法查看具体每个接口的流量情况容量评估时、流量放大系数全靠人为判断、对服务整体的放大系数无感知
3.2 故障发现
一个高可用的业务系统除了技术架构支撑之外,监控系统作为事中决策支撑和事后决策止损是必不可少的一部分
工具:Prometheus、Zabbix、Nagios、Open-Falcon、Pageduty等
3.2.1 监控体系汇总
监控体系分类:一般可分为:业务监控,系统级别监控,网络监控,程序代码监控,日志监控,用户行为分析监控,其他种类监控等
系统级别监控:主要跟操作系统相关的基本监控项
物理监控(对物理机或者容器的监控):存活、内存、cpu、load、硬盘(速率、使用率)、网络
活性检测:进程、端口
应用服务监控:jvm、gc、线程数
服务监控:rpc和http接口的qps、rt、错误码等
业务监控:包含用户访问的QPS,DAU,访问状态(http状态码),业务接口(登录,注册,聊天,送礼,留言,下单,支付,播放按钮点击率,搜索次数,好评差评数等等),产品转化率,充值额度,客诉等很宏观的概念
1-基础业务监控
交易运营数据
业务监控自定义数据
2-业务监控的发展
1-业务监控设置静态阈值无法满足要求
阈值应该配成多少,不同的业务甚至不同的时间段都需要不同的阈值
业务总是出现周期性的趋势,规则配置极易产生误报
特殊的业务场景例如活动引起的冲高回落、大促的冲击都会引起大量误报
对大量维度的业务,比如要监控外部千万级别的商户、上百个不同类型的错误码该如何配置
2-我们要根据业务特征和历史数据生成动态阈值,自动化报警,及时发现故障3-业界产品:
支付宝lego
阿里妈妈goldeneye
4-一般架构图
网络监控
IDC,对网络状态的监控(交换机、路由器、防火墙,vpn)对于一个互联网公司必不可少,但是有很多时候又被忽略:例如:内网之间(物理内网,逻辑内网),外网,丢包率,网络重传,延迟等等
日志监控
日志监控比较重要,所以一般单独管理和分类,日志不仅限于服务系统日志,对于很多专业化的运维工程师来说,需要采集的包括系统日志,设备日志,用户行为日志等等,后续可加工处理,(splunk,ELK)
常用监控图示
链路监控
中间件监控:
异常监控:
当前排除故障的流程
【项目背景】目前公司线上业务,经常遇到以下几种问题:
由于环境的隔离,导致无法从本地开发环境访问线上环境,故而遇到问题,无法使用IDE远程调试应用程序。为了线上业务的正常运作,所以不能在生产中调试,防止因调试导致所有线程不可用,从而影响线上业务。不同环境,参数不同,重现问题难。
一旦我们在生产中检测到问题,我们必须:
回滚到稳定版本。在日志和代码中搜索错误和异常。添加log日志,创建新的修补程序版本。提交测试,等待测试和发布(有可能数天)。部署预发,获取详细日志,验证问题。发布新版本到线上。
完成上述步骤,有的故障甚至持续数天,效率非常低下
故障诊断跟踪系统因此产生,其实纵观计算机科学的发展,也是需求促使着新技术不断被发明,又在一层一层的技术之上建立新的抽象。以京东的JEX平台为例
功能:
自动捕获程序中发生的异常事件自动保存异常发生时的完整调用栈(callstack)自动保存异常发生时的变量值自动关联相关源代码和变量
异常退栈:
JEX:
保存了异常的DEBUG 和TRACE信息
3.3 线上排除故障
3.3.1故障排除方法
上一节,我们有提到,故障排除的一般流程,不妨在此再次总结如下:
回滚到稳定版本。在日志和代码中搜索错误和异常。添加log日志,创建新的修补程序版本。提交测试,等待测试和发布(数天)。部署预发,获取详细日志,验证问题。发布新版本到线上。
另外,别忘了一个很重要的方法:重启服务
3.3.2 故障排除一般需要掌握的技能-工具篇
1-一般情况下,需要了解业务场景,千万不要第一时间着急解决bug,应先评断是否可以回滚,影响面大小,是否为上层提供服务,是否有数据异常。
2-应熟悉项目依赖的监控,学会看监控。
3-应熟练开发环境的断点排查与诊断,熟悉git,maven,idea的使用,分析如何复现线上故障。
4-线上排查故障的工具链(仅供参考)-随着课程慢慢补齐
3.3.2.1 IDEA 断点高阶
1.window快捷键:
所在行处: Ctrl+F8
断点属性编辑: Ctrl+Shift+F8
2.断点类型与设置
行断点(line breakpoints)
在到达设置断点的代码行时暂停程序。这种类型的断点可以设置在任何可执行的代码行上。该类型断点的图标:
字段断点(field breakpoints)
当指定的字段被读取或写入时暂停程序。这允许你对与特定实例变量的交互作出反应。例如,如果在一个复杂的过程结束时,你的某个字段出现了明显的错误值,设置一个字段观察点可能有助于确定故障的来源。该类型断点的图标:
鼠标右键点击该断点图标 ,弹出该断点配置,会有Field access和Field modification选项,此选项是字段类型断点特有的,分别对应访问该字段或修改该字段触发断点,两项同时选中,则访问与修改该字段都会触发断点。
方法断点(method breakpoints)
在进入或退出指定的方法或其实现之一时暂停程序,允许你检查该方法的进入/退出条件。
该类型断点的图标:当断点加在class类名这一行,且该类中没有编写构造函数(只有默认无参构造函数),当调用默认无参构造函数时会触发此断点,程序挂起,故该断点虽然图标是行断点类型图标,但实际上属于方 法类型断点。
鼠标右键点击该断点图标 ,弹出该断点配置,会有Emulated、Method entry、Method exit选项,此选项是方法类型断点特有的。Emulated勾选中,会将方法断点优化成方法中第一条和最后一条语句的行断点,这样会优化调试的性能,因此在IDE中会默认选中,通过匹配符批量添加方法断点,在断点列表页
匹配符示例:
异常断点(Exception breakpoints)异常断点分为两种,一种是Any Exception,任意Throwable异常被捕获或未被捕获就会触发断点,另一种是指定类型的异常及其该异常子类被捕获或未被捕获会触发断点,该类型断点图标鼠标右键点击该断点图标 ,弹出该断点配置,会有Caught exception和Uncaught exception选项,此选项是字段类型断点特有的,Caught exception选项选中时,当指定的异常被捕获时,触发断点程序挂起,Uncaught exception选中时,当指定的异常未被捕获时,触发断点程序挂起
3.断点控制
断点删除
1-所有类型断点:断点设置中移除对应的即可。
2-快捷移除:行位置鼠标左键单击即可移除(异常断点除外)
建议:为了避免意外删除断点并丢失其参数,通常选择点击鼠标中键来删除断点。要做到这一点,请进入 “设置/首选项”|“构建、执行、部署”|“调试器”,选择 "拖到编辑器 "或用鼠标中键点击。点击一个断点将启用或禁用它。
断点静音
如果某些时候不需要在断点处停留一段时间,可以将断点静音。这样就可以在不离开调试器会话的情况下恢复正常的程序操作。之后,可以解除中断点的静音,继续调试。断点静音会静音所有断点
在断点调试窗口,点击断点静音按钮
启用/禁用断点
正常 通过 断电删除 的断点,会连同当时断点的内部所有配置一并删除。如果想暂时关闭一个断点,后续可能还会使用,这是一个很好的选择
同断点删除操作
断点移动/复制
断点移动:鼠标左键拖动
断点复制:按住ctrl,鼠标左键拖动
4.断点属性配置
鼠标操作:右键断点:More(Ctrl+Shift+F8)
快捷键:Ctrl+Shift+F8
快捷键:光标所在行 Alt+Enter
断点有许多属性配置,如下图所示,下面将会对各个属性的作用以及使用进行说明。
Enabled
表示是否启用该断点,选中表示启用,取消选中表示不启用。
Supend
当断点的 Suppend 属性被勾选,触发该断点时,会触发程序挂起,当该属性未选中时,程序触发该断点时,程序不会挂起,常用于输出一些表达式结果日志。当断点的 All 属性被勾选,触发该断点时,会挂起所有线程当断点的 Thead 属性被勾选,触发该断点时,只会挂起触发该断点的那个线程,不影响其他线程当需要在不暂停程序的情况下记录一些表达式时(例如,需要知道一个方法被调用了多少次时),或者需要创建一个主断点,在击中后启用附属断点时,非暂停性断点是非常有用的。
实际生产实践中,可用于调试多线程并发的问题
Condition
可以输入一段能获得true或false的表达式,程序运行到断点处,且表达式条件为true才会触发断点
Log
下面三个属性选项经常配合 Suppend 属性一起使用,用于在不挂起的情况下,输出一些想要的日志信 息Breakpint hit message :控制台输出触发端点的日志信息,类似如: Breakpoint reached at
ocean.Whale.main(Whale.java:5)Stack trace :输出触发断点时的堆栈信息Evaluate and log :计算表达式结果并输出表达式结果到控制台,表达式的计算基于断点所在行的上下文,表达式的语句可以是字符串字面量,如 “我是字符串” ,也可以是方法调用,如 users.size(),也可以是多行语句块,表达式的结果取自return语句,如果没有return语句,会取 表达式中的最后一行语句。
Remove once hit是否在断点触发后移除该断点,后续不在触发
Disable until hitting the following breakpoint
指定在另一个断点触发后,该断点才启用,若该断点启用后,并且被触发,
场景:当只需要在某些条件下或某些操作后暂停程序时,这个选项很有用。在这种情况下,触发断点通常不需要停止程序的执行,而是做成非暂停状态。
Filters
前边说的大都数属性,都只针对方法程序运行上下文。此属性更多关注通过过滤掉类、实例和调用者方法来微调断点操作,只在需要时暂停程序。,有如下几种过滤方式:
Catch class filters :此选项只对异常类型的断点可用,可以让程序只在指定类和子类中抛出的异常才会触发断点或者不在指定的类和子类中触发断点(即排除一些类,排除通常以 - 开始,例 如 -pacakge.ClassName ),Instance filters :只有指定实例id号可以触发断点,多个实例id号以逗号隔开,实例id号可以在Variables和Memory面板中查看Class filters :可以让程序只在指定类和子类中才会触发断点或者不在指定的类和子类中触发断 点(即排除一些类)。Caller filters :根据调用者来进行过滤,需指定方法的全限定名(包含方法签名),例如
mypackage.MyObject.addString(Ljava/lang/String;)V
Pass count
勾选中并输入一个正整数N,N>=1,那么程序会每N次命中断点才会触发挂起,如果同时设置了condition 与 pass count 属性,ide会优先判断 condition 表达式,再判断 pass count 是否满足,下例中, pass count 中传入的是15,每15次命中断点才会触发断点,挂起程序
5.断点状态
图标:
6.断点窗口操作
7.stream流调试
8.远程调试
1-打开Idea的 Run/Debug Configurations 新增一个Remote
JVM参数添加 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
2-远程项目启动添加参数
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar xxx.jar
3-idea启动remote,并打断点调试
9.生产力建议
使用断点进行 "printf "调试
使用非暂停的日志断点,而不是在代码中插入打印语句。这为处理调试日志信息提供了一种更灵活和集中的方式。
场景:
所有需要打印的地方,生产上禁止 System.out.print();
调试无响应的应用程序
如果你的应用程序挂起,暂停会话,让调试器获得关于其当前状态的信息。然后你可以检查程序的状态并找出问题的原因。
场景:
项目启动卡死等处理
测试你的程序是否有并发性问题
发现多线程程序在并发方面是否健壮的一个好方法是使用断点,在碰到时只暂停一个线程。停止一个线程可能会揭示出应用程序设计中的问题,否则这些问题就不会显现出来。
计算保留的大小
对于每个类的实例,你可以计算它的保留大小。保留大小是指对象本身和它所引用的所有对象以及没有被其他对象引用的对象所占据的内存量。
这在估算重型单体或从磁盘上读取的数据(例如,复杂的JSON)的内存占用时,可能很有用。另外,在决定使用哪种数据结构时(例如,ArrayList与LinkedList),这也很有用。
在运行应用程序之前,确保在设置/首选项|构建、执行、部署|调试器中启用附加内存代理选项。
在查看类的实例时,右键单击一个实例并单击计算保留大小。