异常堆栈缺失与OmitStackTraceInFastThrow

目录

  • 现象
  • 原因
  • OmitStackTraceInFastThrow
  • 源码层面分析OmitStackTraceInFastThrow
  • 阈值是多少
  • 源码
    • 源代码
    • 解释

现象

异常没有堆栈信息。只有短短的异常类信息,例如java.lang.NullPointerException。

完整的异常堆栈示例:

java.lang.NullPointerExceptionat fileop.ExceptionTest.testF(ExceptionTest.java:21)at fileop.ExceptionTest.testB(ExceptionTest.java:38)at fileop.ExceptionTest.lambda$main$0(ExceptionTest.java:66)at java.util.concurrent.FutureTask.run(FutureTask.java:266)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)

原因

JDK5中引入了-XX:-OmitStackTraceInFastThrow这个参数,可以关闭掉该行为,具体可以看release note.

The compiler in the server VM now provides correct stack backtraces
for all “cold” built-in exceptions. For performance purposes, when
such an exception is thrown a few times, the method may be recompiled.
After recompilation, the compiler may choose a faster tactic using
preallocated exceptions that do not provide a stack trace. To disable
completely the use of preallocated exceptions, use this new flag:
-XX:-OmitStackTraceInFastThrow.

OmitStackTraceInFastThrow

OmitStackTraceInFastThrow是JVM的一个参数,它的作用是省略异常栈信息以快速抛出异常。当检测到在代码中连续多次抛出同一类型的异常时,JVM会使用Fast
Throw方式来抛出异常,异常的详细栈信息会被清空。这种异常抛出方式非常快,因为它不需要在堆里分配内存,也不需要构造完整的异常栈信息。

这个参数的优化对于提高性能非常有用,特别是在频繁抛出同一类型异常的情况下。这个优化在JIT编译时开启,并且在使用-server模式时,该优化选项是默认开启的。

源码层面分析OmitStackTraceInFastThrow

源码层面的OmitStackTraceInFastThrow的实现涉及到了JVM的核心部分,具体的位置在HotSpot虚拟机中的src/share/vm/interpreter/InterpreterRuntime.cpp文件中。

当一个异常被抛出时,JVM会调用InterpreterRuntime::throw_exception()函数,该函数会检查异常是否已经被抛出过,如果是,则调用OmitStackTraceInFastThrow。

在OmitStackTraceInFastThrow的实现中,首先会检查是否满足以下两个条件:

  1. 异常类型相同;
  2. 抛出异常的次数超过了阈值。

如果满足条件,就会跳过异常栈信息的构造,直接抛出异常。否则,就会正常抛出异常,并保留异常的栈信息。

这个实现的原理就是通过优化异常的抛出方式,提高性能。在异常被频繁抛出的情况下,OmitStackTraceInFastThrow可以有效地减少不必要的内存分配和栈信息构造,从而提高程序的运行效率。

阈值是多少

OmitStackTraceInFastThrow的阈值是由JVM参数-XX:FastUnwindLimit来控制的,默认值为4。这个参数表示在抛出异常之前,可以连续执行的字节码指令的数量。当超过这个阈值时,才会构造异常的详细栈信息。

源码

源代码

github地址

