程式碼品質不佳,會導致無法預料的行為。從使用者的角度來看,這通常表現為可用性不佳。對於攻擊者而言,這提供了以意想不到的方式向系統施加壓力的機會。
notify()
時,無法清楚知道喚醒哪一項執行緒。notify()
,無法指定要喚醒哪一項執行緒。 notifyJob()
呼叫 notify()
。
public synchronized notifyJob() {
flag = true;
notify();
}
...
public synchronized waitForSomething() {
while(!flag) {
try {
wait();
}
catch (InterruptedException e)
{
...
}
}
...
}
wait()
的執行緒,但 notify()
可能會通知不同的執行緒,而不是預期中的執行緒。run()
方法,而不是呼叫 start()
。Thread
物件的 run()
方法是一個錯誤 (bug)。程式設計師打算開始新的執行緒控制,卻意外呼叫了 run()
,而不是 start()
,因此 run()
方法將在呼叫者的執行緒控制中執行。run()
方法,而未呼叫 start()
。
Thread thr = new Thread() {
public void run() {
...
}
};
thr.run();
stop()
方法,這可能使資源洩漏。Thread
物件的 stop()
方法是一個錯誤 (bug)。程式設計師打算阻止執行緒執行,但是沒有注意到這不是停止執行緒的適當方式。Thread
內的 stop()
函數會在 Thread
物件內的任何位置造成 ThreadDeath
異常,這很可能讓物件處於不一致的狀態,並且可能使資源洩漏。由於此 API 本質上就不安全,因此很久之前,就不推薦使用。Thread.stop()
。
...
public static void main(String[] args){
...
Thread thr = new Thread() {
public void run() {
...
}
};
...
thr.start();
...
thr.stop();
...
}
clone()
方法但不會執行 Cloneable
介面。Cloneable
介面,因為它執行了名為 clone()
的方法。但是,此類別沒有執行 Cloneable
介面,且 clone()
方法將不會正確運作。 clone()
方法將導致 CloneNotSupportedException.
public class Kibitzer {
public Object clone() throws CloneNotSupportedException {
...
}
}
ICloneable
介面為其 Clone
方法指定的約定不安全,這是應該避免的。ICloneable
介面不能保證可進行深層的複製。當對執行該介面的類別進行複製時,可能得不到預期的結果。這是因為這些類別雖然執行 ICloneable
,但只執行淺層複製 (只複製物件,不包含現有參照的其他物件),這可能會導致非預期的結果。因為深層複製 (複製物件以及其所有參照的物件) 是一般預設的複製方法,為了避免錯誤的發生,應該避開使用 ICloneable
介面。clone()
方法所呼叫的函數可被取代。clone()
函數呼叫可取代的函數時,可能會造成複製品保留在部分初始化的狀態,或是損毀。clone()
函數所呼叫的方法可被取代。
...
class User implements Cloneable {
private String username;
private boolean valid;
public Object clone() throws CloneNotSupportedException {
final User clone = (User) super.clone();
clone.doSomething();
return clone;
}
public void doSomething(){
...
}
}
doSomething()
函數及其封裝類別不是 final
,這表示可以取代函數,進而可能使複製的物件 clone
保留在部分初始化的狀態,如果未以非預期的方式修改邏輯,可能會導致錯誤。equals()
方法) 比較方塊化原始物件,可導致非預期的行為。equals()
方法,而不是 ==
和 !=
運算子。Java 規格載明有關方塊化轉換的資訊: Boolean
或 Byte
),則只會快取或記住某個範圍的值。對於值子集,使用 ==
或 !=
將會傳回正確的值,對於此子集之外的所有其他值,這會傳回物件位址的比較結果。
...
Integer mask0 = 100;
Integer mask1 = 100;
...
if (file0.readWriteAllPerms){
mask0 = 777;
}
if (file1.readWriteAllPerms){
mask1 = 777;
}
...
if (mask0 == mask1){
//assume file0 and file1 have same permissions
...
}
...
Example 1
中的程式碼使用 Integer
方塊化原始物件,來嘗試比較兩個 int
值。如果 mask0
和 mask1
同時等於 100
,則 mask0 == mask1
將會傳回 true
。但是,現在當 mask0
和 mask1
都等於 777
時,mask0 == maske1
將會傳回 false
,因為這些值不在這些方塊化原始物件的快取值範圍內。