본문 바로가기

프로그래밍/안드로이드(Android)

[Android] ConcurrentModificationException 문제 해결 관련 정보

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

회사에서 개발 하다 문제가 발생해서 메일로 정리 했던것을 옮겼습니다.

 

개발간 activity를 종료할 때 계속 원하는 동작이 되지 않아서 답답해했는데요.

로그도 나오질 않고 해서 한 줄씩 디버깅했습니다.

원인은 activity finish() 하는 부분에서 문제가 발생했습니다.

 

for (Activity activity : activityStack) {

             if (activity == null) {

                    continue;

             }

             try {

                    activity.finish();

             } catch (Exception e) {

                    DebugLogger.w(TAG, "When acitivity finish, exception.");

             }

       }

 

위의 코드에서 결국 ConcurrentModificationException 예외가 발생한 것으로나오네요.

 

이는 동기화 관련 문제로 데이터에 대해서 무결성이 입증되지 않을 때 문제가 발생된다고 합니다.

 

static으로 되어있는 activityStack for문을 돌면서 activity를 종료하다 보니

 

실제로 finish를 하게 되면 activityStack size 1개 줄어 들게 됩니다.

 

처음 하나를 종료하고 나서 돌아와보니 데이터가 달라보여 처리를 못해주고 예외가 발생합니다.

 

, for문의 주체를 내부에서 제거 하는 행동은 좋지 않아 보입니다. 해야하는 경우도 있지만 위의 for문의 경우에는 위험하다는 결론입니다.

 

예전에 for문 쓸 때 위의 방식을 쓰기 보다는 기본적으로 쓰는 (int i = 0; I < size; i++) 형식을 선호하라고 들었었는데

그땐 왜 그래야 하는지 몰랐는데 저런 문제 때문이지 않을까 합니다.

 

해결방법으로 처음 생각 한 게 아래 방법

 

for (int i = 0; i < activityStack.size(); i) {

       Activity activity = activityStack.get(i);

       if (activity == null) {

              continue;

       }

       try {

                    activity.finish();

       } catch (Exception e) {

             DebugLogger.w(TAG, "When acitivity finish, exception.");

       }

}

 

for문을 (i=0;i<size;i) 형식으로 변경하고 size 0이 될 때 까지 맨 처음 것을 가져와서 종료하는 방식입니다.

우선 맨 위에 것을 먼저 지우는 것도 이상해 보이고

그 닥 코드가 좋아 보이지 않아서 for문 말고 while문을 쓰기로 했습니다.

그래서 최종 수정된 게 아래 방법입니다.

 

while (activityStack.size() != 0) {

              Activity activity = activityStack.get(getActivityStackSize() - 1);

              if (activity == null) {

                    continue;

              }

             try {

                    activity.finish();

             } catch (Exception e) {

                    DebugLogger.w(TAG, "When acitivity finish, exception.");

             }

       }

 

size 0이 될 때 까지 마지막 올린 것부터 finish시키도록 했습니다.

정상적으로 모든 activity가 종료되네요.

 

결론은 for문에서 데이터 무결성을 위해서 for문의 주체인 내부를 remove하는 행동은 자제하자.

(int i=0; 비교문; i++) 형식의 for문을 되도록 사용하자 입니다.

 

 

출처 : http://kkomanjell.tistory.com/