当前位置: 首页 > news >正文

java中double强制转换int引发的OOM问题

java中double强制转换int引发的OOM问题

    • 问题代码
    • 排查过程
    • double特殊值与强制转换
      • NaN
      • Infinity

问题代码

最近出现了一次OOM问题,问题代码如下

public void prcess(double total, int step) {int num = (int) Math.floor(total / step);while (num-- > 0) {doSomething(); // 普通方法,占用内存不大}
}

根据单步步长step将total值划分后,然后进行处理。然后日志中发现堆栈在doSomething()时报错OOM,抛出java.lang.OutOfMemoryError。确认过doSomething()方法不会占用过大的内存,那为何会发生问题?

排查过程

怀疑num过大导致,查看入参total为合理值,但是step是取配置值,配置未配置时默认为0,则问题代码为int num = (int) Math.floor(total / step);,这里step为0,Math.floor(total / step) = Infinity,强制转为int后得到值为2147483647。一直在处理此处的逻辑导致内存增长,进而发生OOM

double特殊值与强制转换

java语言中浮点运算存在两个值:NaN与Infinity

NaN

Not-a-Number,非数字值,数学上0/0是无意义的,java在浮点运算中实现了NaN,定义为0.0/0.0。NaN有如下几个特点:

  1. NaN与任何数字都不相等,NaN与其本身也不相等

    System.out.println(Double.NaN == Double.NaN); // false
    System.out.println(Double.NaN == 0.0/0.0); // false
    System.out.println(Double.NaN == 0.0); // false
    
  2. 使用Double.isNaN或Float.isNaN确认是否为NaN

    System.out.println(Double.isNaN(0.0/0.0));  // true
    System.out.println(Float.isNaN(0.0f/0.0f));  // true
    
  3. NaN与任何数字比较都是false

    System.out.println(Double.NaN > 0.0); // false
    System.out.println(Double.NaN < 0.0); // false

Infinity

无限,分为正无限与负限小,定义为一个非0数字除以0。

有如下几个特点:

  1. 正无限与负无限定义

    public static final double POSITIVE_INFINITY = 1.0 / 0.0;
    public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
    
  2. 无限与任何非无限非0数字运算仍为无限

    System.out.println(Double.POSITIVE_INFINITY + Double.MAX_VALUE); // Infinity
    System.out.println(Double.POSITIVE_INFINITY - Double.MAX_VALUE); // Infinity
    System.out.println(Double.POSITIVE_INFINITY * Double.MAX_VALUE); // Infinity
    System.out.println(Double.POSITIVE_INFINITY / Double.MAX_VALUE); // Infinity
    System.out.println(Double.NEGATIVE_INFINITY + Double.MIN_VALUE); // -Infinity
    System.out.println(Double.NEGATIVE_INFINITY - Double.MIN_VALUE); // -Infinity
    System.out.println(Double.NEGATIVE_INFINITY * Double.MIN_VALUE); // -Infinity
    System.out.println(Double.NEGATIVE_INFINITY / Double.MIN_VALUE); // -Infinity
    
  3. 无限与0运算为无限或NaN

    System.out.println(Double.POSITIVE_INFINITY / 0); // Infinity
    System.out.println(Double.POSITIVE_INFINITY * 0); // NaN
    System.out.println(Double.NEGATIVE_INFINITY / 0); // -Infinity
    System.out.println(Double.NEGATIVE_INFINITY * 0); // NaN
    
  4. 负无限与正无限运算为无限或NaN

    System.out.println(Double.POSITIVE_INFINITY + Double.NEGATIVE_INFINITY); // NaN
    System.out.println(Double.POSITIVE_INFINITY - Double.NEGATIVE_INFINITY); // Infinity
    System.out.println(Double.NEGATIVE_INFINITY + Double.POSITIVE_INFINITY); // NaN
    System.out.println(Double.NEGATIVE_INFINITY - Double.POSITIVE_INFINITY); // -Infinity
    System.out.println(Double.POSITIVE_INFINITY * Double.NEGATIVE_INFINITY); // -Infinity
    System.out.println(Double.POSITIVE_INFINITY / Double.NEGATIVE_INFINITY); // NaN
    System.out.println(Double.NEGATIVE_INFINITY * Double.POSITIVE_INFINITY); // -Infinity
    System.out.println(Double.NEGATIVE_INFINITY / Double.POSITIVE_INFINITY); // NaN
    
  5. 无限强制转换为整形会有精度丢失

    System.out.println((int)Double.POSITIVE_INFINITY); // Integer.MAX_VALUE
    System.out.println((int)Double.NEGATIVE_INFINITY); // Integer.MIN_VALUE
    System.out.println((long) Double.POSITIVE_INFINITY); // Long.MAX_VALUE
    System.out.println((long)Double.NEGATIVE_INFINITY); // Long.MIN_VALUE
    

http://www.mrgr.cn/news/56654.html

相关文章:

  • SQL 干货 | SQL 半连接
  • YOLOv11模型改进-注意力-引入单头自注意力Single-Head Self-Attention(SHSA)解决小目标、遮挡
  • 双链表的操作
  • 音视频入门基础:FLV专题(15)——Video Tag简介
  • 第一章 初识Mybatis
  • SpringBoot实现mysql多数据源配置(Springboot+Mybatis)
  • 大厂物联网(IoT)高频面试题及参考答案
  • AIGC文本生成视频
  • Python中的isinstance和hasattr
  • 【使用Flask构建RESTful API】从零开始开发简单的Web服务!
  • 追寻数组的轨迹,解开算法的情愫
  • Python语法基础:复数
  • 【在Linux世界中追寻伟大的One Piece】Socket编程UDP
  • 道可云人工智能元宇宙每日资讯|上海市互联网业联合会人工智能专业委员会成立
  • 上海亚商投顾:沪指缩量震荡 风电、传媒股集体走强
  • 大语言模型及其应用场景
  • 数据集笔记:北京市摩拜数据(摩拜杯算法挑战赛)
  • 【2024工业图像异常检测文献】GLASS: 基于全局和局部异常共合成策略的异常检测方法
  • 配置linux网络的操作步骤(grub,nmcli)
  • ARM架构流派
  • 【日志】Unity3D模型导入基本问题以及浅谈游戏框架
  • 吃透高并发模型与RPC框架,拿下大厂offer!!!
  • Java应用程序的测试覆盖率之设计与实现(四)-- jacoco-maven-plugin
  • Vue学习笔记(五、v-on指令)
  • Golang | Leetcode Golang题解之第501题二叉搜索树中的众数
  • 《Windows PE》9.2 动态加载技术-获取kernel32.dll基址