void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {bool must_throw = true;// If this particular condition has not yet happened at this// bytecode, then use the uncommon trap mechanism, and allow for// a future recompilation if several traps occur here.// If the throw is hot, try to use a more complicated inline mechanism// which keeps execution inside the compiled code.bool treat_throw_as_hot = false;ciMethodData* md = method()->method_data();if (ProfileTraps) {if (too_many_traps(reason)) {treat_throw_as_hot = true;}// (If there is no MDO at all, assume it is early in// execution, and that any deopts are part of the// startup transient, and don't need to be remembered.)// Also, if there is a local exception handler, treat all throws// as hot if there has been at least one in this method.if (C->trap_count(reason) != 0&& method()->method_data()->trap_count(reason) != 0&& has_ex_handler()) {treat_throw_as_hot = true;}}// If this throw happens frequently, an uncommon trap might cause// a performance pothole.  If there is a local exception handler,// and if this particular bytecode appears to be deoptimizing often,// let us handle the throw inline, with a preconstructed instance.// Note:   If the deopt count has blown up, the uncommon trap// runtime is going to flush this nmethod, not matter what.if (treat_throw_as_hot&& (!StackTraceInThrowable || OmitStackTraceInFastThrow)) {// If the throw is local, we use a pre-existing instance and// punt on the backtrace.  This would lead to a missing backtrace// (a repeat of 4292742) if the backtrace object is ever asked// for its backtrace.// Fixing this remaining case of 4292742 requires some flavor of// escape analysis.  Leave that for the future.ciInstance* ex_obj = NULL;switch (reason) {case Deoptimization::Reason_null_check:ex_obj = env()->NullPointerException_instance();break;case Deoptimization::Reason_div0_check:ex_obj = env()->ArithmeticException_instance();break;case Deoptimization::Reason_range_check:ex_obj = env()->ArrayIndexOutOfBoundsException_instance();break;case Deoptimization::Reason_class_check:if (java_bc() == Bytecodes::_aastore) {ex_obj = env()->ArrayStoreException_instance();} else {ex_obj = env()->ClassCastException_instance();}break;default:break;}

解释

这段代码是Java虚拟机(JVM)的一部分,更具体地说,是GraphKit类中的builtin_throw函数。这个函数是用来处理内置的异常抛出的。

首先,函数接受两个参数:一个表示异常原因的枚举值(Deoptimization::DeoptReason
reason),另一个是要抛出的异常参数(Node* arg)。

然后,函数检查是否需要抛出异常。它首先检查是否启用了ProfileTraps,如果启用了,并且对于特定的异常原因,抛出的陷阱计数达到了某个阈值,或者存在异常处理程序,那么就会将treat_throw_as_hot设置为true。

接着,如果treat_throw_as_hot为true,并且满足特定的条件(在Throwable中没有堆栈跟踪或者启用了忽略堆栈跟踪的选项),那么就会使用预先创建的异常对象来抛出异常。具体使用哪个异常对象,取决于异常原因。例如,如果原因是null检查,那么就使用NullPointerException的实例。

这段代码主要用于优化异常处理,特别是对于频繁发生的特定异常,通过一些特定的优化策略来减少处理成本。例如,对于某些特定的异常,会预先创建好对应的异常对象,当发生这种异常时,直接使用预先创建好的对象,避免创建新的对象带来的开销。同时,还可以避免在每次抛出异常时都需要生成和记录堆栈跟踪信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/41047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬虫逆向实战(十六)--某建筑市场平台

一、数据接口分析 主页地址:某建筑市场平台 1、抓包 通过抓包可以发现数据接口是list 2、判断是否有加密参数 请求参数是否加密? 无请求头是否加密? 无响应是否加密? 通过查看“响应”模块可以发现,返回的响应是…

MAUI+Blazor:windows 打包踩坑

文章目录 前言MSIX安装文件如何发布选择Windows平台旁加载自定义签名版本号安装 总结 前言 最近打算研究一下MAUIBlazor,争取在今年年底之前彻底搞懂MAUIBlazor的安装模式, MSIX安装文件 Windows 4种安装程序格式MSI,EXE、AppX和MSIX优缺点…

Java常用API---快速达到Java工作水准系列(1)

目录 1.集合 2.包装类 3.日期处理以及格式化 4.字符串处理类 5.数组 5.BigDecimal 6.Math 1.集合 毋庸置疑,集合在实际项目的使用概率几乎是百分之百。无论是用于数据存储和管理、去重和查找亦或是数据检索和遍历,都离不开集合的使用。任何一个项…

Spring Cloud Gateway系例—参数配置(CORS 配置、SSL、元数据)

一、CORS 配置 你可以配置网关来控制全局或每个路由的 CORS 行为。两者都提供同样的可能性。 1. Global CORS 配置 “global” CORS配置是对 Spring Framework CorsConfiguration 的URL模式的映射。下面的例子配置了 CORS。 Example 77. application.yml spring:cloud:gat…

【【STM32----I2C通信协议】】

STM32----I2C通信协议 我们会发现I2C有两根通信线: SCL和SDA 同步 半双工 带数据应答 支持总线挂载多设备(一主多从,多主多从) 硬件电路 所有I2C设备的SCL连在一起,SDA连在一起 设备的SCL和SDA均要配置成开漏输出模式 …

5.Vue_Element

文章目录 1 Ajax1.1 Ajax介绍1.1.1 Ajax概述1.1.2 Ajax作用1.1.3 同步异步 1.2 Axios1.2.1 Axios的基本使用1.2.2 Axios请求方法的别名 2 前端工程化2.1 前端工程化特点2.2 Vue项目开发流程 3 Vue组件库Element3.1 Element介绍 1 Ajax 1.1 Ajax介绍 1.1.1 Ajax概述 Ajax: 全…

【Unity游戏开发】基于前缀树的红点系统构思与客户端方案

一、前言 前段时间负责了项目中红点系统的实现,和大家分享一下初期是设计思路 红点系统客户端业务的一般实现过程与方式: 数据管理:首先要在客户端建立一个数据管理系统,用于存储和管理各个业务模块的红点状态。可以是一个中央数据管理器或模块化的数据管理系统,具体根据游…

VUE中babel.config.js配置按需引入

VUE中babel.config.js配置 vue/cli-plugin-babel/preset是一款 babel 插件,它会在编译过程中将 import 引入自动转换为按需引入的方式。 module.exports {presets: [vue/cli-plugin-babel/preset],plugins: [[import, {libraryName: element-ui,libraryDirectory…

系统架构设计师---多媒体技术及其应用

概念 媒体:承载信息的载体。 多媒体:数字、文字、声音、图形、图像和动画等各种媒体的有机组合,并与先进的计 算机、通信和广播电视技术相结合,形成一个可组织、存储、操纵和控制多媒体信息的集成环境和 交互系统。 多媒体技术:以数字化为基础,能够对多…

召集令:CloudQuery 社区有奖征文活动来啦!

CloudQuery 社区第一期征文活动来袭!!!只要你对 CloudQuery 产品感兴趣,或者是希望了解 CQ ,都可以来参加,在本期活动中,我们也为大家准备了多种主题供你选择,CQ 使用案例、版本对比…

udp与can通信的选择与比较

UDP(用户数据报协议)和CAN(控制器局域网)是两种不同的通信协议,它们在实时传递性上有一些区别。 UDP是一种无连接的传输协议,它提供了简单的、不可靠的数据传输。UDP不提供可靠性保证、流控制或重传机制。…

EMO实战:使用EMO实现图像分类任务(一)

文章目录 摘要安装包安装timm安装 grad-cam安装einops 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 论文翻译:https://blog.csdn.net/m0_47867638/article/details/132034098?spm1001.2014.3001.5501 官方源码:https://github.com/…

shell的两种属性: 交互(interactive)与登录(login)

1. 背景 在看shell变量的时候引起了兴趣: 局部变量,全局变量,环境变量,shell的配置文件,参考博客: http://c.biancheng.net/view/773.html 2. 交互式与非交互式 参考博客: shell的两个属性:是否交互式(interactive), 是否登录…

生产环境下的终极指南:使用 Docker 部署 Nacos 集群和 MySQL

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

01-集群安装JDK(普通用户)

机器部署 集群规划 我们准备三台服务器kk01、kk02、kk03,内存4G、硬盘50G、处理器4核心2内核(总8) kk01使用 192.168.188.128 kk02使用 192.168.188.129 kk03使用 192.168.188.130 模板机准备 我们先创建一台作为模板机,后…

C++ 11 新特性 学习笔记

1、字符串原始字面量 R“()”用于取消转义,可用于路径表示 运行成功 这两个RawValue起到描述作用(可以不写),并不参与输出 注意,这里输出中文乱码 2、nullptr NULL在C中表示0,在非C中表示万能指针 nullpt…

Vue3 使用json编辑器

安装 npm install json-editor-vue3 main中引入 main.js 中加入下面代码 import "jsoneditor";不然会有报错&#xff0c;如jsoneditor does not provide an export named ‘default’。 图片信息来源-github 代码示例 <template><json-editor-vue class…

SQL | 分组数据

10-分组数据 两个新的select子句&#xff1a;group by子句和having子句。 10.1-数据分组 上面我们学到了&#xff0c;使用SQL中的聚集函数可以汇总数据&#xff0c;这样&#xff0c;我们就能够对行进行计数&#xff0c;计算和&#xff0c;计算平均数。 目前为止&#xff0c…

ESP-C3入门21. I2C接口点亮1306驱动的OLED屏

ESP-C3入门21. 点亮1306驱动的OLED屏 一、Espressif/ssd1306 驱动简介1. 驱动介绍2. OLED充电泵概念 二、I2C 通讯步骤1. 初始化 I2C 总线 (i2c_master_init()函数)&#xff1a;2. 创建 I2C 命令句柄 (i2c_cmd_handle_t cmd i2c_cmd_link_create())&#xff1a;3. 发送启动信号…

【C#】获取电脑CPU、内存、屏幕、磁盘等信息

通过WMI类来获取电脑各种信息&#xff0c;参考文章&#xff1a;WMI_04_常见的WMI类的属性_wmi scsilogicalunit_fantongl的博客-CSDN博客 自己整理了获取电脑CPU、内存、屏幕、磁盘等信息的代码 #region 系统信息/// <summary>/// 电脑信息/// </summary>public p…