`
linliangyi2007
  • 浏览: 1003558 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

一个隐形的java int溢出

阅读更多
故事的背景:

     笔者最近在做一个类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了,坑爹哇~~~这回真是阴沟里翻船了~~
  


    
分享到:
评论
11 楼 lanmingle 2015-05-18  
我不知道你们有没有这样的习惯,如果我写的常量是long的,我必定没有一个都写后缀.
long a = 10L * 100L ...

反正我以前看到书上说自动转型总是会有意想不到的错误,所以我就规范自己.
10 楼 幽蓝星空 2015-01-22  
“任意一个常量上加L”这样总结是有问题的!
60 * 24 * 3600 * 1000=889032704
60 * 24 * 3600L* 1000=5184000000
60 * 24 * 3600 * 1000 * 1L=889032704

因为java中乘法的计算是左结合的!
9 楼 雁行 2013-08-05  

哈哈,我说呢,明明没有超出范围却溢出了
8 楼 looly 2013-06-13  
试验过了,Eclipse里不报错。不过确实是个大坑啊~
7 楼 gezhonglei2007 2012-05-17  
呵呵,这种小问题真的纠结。估计也没有太多人在意数据的范围了!!!推荐一本书,专门罗列类似这种问题、往往又是最基础的东西 的这么一本书——《Java解惑》
6 楼 pppqqq800 2012-02-08  
最近看think in java  发现里面提到了这个问题、。
5 楼 gougou851129 2011-12-30  
这是类型转换的错误 如果不写会先计算成int 然后转成long int的大小还是不够的
4 楼 linliangyi2007 2011-09-30  
store88 写道
不写L的话,ecllipse会报错的


你太自作聪明的,实验一下吧
3 楼 zhengchao860730 2011-09-28  
store88 写道
不写L的话,ecllipse会报错的

好像不会报错。 但是确实会有如此BUG。
2 楼 亦梦亦真 2011-09-06  
store88 写道
不写L的话,ecllipse会报错的

像老师这样的老程序员,应该不是很喜欢用eclipse的
1 楼 store88 2011-08-31  
不写L的话,ecllipse会报错的

相关推荐

Global site tag (gtag.js) - Google Analytics