转的一个jdk bug

转载 2006年06月13日 09:05:00

原文:http://tb.blog.csdn.net/TrackBack.aspx?PostId=776965

Joshua Bloch, 获得过Jolt最畅销奖的《Effective Java》的作者, 是Sun Microsystems的杰出工程师和Transarc的资深系统设计师, J2SE 5.0 Tiger的代言人和领路人, 也是还是JSR166的发起人之一..

后来, Joshua Bloch去了Google, 成为了Google的首席工程师

Joshua Bloch拥有卡耐基.梅隆大学(CMU)计算机科学的博士学位。

在最近Joshua Bloch的一篇文章里, Joshua Bloch回忆了当年在CMU上课的时候, vividly Jon Bentley 第一节算法课, 就要求所有刚进来的PHD学生, 每人都写一个二分查找算法. 然后发现, 多数人的算法都存在BUG, 这在当时给了Joshua Bloch 一个很深的印象..

在之后, Joshua Bloch 负责java.util.Arrays 代码编写的时候, 采用了Bentley 在<<Programming Pearls >>一书中的二分查找算法, 结果在8年后的今天, Joshua Bloch 发现, 这里面原来还是有一个BUG.

问题到底是出在哪里? 竟然逃过了Bentley 和Joshua Bloch 的双重检测?

一起来看看java.util.Arrays的代码:

1:     public static int binarySearch(int[] a, int key) {
2:         int low = 0;
3:         int high = a.length - 1;
4:
5:         while (low <= high) {
6:             int mid = (low + high) / 2; //jdk1.5:int mid = (low + high) >> 1;
7:             int midVal = a[mid];
8:
9:             if (midVal < key)
10:                 low = mid + 1;
11:             else if (midVal > key)
12:                 high = mid - 1;
13:             else
14:                 return mid; // key found
15:         }
16:         return -(low + 1);  // key not found.
17:     }


这是很经典的一个二分查找算法.

bug出现在第6行:

6:             int mid =(low + high) / 2;

在一般情况下, 这个语句是不会出错的, 但是, 当low+high的值超过了最大的正int值 (231- 1) 的时候, mid会变成负值,  这个时候, 会抛出ArrayIndexOutOfBoundsException 异常.


所以当一个数组包含超过2的30次方 个元素的时候, 就很可能会带来问题... 当然, 在一般的应用里面, 很少数组会包含那么多元素, 但是现在这样的情况已经越来越多了, 比如Google的海量运算..

那如何解决这个问题?

很简单, 修改这行语句为:

6:             int mid = low + ((high - low) / 2);
或者
6:             int mid = (low + high) >>> 1;


在c或者c++中, 则可以如下实现:
6:             mid = ((unsigned) (low + high)) >> 1;

相关文章推荐

JDK6的Random和System.nanoTime()引起的一个“大”bug

目前在做一个基于nats的paas项目时,碰到了一个诡异的问题。这个场景是业务A发送一个消息,业务B处理完以后应答,业务A拿到应答数据以后处理。 业务A --->request---->nats s...

今天非常高兴,解决了一个关于java类转json时有关联对象而且困扰我很久的BUG

之前在做毕设的时候,在java类转json且有关联对象的时候总是会遇到如下的错误,真的是困扰我很久   freemarker.template.TemplateModelException: Met...

.net的一个Bug:Int64与Byte[8]互转的问题

有一个64位整数值:    Int64 n = 634636512000000000; 有两种方法可以转为字节流 1:    byte[] buffer = new byte[8];  ...

VC调试版本C运行库内存申请的一个bug(转)

遇到过一个通信方面的软件,需要长期运行,做压力测试时,高负荷连续运行一定天数时必定崩溃,而且都是在msvcrtd.dll中崩溃。负责维护的人百思不得其解,就去问微软的人,结果微软的人说这是VC6带的m...
  • hazy
  • hazy
  • 2011-05-23 23:06
  • 1539

Eclipse解决bug:JDK是8.0,打不开eclipse

打不开eclipse 1.问题描述: 2.解决分析: 3.总结:…………
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)