论坛首页 Java企业应用论坛

一个隐形的java int溢出

浏览 30446 次
该帖已经被评为良好帖
作者 正文
   发表时间:2011-08-30  
故事的背景:

     笔者最近在做一个类SNS的项目,其中使用了MongoDB进行Feed信息存储,并使用定时器删除过期信息。
     定时器的时间变量为60天,设定
     
     private long msgInvalidDue = 60 * 24 * 3600 * 1000;
   

故事的发生:
     在项目上线的某天,突然发现,2周前的数据丢失了,遍历了程序,没发现逻辑问题,甚至开始当心MongoDB造成的数据丢失(业内也是发生过的)。 笔者当时纠结啊~~
    但第二天又发现数据的丢失是持续而且有规律的,于是,焦点便集中到了“定时删除任务”。左查右查没发现问题,只能一步一步的进行跟踪调试。。。。

故事的结局:
     很难令人想象,问题就出现在msgInvalidDue这个long型常量上。按道理它的值应该是5184000000L的(表示60天的时间),但是它实际值却是 889032704(大约10天时间),why???? 居然是int在计算过程中的溢出~~~~太隐晦的bug了~~正确的写法
     
     private long msgInvalidDue = 60 * 24 * 3600L * 1000;

任意一个常量上加L,转long型就OK了,坑爹哇~~~这回真是阴沟里翻船了~~
  


    
   发表时间:2011-08-30  
哈哈,这种bug是挺难查的。不过可以借助一些工具来扫一下,比如findbugs,这样的bug应该可以避免。
0 请登录后投票
   发表时间:2011-08-30  
不知道什么时候也触发过此bug(最可能的是算时间: 24 * 60 * 60 * 1000).
所以现在一直习惯性的这样写:long l = 1L * XXX
0 请登录后投票
   发表时间:2011-08-30   最后修改:2011-08-30
这个bug经典,effective java 里面有讲到这一点,
Java的隐式转换确实问题很多。
1/4+3/4 =? 的问题虽然很基础,但是很重要。
类似的问题,算术计算方面的,谁来总结一下。
0 请登录后投票
   发表时间:2011-08-30  
java解惑里的谜题三也讲到了这个问题,以int运算来执行,运算完成后提升为long类型,但此时计算已溢出。
0 请登录后投票
   发表时间:2011-08-30  
又长见识了……这个问题还真没遇到……
0 请登录后投票
   发表时间:2011-08-30  
小问题大BUG,血的教训告诉我们...没事应该注视下基础
0 请登录后投票
   发表时间:2011-08-30  
前车之覆后车之鉴,LZ的教训值得铭记啊

PS:居然有人投新手贴,抱不平
0 请登录后投票
   发表时间:2011-08-30  
确实经典,看来要好好研究一下java虚拟机原理了。
0 请登录后投票
   发表时间:2011-08-30  
多谢楼主,小弟受教了…
在学习的时候会看到这样的例子之类的,但是在实际工作中很多时候容易忽略…
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics