2011-10-10 75 views
2

似乎Java機器在某些類型的循環上失敗,這些循環似乎對其系統檢查是無限的,但實際上是由循環類以外的代碼終止的。這種情況不常發生,但最近我在最近的TickleService中發現了這種情況,在這種情況下代碼的有限循環無故障運行,但需要任何外部終止的循環失敗。例如:Java機器拒絕某些形式的循環代碼

class TickleService extends Service{ 
... 
    void execute(){ 
     while(true){ 
      Log.e("Test","Tickle"); 
      wait(1000); 
     } 
    } 
... 
} 

上述情況導致系統ANR立即崩潰(CPU使用率> 99%例外)。 但是,下面的版本將只運行一次,並停止進一步的操作而沒有崩潰:

public class TickleService extends Service{ 
... 
    public static boolean amNotAlive = false; 
    void execute(){ 
     while(true){ 
      Log.e("Test","Tickle"); 
      if(amNotAlive) 
      break; 
      wait(1000); 
     } 
    } 
... 
} 

執行一次以上循環和停止循環。 接着,如果代碼有一個有限環它將完美執行:

public class TickleService extends Service{ 
... 
    public static boolean amNotAlive = false; 
    void execute(){ 
     for(int i = 0; i<5;i++){ 
      Log.e("Test","Tickle"); 
      wait(1000); 
     } 
    } 
... 
} 

這上面的循環將運行5次,每次相隔一秒如預期。 最終,我修補程序應用是要運行中,我試圖將JVM欺騙以爲無循環在所有存在的以下內容:

public class TickleService extends Service{ 
... 
public static boolean amAlive = true; 
void execute(){ 
    Log.e("Test","Tickle"); 
    wait(1000); 
    if(amAlive) 
     restartService(); //pseudo code for doing startService on self 
} 
... 
} 

這招無一例外產生執行且可靠地發癢相隔一秒。 運行了許多測試,都證實如果連續循環根據類之外的觸發器終止,則連續循環失敗,但如果內部終止,則會正確運行。最終,儘管我強烈懷疑Dalvik java機器中有目的的設計缺陷或意外錯誤導致了這個問題,但證據只是間接的。此外,我在Android中編寫的所有服務似乎都沒有出現這個問題。有人知道爲什麼嗎?我很想更好地理解這個問題。

+0

我認爲你的修復最終會導致堆棧溢出 - 不知道「startService」是如何工作的(android沒有經驗)。 –

回答

3

Dalvik虛擬機在您顯示的所有情況下都能正確運行。運行無限循環,從而阻塞主UI線程是不好的做法,只會讓你的ANR錯誤。我還沒有看到你的其他代碼,所以我無法迴應。

+0

這正是我需要知道的。我認爲每個服務都在自己的線程上運行,但是如果它們全都在UI線程上運行,那麼它就會探測到我所擁有的錯誤。謝謝! –