2011년 4월 5일 화요일

Linux 명령어 du/df

1. 특정 디렉토리의 용량을 확인하는 du 명령어 개론

- du 는 “Disk Usage” 의 약어로서 파일및 디렉토리의 사용량을 확인 할 때 사용하는 명령어임.

- df 명령어가 파티션( 파일시스템 ) 단위의 디스크사용량을 점검한다면 du 명령어는 특정 디렉토리 또는 파일을 단위로하여 그 용량을 확인하는 명령어임

- du 명령어는 현재디렉토리의 용량뿐 아니라 현재디렉토리의 서브디렉토리 및 파일들 까지 모두 함께 사용량을 계산하여 표시해 줌.

- 사용형식 : du [ 옵션 ]….[ 파일 ] [ 디렉토리 ]

2. 특정 디렉토리의 전체 사용량 점검하기

- du -s /etc

- 전체용량을 간략히 표시할때는 -s 옵션을 사용함.

3. 특정 디렉토리의 전체 사용량을 용량단위를 붙여서 점검하기

- 전체용량을 모두 합해서 용량단위까지 붙여서 출력하라는 옵션은 -sh 이다.

- du 명령어사용시 “-h”(human-readable)는 단위를 표시하게 하는 du 명령어의 옵션으로서 KByte 또는 MByte 또는 GByte 등의 용량표시를 해주게 됨.

- du -sh /etc

4. 일반 계정사용자의 홈디렉토리 전체 디스크 사용량 점검하기

- du -sh ~stkim

- “du -sh ~ID” 라고하면 현재 자기가 사용중인 계정의 전체용량을 확인할 수 있음.

5. 현재 서버의 파일시스템별 디스크사용량 점검하는 df명령어 실무활용

- df 는 “Disk Free” 의 약어로서 현재 사용중인 파일시스템의 전체용량, 사용한 용량, 사용가능한 용량, 사용울, 마운트정보등을 보여줌.

- 서버 장애의 주된 원인이 될 수 있는 File System Full( 파일시스템용량이 꽉 참 ) 을 방지하기 위하여 서버관리자의 주된 업무 중 한가지가 주기적인 파일시스템 사용량 점검임.

- 파일시스템의 사용량점검을 위해 사용되는 명령어가 df 임.

- df 명령어는 /etc/fstab 파일에서 파일시스템정보를 참조하고, /etc/mtab 에서 마운트됨 정보를 참조함.

- 현재 서버의 디스크사용량을 파티션별로 확인하기

- 파일시스텤 사용량 정보를 확인하기 위해서는 간단히 “df” 라고만 입력하면 됨.

6. 디스크사용량을 파티션별로 확인할 때에 용량을 KByte 단위로 표시하기

- df -k

- -k 옵션을 사용하면 표시되는 용량단위가 KB임. 하지만, 아무런 옵션없이 사용하여도 기본 표시단위가 KB 이므로 -k 옵션은 디폴트( default) 라고 생각하면 됨.

7. 디스크사용량을 파티션별로 확인할 때에 용량을 Mbyte 단위로 표시하기

- 용량을 MB단위로 용량을 표시하려면 -m 옵션을 사용함.

8. 디스크사용량을 파티션별로 확인할 때에 가장 적당한 용량단위 표시하기

- -h 옵션은 human-readable 이라는 의미에서도 알 수 있듯이 사람이 보기 쉽도록 최적의 용량단위를 알아서 표시해 줌.

- df -h

9. 디스크용량 확인시에 모든 파일시스템을 대상으로 점검하기

- df -a

- 파일시스템의 크기가 0인 것까지 모든 파일시스템을 확인하는 옵션인 -a .

10. 파틱션별로 디스크용량 점검시에 inode 사용자정보를 표시하기

- df 명령어 사용시에 -i 옵션을 사용하면 블록대신에 inode 단위로 사용량 정보를 표시해 줌.

11. 디스크사용량을 출력할 때에 파일시스템의 종류와 함께 표시하기

- df -T

- -T 옵션은 각 파일시스템들이 사용하고 있는 파일시스템 종류를 추가로 표시해 줌.

12. 특정 파일시스템의 종류만을 대상으로 디스크사용량 조사하기

- df -t 파일시스템종류

- df 명령어 사용시 -t 옵션뒤에 파일시스템의 종류명을 지정하면 그 파일시스템의 종류를 가진 파일시스템에 대해서만 사용량을 표시해 줌.

13. 특정 파일시스템의 종류를 제외한 디스크사용량 조사하기

- df -x ext3

- df 명령어에 -x 과 파일시스템 명을 명시하면 지정한 파일시스템을 제외한 파일시스템에 대해서만 사용량을 표시해 줌.

2011년 3월 17일 목요일

Gerrit

gerrit
http://gerrit.googlecode.com/svn/documentation/2.0/install.html
http://gerrit.googlecode.com/svn/documentation/2.0/dev-readme.html

Gerrit 설치가이드
http://gregmeiste.com/tag/gerrit/
http://gregmeiste.com/2009/06/gerrit-code-review-installation/
http://blog.naver.com/PostView.nhn?blogId=johnforstar&logNo=30071252777&redirect=Dlog&widgetTypeCall=true


gerrit 프로젝트 홈
http://code.google.com/p/gerrit/


Gitosis를 이용한 Git server 설치:http://stdnstr.tistory.com/110
http://www.mirwing.com/entry/Android-Source-%EA%B4%80%EB%A6%AC

[Android] 현재 내 어플에서 다른 어플리케이션 실행시키기..

PackageManager pm = getPackageManager();
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

List appList = pm.queryIntentActivities
(mainIntent, 0);
Collections.sort(appList, new ResolveInfo.DisplayNameComparator(pm));
int temp=0;
for(int i=0; i Log.v("RJ",appList.get(i).loadLabel(pm).toString());
if(appList.get(i).loadLabel(pm).toString().equals("Calendar"))
temp = i;
}
Intent i = new Intent();
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

i.setComponent(new ComponentName(appList.get (temp).activityInfo.applicationInfo.packageName, appList.get(temp).activityInfo.name));
startActivity(i);

HashMap 기준에서 Hashtable과 비교

출처 : http://alones.kr/blog/852?category=20

HashMap 기준에서 Hashtable과 비교하면

1. HashMap은 key와 value에 null을 허용하지만 Hashtable은 그렇지 않다.

2. HashMap은 thread safe하지 않고 (not synchronized) Hashtable은 그렇다 (synchronized). 진정한 Java인이라면 미래를 위해 Hashtable을 쓰는 게 맞을 것 같기도 하다.
HashMap 자체는 not synchronized하기 때문에 다음과 같이 Collection.synchronizedMap을 이용해서 synchronized하게 만들 수 있다.

Map m = Collections.synchronizedMap(new HashMap(...));3. HashMap은 bucket에 element들을 흩어뿌리기 때문에 get/put과 같은 기본 동작들이 동일한 시간 (constant-time performance) 에 수행된다.



HashMap과 Hashtable에서 둘 다 고려할 사항은

1. capacity와 load factor

Capacity는 bucket의 수이고 load factor는 bucket의 element가 얼만큼 찼을 경우 rehash를 발생 시킬 것인지를 정하는 것이다. rehash의 경우는 bucket의 수가 두 배로 늘어나고 각 element에 대해서 hash가 다시 일어나는 것을 의미하기 때문에 이 것은 시간-공간의 trade-off가 있다.

Load factor는 0.75를 HashMap과 Hashtable에서 둘다 ideal number로 권장하고 default value이다.

Capacity는 HashMap은 default value가 16이고 Hashtable은 11이다.

생성할 때 아주 많은 (얼만큼인지는 제시하지 않고 있다) element가 삽입될 것이라면 capacity를 초기에 높게 잡는게 좋을 것 같다.



2. ConcurrentModificationException

Iterator를 얻은 후에 Iterator를 통하지 않고 외부에서 element가 삭제되거나 추가되면 ConcurrentModificationException이 발생한다 (fail-fast라고 한다. 문제가 생기면 바로 보고하는 것으로 fail-stop이라고 한다). 당연한 말이겠지만, fail-fast로 인한 exception handling을 통해 기능을 수행하는 코드를 작성하지 말고 말 그대로 bug를 찾기 위해 이를 이용해라고 한다.



아무튼 오래 만에 JavaDoc을 자세히 읽어 본거 같다. 프로그램에서 많은 것들이 중요할 것이고 그 중 자료 구조 (특히 자바와 같은 언어에서)도 많은 것을 고려해야 하기에 포스트를 지루하게 써보았다.

"별 생각 없이 쓴다" 라는 말 자체를 이미 거론해 버렸지만 그리고 그 목적으로 HashMap을 거론했지만, "별 생각 없이 쓴다" 라는 말 자체는 (그리고 그 "별 생각 없이 쓴 것"들이 많아 질 수록) 미래의 재앙을 키워가는 것이기 때문에 지양 해야 할 것이다.



[Ref]

HashMap Java Doc SE6: http://java.sun.com/javase/6/docs/api/java/util/HashMap.html

Hashtable Java Doc SE6: http://java.sun.com/javase/6/docs/api/java/util/Hashtable.html

Fail-fast (Fail-stop): http://en.wikipedia.org/wiki/Fail-fast

alones

국가별 언어설정 가져오기

Locale systemLocale = getResources().getConfiguration().locale;
String strDisplayCountry = systemLocale.getDisplayCountry();
String strCountry = systemLocale.getCountry();
String strLanguage = systemLocale.getLanguage();

2011년 3월 7일 월요일

Memory Leak

자바 메모리 누수 관련하여 검색중 좋은 자료가 있어서 퍼왔습니다!^^;

정확한 메모리 사용량 측정법
========================

자바 프로그램의 실제 메모리 사용량은 시스템의 작업 관리자에서 나오는 메모리 사용량으로는
측정의 정확도가 매우 떨어진다.
따라서, 개발자 수준에서 메모리 사용량을 측정하고 개선하기 위해서는,
자바 어플리케이션의 메모리 사용량은 디버그 출력으로 totalMemory() - freeMemory()를
출력하거나, OptimizeIt과 같은 개발도구로 측정하는 것이 좋다.



메모리 누수(leak)의 심각성
=======================

자바에서는 GC에 의해 메모리가 자동 관리되어 memory leak가 없다고 하지만,
사실은 memory leak가 발생할 수 있다.
그 이유는 실제로 사용되지 않는 객체의 reference를 프로그램에서 잡고 있으면
그 객체는 GC에 의해 처리되지 않고 프로그램내에서도 접근하여 사용될 수 없는
사실상 쓰레기로서 메모리(보다 정확하게는 주소 공간)를 점유하게 된다.
그러한 메모리 누수 현상이 있으면 창을 열고 닫을 때마다 그리고 문서를 열고 닫을 때마다
지속적으로 메모리가 증가되어 성능 저하뿐만 아니라 결국에는 메모리 오류 발생으로
프로그램이 종료되는 심각한 현상이 발생한다.



자바 GC 알고리즘
=============



이와 같은 자바의 메모리 누수 현상에 대한 정확한 진단과 처방은 때로는 GC 알고리즘에 대한 보다 정확한 이해를 필요로 한다.
자바의 GC 알고리즘은 reference counting을 사용하지 않아서 객체간에 cyclic reference가 생겨도 GC되지 않는 문제가 없는 완벽한 방법이지만 일정 시간의 GC 시간을 필요로 한다는 단점을 가지고 있다.
즉, 자바 heap의 모든 객체는 현재 사용중인 객체와 사용되고 있지 않는 객체, 2가지로 나뉘어지며,
사용중인 객체중에서도 사실상 사용되지 않는 객체가 있을 수 있으며 이는 메모리 누수에 해당한다는 것이다.


현재 사용중인 객체란 다음과 같은 루트 참조 (객체가 아님)들로부터 직간접적으로 참조가 되는 (reachable한) 모든 객체를 의미하며, 나머지 객체는 모두 쓰레기 객체이고, 요즘 JVM은 이러한 쓰레기 객체를 완벽하게 수거하므로 (옛날 버전의 JVM은 그렇지 않았음) 이 단계에서의 메모리 누수는 없다.


이와 같은 루트 참조는 다음과 같이 크게 3가지가 존재한다.

1. static 변수에 의한 객체 참조
2. 모든 현재 자바 스레드 스택내의 지역 변수, 매개 변수에 의한 객체 참조
3. JNI 프로그램에 의해 동적으로 만들어지고 제거되는 JNI global 객체 참조



이를 직관적으로 이해하는 방법은 다음과 같다.
GC 알고리즘에서 현재 사용중인 객체의 의미는 현재 생성된 객체들중에서 현재 이후에 참조되어 사용될 가능성이 있는 모든 객체를 의미한다.
객체는 직접 참조되지 않고 항상 변수를 통하여 참조가 가능하다.
static 변수는 프로그램 어디서든 사용할 수 있으므로 static 변수에 의해 참조되는 객체와 그 객체로부터 직간접적으로 참조되는 모든 객체는 언제든 사용될 가능성이 있는 객체라서 사용중인 객체이다.



자바에서 현재 실행중인 (각 스레드별로) 모든 메소드내에 선언된 지역 변수와 매개변수에 의해 참조되는 객체와 그 객체로부터 직간접적으로 참조되는 모든 객체는 참조되어 사용될 가능성이 있으며, 이 뿐만 아니라 caller 메소드로 return된 후에는 caller 메소드에서 참조하고 있는 지역변수, 매개변수에 의해 참조되는 객체와 그 객체로부터 직간접적으로 참조되는 모든 객체 또한, 참조되어 사용될 가능성이 있다.


따라서, 각 자바 스레드의 스택 프레임내에 있는 모든 지역변수와 매개 변수에 의해 참조되는 객체와 그 객체로부터 직간접적으로 참조되는 모든 객체들이 참조되어 사용될 가능성이 있다는 것이다.

또한, JNI 네이티브 C 함수내에서도 JNI 함수를 사용하여 자바 객체를 생성할 수 있다.
이때 생성된 자바 객체에 대한 참조를 int 값등으로 변환시켜 C 함수내의 지역 변수, 매개 변수, 전역 변수로 참조하더라도 이는 자바 가상 머쉰의 영역을 벗어나는 것으로서, 즉 자바 스레드 스택이 아닌 네이티브 스택이어서 자바 가상 머쉰의 스레기 수거 기능이 동작하지 못한다. 따라서, 자바의 static 변수나 지역 변수, 매개 변수에 의해 참조되지 않으면서 쓰레기 수거되지 않고 C 변수를 통하여 지속적으로 자바 객체를 접근할 수 있도록 JNI C 함수를 호출하여 JNI global reference로 JVM내에 등록시킬 수 있으며, 물론 등록 해제도 가능하다.


따라서, 자바의 사용되는 메모리란 사용될 가능성이 있다는 것일뿐이므로 논리적으로도 정확하게 사용되고 있는 객체가 아닌 사실상의 쓰레기 객체가 있을 수 있으며 이러한 객체들이 자바나 닷넷 프로그램의 메모리 누수 현상을 초래하는 것이다.
이와 같이 사살상의 쓰레기인지 아닌지는 기계적인 검출이 사실상 곤란하여 툴의 도움을 받을 수 있을지라도 프로그래머가 로직을 이해하여 파악해야 한다.
그렇지 않은 객체들은 어떠한 방법으로도 참조할 수 있는 수단이 없어서 확실하게 쓰레기 객체라는 것을 의미하며, 최근 버전의 자바 가상 머쉰은 이런 확실한 쓰레기 객체는 확실하게 수거해서 재사용되게 해준다.



메모리 누수 검출을 위한 개발 도구 사용법
===================================



OptimizeIt등의 도구로 보면, 전체 루트 참조 목록을 볼 수 있고 이로부터 참조되는 객체들을 모두 따라갈 수 있으며, 루트 참조들은 위에서 지적한 바와 같이 3가지 중에 1가지로 구분되어 확인할 수 있다.
또한, 특정 객체 참조를 참조하는 객체들을 따라갈 수도 있다.
메모리 누수 검출을 위해서는 메모리 누수 원인이 되는 요주의(?) 대상 객체 (창 객체나 Document 객체등)를 참조하는 객체들을 따라가서 일단 루트까지 따라가야 한다. 루트가 아닌 일반 객체에서 그래프가 끝나는 경우가
많은 데 이는 객체 참조 그래프에서 cycle이 생성되어 끝난 것이며 이러한 객체는 루트 참조가 아니므로 메모리 누수와 관련이 없어서 무시하면 된다.
일반적으로 특정 객에 이를 수 이를 수 있는 루트 참조는 몇개 정도로만 압축되므로 이들 루트 참조들을 위주로 조사를 해보면 되는 것이다.


메모리 누수 원인, 처방, 개발자들의 오해
===================================



메모리 누수 원인을 파악할 때 개발자들이 흔히 잘못하는 실수는 객체와 클래스(혹은 코드)의 차이를 명확히 구분하는 것이다. 스레기 수집은 객체들간의 참조 관계로부터 파악되는 것이므로 클래스 구조나 패키지 구조와 별로 관계가 없다. 또한, 이와 같은 메모리 누수가 GUI 어플리케이션과 같이 객체들간에 상호 참조가 많은 경우에는 하나의 객체 참조를 null 처리해주지
않은 실수가 전체 창, 혹은 전체 문서의 메모리 누수로 이어지는 경우가 많다.
그 이유는 Frame에서 부터 시작하여 Frame내에 포함되는 모든 UI 컴포넌트들은 parent 변수와 childs 변수를 통하여 상호 참조하게 되어 전체가 한 덩어리가 되어 이중 한개의 UI 컴포넌트에 대한 참조가 남아있어도 전체 Frame과 여기에 포함된 모든 UI 컴포넌트의 객체들이 사용중인 객체가 되는 것이다.
뿐만 아니라 이벤트 리스너 등록등으로 인하여 UI 컨트롤에서 UI 컨트롤이 아닌 객체로의 참조가 남아서 메모리 누수가 더 확대될 수 있다.

비슷한 현상으로 Document, View 구조에서 Document 구조 또한 부모-자식 Element들간에 상호 참조되어 전체가 하나의 군집을 이루고 View 구조의 각 뷰 객체들이 Document를 참조하므로 이들중 1개의 객체라도 그 참조가 남아있으면 (루트 참조에 의해 직간접적으로 참조되면) 전체 Document 객체와 이로부터 직간접적으로 참조되는 모든 객체들의 메모리 누수로 확대된다.

일반적으로 static 변수를 사용하는 이유는 프로그램내에서 전역적으로 데이터를 공유할때 사용한다.



static 변수는 이와 같은 메모리 누수의 원인이 되는 경우가 많으므로 굳이 static 변수를 써야만 하는 상황이 아니라면 인스턴스 변수를 사용하도록 프로그래밍시에 유의해야 한다.
즉, GUI 어플리케이션의 경우, 창 객체 참조나 문서 객체 참조를 통하여 이러한 인스턴스 변수를 (직간접적으로) 접근하도록 하는 것이다.
만약, 그 static 변수가 필히 사용될 필요가 있다면 그 static 변수로부터 창 객체나 문서 객체에 참조로 이르는 참조 그래프내의 참조 경로상의 적정 시점에서 null 대입을 통하여 그 static 변수로부터 문서 객체(혹은 창 객체)에 이르는 모든 가능한 참조 경로를 끊어주어야 한다.
가령, static 변수에 의해 참조되는 Vector에 이벤트 처리를 위해서 문서 객체나 창 객체 혹은 이들에 대한 구성 객체를 등록한 경우에는 다음과 같이 2가지 해결방법이 있다.



1. 그 이벤트 처리기 목록에 등록되는 객체들이 특정 창 혹은 특정 문서가 열렸을 경우에만 유효한 객체들로 분리시켜 관리할 수 있는 경우에는 이벤트 처리기 목록에 등록되는 객체 참조를 저장하는 static 변수를 창 객체나 문서 객체를 통하여 접근할 수 있는 아마 인스턴스 메소드로 접근하게 될) 인스턴스 변수에 저장하는 것이 가장 이상적이며, 이 경우 창을 닫거나 문서를 닫을때 reference를 끊어주는 처리를 전혀 할 필요가 없어 안전하다.


2. 그 이벤트 처리기 목록에 등록되는 객체들이 특정 창 혹은 특정 문서와 관련없은 전역적인 객체들이거나 적절히 분류될 수 없다면 static 변수를 사용할 수 밖에 없고, 이 경우 static 변수에 의해 참조되는 Vector내의 관련없는 객체들을 창닫거나 문서닫을 때 제거해주는 처리를 해주어야 한다.

이와 같이 메모리 누수는 대부분의 경우 static 변수가 핵심적인 역할을 하므로, 이를 주의깊게 살펴보면 대부분의 메모리 누수 문제를 해결할 수 있을 것이다.



자바 스레드 스택의 지역 변수가 매개 변수에 의한 참조도 살펴볼 필요가 있는데, GUI 어플리케이션에서는 이러한 지역 변수나 매개 변수는 대개의 경우 메모리 누수 문제와 관계가 없다.
그 이유는 GUI 어플리케이션이란 main 메소드와 그 메소드로부터 직간접적으로 메소드들이 끊임없이 호출되는 일반 어플리케이션 모델이 아니라, main 메소드는 창을 연후에 종료되고 일반적으로는 스레드 스택이 모두 비어 있으며 이벤트 루프를 실행시키는 스레드만이 waiting하는 경우가 대부분이라서 스레드 스택에 남아있는 게 없다는 것이다.


하지만, GUI 어플리케이션이더라도 백그라운드 스레드를 사용하는 경우에는 문제가 될 수 있다.
이 백그라운드 스레드가 실행은 되지 않더라도 종료되지 않고 waiting하고 있다면 스레드 스택이 존재하고 지역변수, 매개변수가 살아있어서 이로부터 직간접적으로 참조되는 모든 객체는 사용중인 객체가 되기 때문에 메모리 누수 요인이 될 수 있다.
즉, 요약한다면 GUI 어플리케이션에서는 메모리 누수 원인을 조사하는 데 있어서 지역 변수와 매개변수에 대해서는 백그라운드 스레드만 조사해보면 된다는 것이다.

마지막으로, JNI 전역 참조에 의한 메모리 누수는 크게 2가지 요인이 있을 수 있다.



1. 네이티브 코드쪽에서 JNI 전역 참조를 해제하지 않는 버그로 인하여 메모리 누수 발생.
자바의 GUI 관련 패키지는 이제는 많이 안정화되었고 변화도 많지 않으므로 자바의 GUI 관련 패키지내에서는 이러한 버그가 있을 가능성이 거의 없다.
JVM에 내장되지 않은 혹은 자체 제작한 JNI 함수내에서 JNI 전역 참조를 해제하지 않는 버그로 인하여 메모리 누수 발생할 수 있는데, 네이티브 코드에서 JNI 전역 참조를 만드는 경우 또한 매우 드문 경우이다.



2. 네이티브 자원을 반환하는 dispose(), close() 메소드를 제때에 호출해주지 않아서 메모리 누수 발생.
이러한 메소드는 기본적으로 JNI 전역 참조를 해제하는 것이 아니고 시스템 자원
(시스템 그래픽스, 시스템 윈도우즈, 시스템 파일 descriptor등등)을 반납하는 경우가 대부분이다.
이들이 사용하는 메모리는 자바힙이 아니라 네이티브 힙등 네이티브 메모리 영역으로서 자바 개발 도구등으로 검출되지 않아서 자바 메모리 누수와 직접적인 관련성이 없다.
단, 이들 네이티브 자원과 관련된 코드가 JNI 전역 참조를 가지고 있어서 이들 자원이 해제되기 전에는 JNI 전역 참조를 해제하지 않아서 해당 자바 객체의 메모리 누수가 발생할 수 있으나,
이러한 경우는 일반적으로 드물 것이다. 그 이유는 네이티브 자원은 자바 코드보다 더 low-level한 것으로서 이러한 자원을 관리하는 코드에서 자바 객체에 대한 전역 참조를 관리할 필요성이 대부분 없기 때문이다.


메모리 누수 원인을 조사할 때 다음과 같은 순서로 문제 발생 가능성, 누수 원인이 미치는 메모리 누수량, 문제 원인 진단의 용이성이 높으므로 이와 같은 순서로 누수 원인을 철저하게 조사하는 것이 개발 효율적이다.



1. static 참조
2. 백그라인드 스레드의 지역, 매개 변수
3. 네이티브 코드내의 JNI 전역 참조



캐쉬와 관련된 메모리 누수
=====================



캐쉬는 일반적으로 캐쉬 엔트리에 대한 접근을 위해 키와 value로 이루어지고 HashMap등으로 관리되며, 메모리를 추가로 사용하여 속도 성능 효율을 얻는 것이 주목적이다.
이 캐쉬의 각 엔트리는 언제든 제거되어도 상관없으며, 키나 키와 관련된 데이터로부터 원본 value 객체에 접근하여 언제든 원본 value에 접근하여 가져올 수 있다는 특징을 갖는다.
그러나, 보통 간단하게 구현된 캐쉬는 캐쉬가 자꾸 커지기만 할뿐 줄어들지 않아서 메모리 누수가 발생할 수 있다.


일반적으로 변수에 대입한 참조들은 모두 강 참조(strong reference)이다.
강 참조만으로 이루어진 HashMap에서는 메모리 부족 상태를 파악하여 캐쉬 엔트리에 대한 참조를 적절히 제거해주면 메모리 누수가 발생하지 않을 수 있으나 메모리 부족 상태를 파악하기 어렵고 추가 작업을 해야 하므로 이와 같이 처리하지 않는 경우가 대부분이다.

하지만, 약간의 코딩으로 이러한 메모리 누수를 해결할 수 있는 방법이 있다.
이러한 용도로 사용할 수 있는 것이 SoftReference, WeakReference라는 것이 있다. (PhantomReference도 있는 데 잘 사용되지 않는다.)
SoftReference, WeakReference 객체를 사용하여 소프트 참조, 약 참조를 사용하면 이러한 참조 객체에 의해 참조되는 객체는 메모리가 부족해지면 JVM에 의해서 모두 null 참조로 바뀌고 쓰레기 수집된다.


예전에 실험해본 바에 의하면 소프트 참조와 약 참조 모두 할당된 자바 힙 크기가 부족해질 경우에만 비로서 쓰레기 수집되었다.
따라서, 메모리 누수는 없을지라도 사실상의 메모리 누수와 유사한 성능상 나쁜 효과를 초래할 수 있다.


소프트 참조와 약 참조는 최대 자바 힙 크기에 이를때까지 쓰레기 수집 되지 않고 최대 자바 힙 크기에 이를 때까지 메모리를 차지하여 현실적으로는 더 많은 메모리를 (더 정확히는 가상 주소 공간과 가상 메모리)를 사용하여 RAM 메모리 효율성이 떨어져서 성능 저하 효과를 가져올 수 있다.

문서 객체나 창 객체에 종속적인 캐쉬는 문서나 창이 닫힐때 캐쉬 전체를 null 대입함으로써 이와 같은 메모리 누수 문제 혹은 메모리 효율성 저하 문제를 해결할 수 있다.


Toolkit 클래스의 getImage 메소드 같은 경우에는 동일 URL에 있는 이미지를 여러번 참조하는 경우를 대비하여 효율성을 위해서 URL(혹은 파일 경로명)을 키로 하여 이미지 객체를 캐슁하여 사용한다.
이때, URL로부터 언제든 원본 이미지 데이터에 접근하여 이미지 객체를 생성할 수 있으므로 JVM 내에서는 소프트 참조로 구현되어 있으므로 메모리 부족시에는 자동으로 쓰레기 수집되므로 꼭 메모리 누수는 아니나, 상기에 언급한 이유로 메모리 효율성이 저하될 수 있다.
Toolkit 클래스의 getImage 같은 편의상 제공되는 메소드는 최적화에는 방해가 될 수 있으므로 사용하지 않는 것이 좋다.


문서내의 이미지들을 Toolkit 클래스의 getImage를 사용하지 않는다고 해도 JVM 전역적인 캐쉬를 만들어서 사용하면 메모리 누수나 메모리 효율성 저하 문제가 발생한다.
따라서, 주어진 문서내의 이미지만을 저장하는 캐쉬를 사용하고 그 문서가 닫힐 때 해당 문서 이미지 캐쉬에 대한 참조를 반환하면 이미지 캐쉬에 대한 메모리 문제를 해결할 수 있다.

이미지 캐쉬는 메모리를 많이 사용하므로 주의 대상이 된다.




자바힙 메모리 관리와 시스템 메모리 관리와의 관계
==========================================



일반적으로 윈도우즈에서 프로그램의 메모리 사용량은 작업 관리자를 열어서 메모리 사용량과 가상 메모리 사용량을 측정할 수 있는데, C 프로그램보다 자바 프로그램이 휠씬 많은 메모리를 사용하는 것으로 측정되는 경우가 많다.


그러나, 자바에서의 메모리 사용량이 MS 오피스와 같은 네이티브 어플리케이션만큼 메모리를 많이 사용한다고 해도 그 차이만큼 실제 메모리를 꼭 많이 쓰는 것은 아니다.
자바가 시스템으로부터 할당된 메모리중의 일부를 자바 힙이 사용하고 이 힙의 일부는 아직 자바 객체에 할당되지 않아서 실제 메모리로 할당될 가능성이 작고, 프로그램간 공유되는 메모리의 크기는 잘 측정되지 않기 때문이다.



MS사의 MSDN이나 Knowledge base를 뒤져봐도 메모리 사용량, 가상 메모리 사용량 및 이와 관련된 메모리 성능을 제대로 평가하는 데 필요한 많은 메카니즘들이 소개되어 있지 않다.
향후 이를 좀더 정확히 이해하고 자바의 GC 알고리즘의 메모리 성능 효과를 이해하게 되면
자바에서의 메모리 사용량이 그렇게 큰 문제는 아니라는 것을 명확하게 설명할 수 있을 것이며,
이를 뒷받침하는 구체적인 실험 결과를 제공할 수 있을 것이다.
만약, 실험에 의해서도 메모리 성능 문제가 심각하다면 정확한 이해를 바탕으로 이를 위한 개선 방안을 찾아볼 수 있다.

[출처] 자바 메모리 누수의 원인과 처방 |작성자 즐건하루

2011년 3월 6일 일요일

Xming with Putty

1. Download Xming X Server for Windows in http://sourceforge.net/projects/xming

2. Install Xming

3. Configure PuTTY
- Open PuTTY
- Go to Connection - SSH - X11
- Check Enable X11 forwarding
- Add localhost:0.0 to X display location

4. Execute Xming
5. Open Session with the previous configuration in PuTTY
6. Command kdiff3 to test Xming

7. To customize the font size of Xming Window, following the below.
Open “Properties” window of Xming shortcut.

Add the following statement.
-dpi 96 –ac -lesspointer

우분투 안드로이드 빌드 서버 환경 구성

$ sudo apt-get install git-core gnupg flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32readline5-dev lib32z-dev

$ sudo apt-get install chkconfig ccrypt patch

- Java sdk 설치
$ sudo add-apt-repository "deb http://kr.archive.ubuntu.com/ubuntu/ jaunty multiverse"
$ sudo add-apt-repository "deb http://kr.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse"
$ sudo apt-get update
$ sudo apt-get install sun-java6-jdk
$ java -version // 버전 확인



$ sudo curl http://android.git.kernel.org/repo > repo
$ sudo chmod a+x repo
$ sudo cp repo /usr/local/bin
- Max Open File 변경
- 설정 파일 : /etc/security/limits.conf
- 변경 사항 : nofile 항목이 아래와 같이 4096 이상으로 설정되도록 수정

* soft nofile 4096
* hard nofile 4096
-기본 쉘 bash 로 설정

2011년 3월 5일 토요일

Service와 thread의 차이점

Service에서 수행한다는 것은 Main thread에서 실행을 의미하고, thread에서 수행한다는 것은 Main thread의 자식 thread에서 실행하는 것.

android에서는 apk를 실행하면 보통 하나의 process가 생성( 하나의 apk에 여러 개의 process맵핑도 가능)

process가 생성되면 thread가 하나 생기는데 이를 Main Thread( = UI Thread)라고 함.

thread를 application의 모든 component(activity, service,contentprovider..)들이 공유.

그리고 모든 component event( View UI event , BroadcastRecicever호출등…)를 Main thread에서 처리.

즉, 하나의 activity에서 startService하면 여전히 Main thread가 실행하는 것임.

여기서 Service에서 overload가 많이 걸리는 작업을 수행하면 UI holding이 일어나기도 하고 ANR에도 걸림.


이를 피하기 위해 자식 thread를 생성하여 UI적이지 않은 작업을 수행하고 ANR을 피함
이 thread에서 View 메소드를 직접 호출해서 화면 갱신을 할 수 없음.
( Message Handler를 통해 Main thread에서 다루어져야 함 – AsyncTask class가 이에 대한 wrapper class임.)






.

LogCat 사용법

로그 입력 방법
 Log.변수(태그스트링, 메시지스트링);
 Log.d(“LOGCAT”, “mSKey : ”+mSKey+”, sKey : ”+sKey);

로그 확인 방법
 adb logcat –c : Clear
 adb logcat –f Filename : file로
 adb logcat –d *:Priority
 전체 Debug 메시지를 출력
 adb.exe logcat -s [태그명]:[debug level]변수명
 -s의 의미는 계속 나오게 하는 것!
 adb.exe logcat -s WindowManager:d
 Kernel Message 출력
 adb shell cat proc/kmsg
 radio 로그 확인 방법 (-b가 무슨 의미인지 모르겠지만, 없으면 안됨)
 adb.exe logcat -b radio * ⇐= radio관련 log 출력됨
 File로 저장
 adb logcat -s PowerManagerService:d > log.txt

Sticky intent (또는 Sticky broadcast intent)

Sticky intent 는 말 그대로 끈적끈적한 intent 를 말합니다. ^^;
끈적끈적해서 자신의 역할을 수행한 뒤에도 메모리에 딱 달라붙어서 사라지지 않고 남아있는 것이죠.
보통의 broadcast 된 intent는 자신과 관련된 모든 Broadcast receiver 를 거치고 나면 임무 완료되어 ‘즐거운 퇴근길에 올라’ 메모리 상에서 제거됩니다. 하지만 Sticky intent는 임무 완료 후에도 메모리에 남아 있는다는 사실! (정확하진 않지만 해당 event에 대한 다음 broadcast 가 있을 때까지 남아 있는 것 같습니다)

그럼 이 sticky intent를 어디에 사용할까요?

안드로이드에서 Broadcast receiver 는 두 가지 방법을 통하여 등록할 수 있습니다. 정적으로 AndroidManifest.xml 에 태그를 이용하여 등록하는 방법 과 동적으로 Context.registerReceiver() method를 이용하는 방법.

정적으로 등록하는 경우에는 Broadcast receiver 를 등록한 app의 실행 여부와 관계없이 관련 Broadcast intent 가 있으면 등록한 Broadcast receiver 의 onReceive() method가 호출됩니다. 무의미한 상황에서 CPU와 배터리를 사용하는 셈이 될 수도 있는 것인데요. 만약 우리가 작성한 app 이 실행 중인 상황에서만 Broadcast receiver 가 동작하기를 원한다면 정적인 등록 방법은 알맞지 않겠죠.

그래서 아래와 같이 동적으로 등록하는 방법을 사용할 수 있겠습니다.
registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1){
//TODO
}
}, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

짐작하시겠지만, 동적으로 등록하는 경우엔 당연히 Broadcast receiver 를 등록한 이후에 발생하는 intent 만을 수신하게 됩니다. 그런데 여기서 문제가 발생합니다.
예를 들어, Status Bar 에 배터리의 상태를 표현하려고 동적으로 Broadcast receiver 를 등록했는데, 이미 해당 intent (Intent.ACTION_BATTERY_CHANGED 를 action으로 갖는 intent)가 broadcast 된 후라면 그 Broadcast receiver 는 동작하지 않게 됩니다. 다음 broadcast 가 있을 때까지 말이죠. 따라서 intent 가 아닌 다른 방법으로 배터리 상태를 확인하는 코드를 추가해야 할지도 모릅니다.
하지만 편리하게도 안드로이드에서는 위와 같은 상황이 일어나지 않습니다. 배터리의 상태를 알리는 intent 는 Sticky intent 이기 때문이죠. 다시 말해 이 intent는 자신의 임무를 완료한 후에도 메모리에 남아 있다가 자신과 관련된 Broadcast receiver 가 등록되면 해당 receiver에 바로 전달되는 것입니다.

참고로 안드로이드 시스템에서 broadcast 하는 Sticky intent는 아래와 같습니다.
1) 배터리 관련 : Intent.ACTION_BATTERY_CHANGED
2) 저장소 관련 : Intent. ACTION_DEVICE_STORAGE_LOW
3) Docking 관련 : Intent. ACTION_DOCK_EVENT
4) Network 관련 : ConnectivityManager.CONNECTIVITY_ACTION

참고) http://blog.naver.com/PostView.nhn?blogId=huewu&logNo=110090854068

2011년 3월 4일 금요일

application에서 UI의 반응 속도를 높이는 방법

제목은 ‘Speed up your Android UI’ 로 android activity에서 화면 갱신 속도를 높일 수 있는 방법을 설명하고 있습니다.
http://www.curious-creature.org/2009/03/04/speed-up-your-android-ui/


결론은
1. Activity가 전체 화면을 그리는 UI라면 (예: 화면 전체에 그림을 출력하는 경우, Gallery에서 사진을 전체화면으로 보는 경우) background를 그리지 않게 하여 background가 그려지는 시간을 줄일 수 있다.:
Android에서 View가 그려지는 놈은 DecorView인데 DecorView는 theme에서 background로 설정된 drawable 객체로 한번 지워(그려)집니다. 그런데 Activity가 전체화면 UI라면 background로 전체 화면을 지운 후 다시 전체화면을 UI에 맞게 다시 그릴 것이기 때문에 background로 지우는 작업이 필요 없다. 이 background로 지우는 작업이 T-Mobile G1에서는 3 millilseconds정도 된다고 합니다.
Windows Mobile에서 WM_ERASEBACKGROUND 메시지를 App에서 처리하여 윈도우화면이 erase되는 시간을 줄여 껌뻑임을 막았었는데 개념상 동일한 내용입니다.

2. 자신의 배경을 가진 Activity의 시작시간(perceived startup performance of some of your activities.) 을 줄이려면 activity가 사용하는 배경 이미지를 theme의 background로 적용하라.
activity가 실행 될 때 기본 동작은 default theme의 background로 그린 후 activity의 background로 다시 그리는 것입니다. 따라서 theme의 background에 activity에서 사용할 이미지를 지정하여 전체 화면 갱신을 한번만 하자.

Eclipse 상에서 Android Framework단 원하는 특정 APK(e.g Home, Calendar, etc)만을 Customization 또는 기타 수정 작업을 진행 하기 위한 방법

Eclipse 상에서 Android Framework단 원하는 특정 APK(e.g Home, Calendar, etc)만을 Customization 또는 기타 수정 작업을 진행 하기 위한 방법(별도의 전체/부분 Platform build 과정을 거치지 않기 때문에 빠른 개발 진행이 가능)

(*) 선행 조건/과정
-> Android Eclaire Platform Full Source 빌드 완료 가정!

(1) 작업 하고자 하는 특정 APK를 로컬 다른 작업 폴더에 Copy 후 Eclipse에서 Import 한다. => 다수 에러 발생 (해당 라이브러리를 로딩 하지 않았기 때문 임)
(2) \mydroid\out\target\common\obj\JAVA_LIBRARIES와\mydroid\out\target\common\obj\APPS 를 로컬 다른 작업 폴더에 Copy 함
(3) Android Home의 경우
framework_intermediates와 core_intermediates 내 classes.jar를 User library 타입으로 가져 온다. => 정상 빌드 확인

(*) 이제 Eclipse상 특정 APK 소스 로딩 및 빌드 과정이 끝났습니다. 이제 해당 APK를 Emulator 등에 재 배포/설치 해서 디버깅 하기 위해서는 Signing 과정을 다음과 같이 수행 해야합니다.

(*) Application Signing 관련 부연 설명 - 서명되지 않은 애플리케이션을 설치하려고 하면I[NSTALL_PARSE_FAILED_NO_CERTIFICATES] 에러가 발생 합니다.
현재 Eclipse ADT 환경에서 안드로이드 애플리케이션을 개발하면서, 서명 작업을 의식하지 않고 자연스럽게 타겟에 애플리케이션을 설치하고 테스트 할 수 있는 것은 해당 애플리케이션을 빌드 하면서 자동으로 apk에 서명까지 함께 해주기 때문 입니다.

APK 서명에는 Debug/Release 모드가 있는데, Eclipse는 Debug 모드로 서명을 해줍니다.
(Eclipse가 APK를 디버그 모드로 서명하기 위한 키/인증서(key/certificate)는 "$HOME/.android/debug.keystore" 파일에 저장되어 있습니다.)
Eclipse->Preferences->Android->Build 메뉴를 보면 Default로 debug keystore 파일이 설정되어 있는 것을 확인하실 수 있습니다.

(4) 해당 APK의 서명 테스트 키를 확인 하고 로컬 폴더에 Copy 합니다.

=> Android 제공 하는 서명용 테스트 키는 다음과 같습니다.
• testkey -- a generic key for packages that do not otherwise specify a key.
• platform -- a test key for packages that are part of the core platform.
• shared -- a test key for things that are shared in the home/contacts process.
• media -- a test key for packages that are part of the media/download system.

해당 APK의 Android.mk 파일을 보면 LOCAL_CERTIFICATE 값을 보고 맞는 키를 쓰시면 됩니다. 만약 LOCAL_CERTIFICATE 변수가 정의돼 있지 않으면 testkey 키로 서명하시면 됩니다.

(5) Android Home의 경우 Shared 설정 이기 때문에 shared.pk8, shared.x509.pem을 Copy 해 옵니다.

(6) Eclipse상에서 일반 유저 애플리케이션처럼 서명 작업을 신경 쓰지 않고 Run As 또는 Debug As로 개발/디버깅/테스트 할 수 있게 안드로이드 Debug용 keystore를 다음과 같이 만든다.

windows command 실행 예) -> 입/출력 파일명 말고 나머지는 모두 동일하게 typing 해 주십시오.

# openssl pkcs8 -inform DER -nocrypt -in shared.pk8 -out shared.pem
=> copy해 온 .pk8 파일을 가지고 .pem 생성
# openssl pkcs12 -export -in shared.x509.pem -inkey shared.pem -out shared.p12 -name androiddebugkey
=> shared.p12 생성
# keytool -importkeystore -deststorepass android -destkeystore sisan.android.debugging.shared.keystore
-srckeystore shared.p12 -srcstoretype PKCS12 -srcstorepass android
=> sisan_android_debugging_shared.keystore 생성

(7) (6)번 과정에서 만들어진 .keystore 파일을 Eclipse->Preferences->Android->Build 상 Custom debug keystore로 설정 하시면 됩니다.

Eclipse상에서 F11 디버깅 시작!

Garbage Collection

어디선가 퍼왔음...

목차
________________________________________
1. Garbage Collection이란?
2. JVM GC 설계자의 고민 - Generation
3. JVM GC 설계자의 고민 - GC Algorithm
4. JVM의 Garbage Collector
5. Serial Collector
1. Young Generation GC
2. Tenured Generation GC
6. Parallel Collector(Throughput Collector)
1. 언제 쓰면 좋지?
7. Parallel Compacting Collector -> 보강 필요
8. Concurrent Mark-Sweep(CMS) Collector
1. Tenured Generation GC
2. CMS Collector의 안좋은 점
3. Incremental Mode
4. 언제 쓰면 좋지?
9. GC와 관련된 JVM command line option들
10. 참고 문헌 및 Web Site

Garbage Collection이란?#
program이 점유하여 쓰고 있는 memory 공간 중 더 이상 쓰지 않는 memory 영역을 Garbage라 합니다. 예전의 programming 언어(이하 PL)들은 programmer가 이 garbage를 OS에 반납하는 code를 일일히 작성해야 했습니다(C 좀 하셨던 분들은 malloc()과 free() 함수를 기억하실 것입니다). 그런데 사람이 원래 '화장실 가기 전과 화장실 가고 난 후가 다르다'고, 반납하는 code 작성을 빼먹고 그랬습니다. 그러면 그 program이 도는 machine의 momory가 야금야금 줄어드는 현상이 발생하고(전문 용어로 memory leak이라 하는데, 이런 문제는 일정 시간이 경과해야 발견할 수 있는, 참 찾기 어려운 bug입니다) 급기야는 그 machine의 memory과 꽉 차서 system이 뻗는 현상이 발생합니다.
현대적인 언어들은 이러한 성가신 작업을 자동으로 해 주고 이를 바로 Garbage Collection(이하 GC)이라고 합니다. 그리고 Java도 바로 그 현대적인 PL에 들죠! 아싸~! 바로 JVM 덕분입니다.
그런데, 그런데 말이죠, 'There's no silver bullet in the world'라고, 이 성가신 작업을 programmer들이 안해도 되긴 하나 결코 만능은 아니라는 거~! GC를 자동으로 하는 것은 좋은데, GC를 수행할 때 JVM 상의 program들 수행을 모두 멈추고 GC를 수행하므로 program 성능이 참 나쁘게 하는 부작용도 있습니다. 그래서 JVM의 GC를 잘 안 나게 하고, 나더라도 금방 되게 하는 것이 중요한 성능 향상 수단이 됩니다.



JVM GC 설계자의 고민 - Generation#

위 graph가 표시하는 것이 뭘까요? 결론을 말하면, 생긴 지 얼마 안된 객체는 대부분이 얼마지 않아 필요 없어져서 GC 대상이 되고, 오랫동안 살아남는 객체는 적다 되겠습니다. 즉 생긴 지 얼마 안 된 객체들은 GC 수행을 자주 해야 하고, 생긴 지 좀 객체들은 그래도 GC 수행을 자주 할 필요가 없단 말이 되죠.

그래서 JVM 설계자는 JVM의 Heap 영역을 두 부분으로 나누고 한 부분은 생긴 지 얼마 안 된 객체들을 살게 하고(이 부분은 자주 GC를 해 줘야겠죠?) 한 부분은 오래 산 객체들이 모여 살도록 해서(자주 GC를 할 필요는 없죠) - 그러고 보니 정말 Young, Tenured란 이름이 걸맞네요 - 앞 부분은 빠른 수행이 가능한 GC algorithm을 적용하고 뒷 부분은 오래 걸리긴 해도 꼼꼼하게 GC하는 algorithm을 적용하기로 합니다. 그리고 Java 진영에서는 이러한 것을 Generational GC라 부르죠.

그러면, 이 Generational GC는 어떤 장/단점이 있을까요?
• 장점: 위와 말한 바와 같이 각 Generation에 대해 효율적인 GC algorithm 적용이 가능합니다.
• 단점: Java Error 중 유명한 것으로 OutOfMemoryError(흔히 OOM이라고 많이 합니다)가 있는데, 바로 JVM에 더 이상 객체를 생성할 수 없을 정도로 빈 공간이 없을 때 나는 Error입니다. 그런데 이 Error가, 예를 들어 전체 64MB memory가 있는데 이 영역을 다 써서 나는 게 아니라 Young이나 Tenured 영역 중 하나가 다 차 버려도 OOM이 발생합니다. 예를 들어 Young 영역은 널럴해도 Tenured가 꽉 차면 OOM이 나 버리죠.

여하튼 이러한 이유로, JVM은 memory를 다음과 같이 영역을 구분하여 씁니다.

• Young: 생긴 지 얼마 안되는 Java 객체(Object)들이 생기고 사는 곳입니다.
• Tenured: 생긴 지 좀 된 Java 객체들이 사는 곳이죠.
• Perm: Permernemt의 줄임말로, Java 함수의 몸체 부분이나 static 변수 같은 변할 일이 없는 것들이 사는 영역입니다.


JVM GC 설계자의 고민 - GC Algorithm#

위 그림은 또 뭘까요? GC algorithm의 분류 체계라 말할 수 있을 것인데요, 각각을 설명하면 다음과 같습니다.

• Serial / Parallel: GC 대상을 하나의 Garbage Collector 혼자서 모든 garbage를 차례대로 다 치우느냐(Serial), 여러 개의 Garbage Collector가 나눠서 함께 치우느냐 되겠습니다. CPU가 여러 개인 system에서 Serial GC는, 비록 CPU가 여러 개 있어도, garbage collector가 1개만 돕니다. 그런데 Parallel GC는 여러 개가 돌죠. Parallel GC가 당연히 빠르겠지만, 아무래도 좀 더 복잡하고 잠재적으로 memory 단편화를 더 일으킬 수는 있습니다. (일반 PC 쓰는 분들은 Parallel GC는 나랑 해당 사항 없겠네 하시겠지만, 요새 dual core CPU가 일상화되었으니 Parallel GC가 해당 사항이 있을 수도 있겠죠?)
• Stop-the-world / Concurrent: Stop-the-world는 GC 수행할 때 program의 수행을 죄다 멈춘 후 하고, Concurrent는 program 수행을 안 멈추고 GC와 program 수행을 같이 합니다. 옛날 JVM은 stop-the-world였기 때문에 GC 하면 죄다 program 수행을 일단 정지 시키므로, 성능 나쁘게 한다고 악명이 높았죠. 여하튼 Concurrent가 일견 더 좋아 보일 수 있으나, GC 수행 중 같이 도는 program이 쓰레기를 만들어 놓고, 그리고 그 쓰레기를 치우지 못할 개연성은 있습니다.
• Compacting / Non-Compacting / Copying: 쓰레기를 수집하고, 그 쓰레기가 있던 자리는 빈 공간으로 남습니다. 그리고 이런 짓거리를 여러 번 하다 보면, memory는 여기 저기 구멍 난 누더기처럼, 빈 공간과 Java 객체가 쓰고 있는 공간이 여기저기 널려있게 됩니다. 이를 단편화(fragmentation)라 하는데, GC를 하는 김에 이런 단편화 제거도 싸그리 하여 연속된 빈 공간을 확보하는 작업도 할 필요가 있습니다. 왜냐하면 연속된 빈 공간이 있어야 큰 Java 객체가 생겨도 빈 공간 찾아 해메는 시간을 줄이거든요. 이러한 단편화 제거를 compacting이라 하고, compacting은 GC하여 쓰레기를 날린 후 compacting을 하는 것이고, non-compacting은 배째라 하고 안해버리는 것이죠. non-compacting도 나름 타당한 것이, compacting에도 분명 시간이 걸리므로 전체적인 GC 시간을 길게 하는 요소기는 하거든요. 대신 memory의 누더기 현상은 피할 수 없고, 큰 Java 객체라도 만들어야 하면 빈 메memory 공간 찾느라 시간 좀 걸리겠죠. copying은 GC 뒤 살아남은 객체를 옮겨서 compacting을 하기 보다는 그 객체를 특정 영역으로 복사하고, 원본 객체는 쓰레기로 간주하여 추후에 해제되게 하는 방식의 GC법입니다. 영역을 정해놓고 영역 전체를 무차별적으로 날려버리는 식의 쓰레기 수집이 가능하고, 그럼으로써 연속된 공간도 아울러 확보하는 것이 장점이나, 아무래도 복사하는데 시간이 들고, 살아남은 객체와 원본 객체라는 두 벌의 객체가 존재하므로 memory 사용량이 다른 방식에 비해 좀 큰 게 사실입니다.


JVM의 Garbage Collector#
Sun Microsystems가 배포하는 Java SE 5 update 6 이후 version의 JVM에는 4개의 Garbage Collector가 있습니다.


이 중 기본적으로 쓰이는 Collector는 Serial Collector입니다. 그럼, 각각을 살펴볼까요?


Serial Collector#
Serial Collector는 Serial, Stop-the-world 방식의 collector입니다. 그리고 java command line option으로 -XX:+UseSerialGC를 주면 JVM은 이 collector를 씁니다. 그런데 young generation과 tenured generation을 처리하는 방식이 좀 틀립니다. 이 각각을 자세히 살펴보겠습니다.

Young Generation GC#
serial collector는 young generation GC에 copying 방식을 씁니다. 즉 serial collector가 young generation을 GC하는 방식은 serial, stop-the-world, copying 방식이라 할 수 있죠.

• 자바 객체는 Eden 영역에 태어납니다. 이를 memory 할당(allocation)이라 합니다. 즉 Eden은 모든 Java 객체의 고향이죠.

• Eden 영역이 간당간당해져서 GC 필요성이 생기면 살아야 할 놈은 S0으로 복사합니다.

• Eden 영역을 다 날립니다(사실은 이때 S1 영역도 같이 날립니다)!

• 또 Eden에 Java 객체들이 태어납니다.

• 그러다 또 Eden이 간당간당하면 이번엔 살아야 할 놈들을 S1으로 복사합니다. 이 땐 S0에서도 살아야 할 놈들은 S1으로 복사합니다.

• 또 한 번 Eden과 S0를 다 날립니다(으... Java 객체의 대규모 학살...)!

음.... 정말 Survivor 영역은 이름 그대로 생존자가 사는 곳이군요.... 보시다시피 Eden 영역은 말 그대로 Java 객체가 처음으로 태어나는 고향 같은 곳(성경에 따르면 최초의 인류인 아담과 하와가 살던 곳이 Eden이죠?), Survivor 영역은 몇 번의 대학살(?) 끝에 살아 남은 Java 객체들이 사는 곳으로 용도가 구분되어 있습니다. 어쨌든 위와 같이 S0, S1을 번갈아 가며 말 그대로 생존자를 끌어모으고 나머지 영역은 다 날리는 식으로 GC를 수행합니다.

또한 이렇게 S0, S1을 왔다갔다하면서 질기게 생존하는 Java 객체들은 어느정도 와리가리를 하면 Tenured 영역으로 옮겨가는데 이를 승진(promotion)이라고 합니다. Tenured 영역으로 넘어갔다는 이야기는 어느 정도의 생존성을 보장 받았다는 이야기니 승진이라고 봐도 되겠죠?

Tenured Generation GC#
Serial Collector의 Tenured 영역을 위한 GC algorithm은 Mark - Sweep - compact란 방식을 취하는데, 이는 글자 그대로 먼저 Java 객체를 주욱 훑어 쓰레기에는 표시를 하고, 그 다음 쓰레기로 표시한 Java 객체가 차지하는 memory 영역을 해제한 다음, 살아남은 객체들을 한 곳으로 싹 몰아 연속된 큰 빈 공간을 확보하는 방식입니다.
그럼 이것도 차근차근 GC되는 과정을 살펴보도록 하겠습니다.

mark phase에서는 쓰레기를 식별하여 표시하고(mark), sweep phase에서는 표시한 쓰레기를 날린 다음, compact phase에서는 Tenured 영역의 시작으로 살아남은 객체를 좌악 이동시켜서 compaction을 합니다(이를 sliding compaction이라 합니다. 말 그대로 살아남은 객체가 스르륵 미끄러지듯 이동하죠?)


Parallel Collector(Throughput Collector)#
Serial Collector의 young generation GC 기능 개선판으로, 간단하게 말하면 collector를 하나만 돌리는 것이 아니라 한꺼번에 여러 개 돌려 시간 단축을 꾀합니다. multiprocessor system에서나 빛을 보는 방식입니다만, PC용 CPU도 dual core CPU가 나오는 상황이므로 꽤 쓸만합니다. 이 collector의 목적은, 아무래도 자주 발생하게 마련인 young generation GC 시간을 단축시켜 전체적인 program의 thoughput을 개선하기 위함입니다. 그런데 tenured generation GC는 Serial GC의 그것과 똑같으며, young generation GC의 경우도 하나하나의 collector가 수집하는 방식은 serial GC의 그것과 같습니다.

이 collector를 쓰기 위한 command line option은 -XX:+UseParallelGC입니다.



파랑 화살표가 일반 program 수행, 주황색 화살표가 collector 수행을 나타냅니다. idea는 간단합니다. multiprocessor system에서 일단 모두 program 수행을 멈추어 놓고 1개가 아닌 여러 개의 garbage collector가 돌아 쓰레기를 처리하여 수행 중단 시간 단축을 꾀합니다. 하나하나의 GC가 처리하는 Young Generation의 경우, serial collector의 young generation GC와 같습니다.

언제 쓰면 좋지?#
여러 개의 CPU를 가지고, program 수행 중단이 자주 일어나지 않아서 제약이 덜하긴 하지만, 한번 중단되면 시간이 좀 긴 상황에서 적용하면 개선 효과가 큽니다. 이런 류의 program 예는 batch 처리, 과금, 급여 처리, 과학 기술 관련 연산 등을 꼽을 수 있습니다(전부 덜 interactive한 성격의 program들이군요).


Parallel Compacting Collector -> 보강 필요#
이 collector는 Java SE 5 update 6에서부터 처음 나온 collector입니다. Parallel collector와의 차이점은 이 놈은 tenured generation을 위한 새로운 GC algorithm을 적용했다는 점이죠. 점진적으로 Parallel Collector는 이 collector로 대체할 예정이라네요. 허긴, Parallel Collector는 Tenured Generation GC는 나아진 것이 없죠. young generation GC algorithm은 Parallel Collector와 똑같으므로 넘어가겠습니다.


Concurrent Mark-Sweep(CMS) Collector#
위에서 살펴 본 collector들이 단위 시간당 최대 throughput 획득이 목적이라면, 이 collector는 빠른 응답 시간(response time)이 목적입니다. 이 목적을 달성하기 위해서 본 collector(응? bone collector?)는 Tenured Generation을 청소할 때 유발되는 Stop-The-World 시간을 최소화하는 전략을 세웁니다. 이 collector가 Young Generation을 청소하는 algorithm은 Parallel Collector와 똑같으므로 여기서는 Tenured Generation 청소 algorithm만 알아봅니다.

Tenured Generation GC#
CMS Collector의 GC는 initial mark, concurrent mark, remark, concurrent sweep의 4단계(phase)로 나뉩니다. 그러고보니 한 번 쓰레기 청소 하려고 쓰레기라고 표시하는 작업을 무려 세 번이나 하는군요. Bingo~! 표시 작업을 나눠서 함으로써 한 번 멈출 때 길게 멈추는 것이 아니고 잠깐 잠깐 멈춘 여러 번 멈춤으로써 응답 시간을 개선하는 것이 이 collector 동작 방식의 핵심입니다(전체적인 stop-the-world 시간을 짧게 하려는 것이 아닙니다! 전체 잠깐 잠깐 멈춘 시간을 모두 합산하면 다른 collector의 stop-the-world 시간보다 더 걸릴 수도 있습니다).

그러면 각각을 찬찬히 뜯어먹어 보가써~요! 먼저 아래 그림과 같은, 곧 GC를 해야 하는 JVM memory 상태가 있다고 합시다.

Thread A, B는 현재 돌고 있는 program이고 heap에는 가 ~ 파 까지의 Java 객체가 존재하는 상황입니다. 이 Java 객체 중 살 놈과 죽을 놈을 판별해서 GC를 해야 하는 거죠.

• initial mark: 일단 모든 program의 수행을 중단시키고 각 program에서 직접 참조하는 Java 객체들을 살 놈으로 표시한 다음 멈췄던 program 수행을 재개시킵니다. 여기서는 Thread A, B를 멈추고 그 둘이 직접 참조하는 가 ~ 마 객체를 살 놈으로 표시한 다음, Thread A, B를 다시 수행시키죠. 모든 살아야 할 객체를 다 식별하는 것이 아니라 program들이 직접 참조하는 객체만 살 놈으로 인식하는 작업을 수행하므로 program 중단 시간이 짧죠.


• concurrent mark: Initial Mark 후 다시 표시 작업을 수행하는데 이 때는 program을 안 멈추고 표시 작업을 합니다. 그 다음 initial mark 때 살 놈으로 표시당한 객체들을 주욱 훑으면서, 이 객체들이 참조하는 다른 객체들을 살 놈으로 표시합니다. 이 때는 program 수행을 중단하지 않지만, 부작용(side effect)이 있긴 있습니다. 위 그림에서는 바로 6번과 하 객체 같은 것들인데요, program을 중단시키지 않으므로 concurrent mark 작업 하는 사이에 GC 이후에도 살아남아야 할 객체가 생길 수가 있습니다. 이래서 remark 단계가 더 있는 거죠.


• remark: Concurrent Mark 동안 생긴, 살아남아야 할 객체들을 식별하는 단계입니다. 이 단계는 살 놈, 죽을 놈을 구별하는 최종 단계로, 이 때에는 표시하는 동안 살아남아야 할 객체가 또 생기면 안되므로, 모든 program을 중단시키고 표시 작업을 합니다. 위 그림에서 회색으로 표시한 자 ~ 파 객체는 최종적으로 쓰레기로 표시된 객체를 나타냅니다.

• concurrent sweep: 쓰레기를 싹 날리는 단계입니다. program 수행을 중단하긴 하지만 Collector가 여러 개 돌면서 날리므로 속도가 빠릅니다.

어떨 땐 collector 여러 개를 한꺼번에 돌리고, 어떨 땐 하나만 돌리고, 어떨 땐 program을 죄다 멈추고, 어떨 땐 program을 안 멈추고... 헷갈리죠? 아래 그림을 보시면 좀 명확할 겁니다.

파랑 화살표가 일반 program 수행, 주황색 화살표가 collector 수행을 나타냅니다. stop-the-world pause가 자주 발생하긴 하지만 멈추는 시간 자체는 짧죠?

CMS Collector의 안좋은 점#
세상에 공짜가 어딨나요, 이 collector의 안 좋은 점도 살펴봅시다.

1. 다른 collector는 표시를 수집 한 번 하려면 표시 작업을 한 번 하지만, 이 collector는 세 번이나 표시합니다. 짐이죠.
2. CMS Collector는 쓰레기를 수집하여 memory를 해제하지만, 다른 collector와는 달리 compaction을 하지 않습니다. 그래서 memory 단편화는 필연적입니다. 또한 tenured 영역으로 어떤 객체가 승진되어 오면, 이 객체 덩치가 들어갈만한 빈 공간을 찾느라 시간이 걸리는 짐이 더 생깁니다. 무엇보다도, 다른 collector들은 compaction을 하므로 빈 공간을 인식하려면 빈 공간의 시작 주소만 알면 되지만, 이 collector는 진짜 Free List라는 것을 유지해야 합니다. 이 또한 짐이죠.
3. 이 collector는 다른 collector보다 heap 공간을 더 먹습니다. concurrent mark 시 다른 program들이 안 멈추고 돌기 때문에 계속 객체가 생길 수 있고, 그러다보니 tenured 영역으로 객체가 승진할 수 있기 때문에 실제로 memory가 꽉 차서 GC를 수행하다가는 이런 상황이 발생할 때 대책이 안 설 수 있습니다. 또한 program이 돌면 새 객체만 생기나요? 쓰던 객체 더 이상 안 쓸 수도 있잖아요? 역시 concurrent mark 시 기껏 살 놈으로 표시했더니만, 고 사이에 실제로는 쓰레기가 되는 객체도 있긴 있습니다. 이런 놈들을 floating garbage(붕 뜬 쓰레기로 번역하면 딱이겠는걸요~)라 부르고, CMS collector는 floating garbage도 생길 개연성이 충분하다는 점입니다. 결론은, 이러한 전차로 이래저래 CMS collector는 다른 collector보다 여유 공간이 더 필요합니다.
4. 이 collector는 memory 단편화가 생긴다고 했죠? 이 단편화 뒤치다꺼리를 하려면, CMS collecotor는 객체의 평균 크기를 추적하고, 향후 memory 요구 사항을 추정하고, 간간히 free list를 주욱 훑어서 free block을 합치거나 나누거나 하는 작업들도 해 줘야 합니다.

아까도 말씀드렸듯, 이 Collecor는 다른 collector와는 달리 "memory가 꽉 찼네? 슬슬 GC해 볼까?" 했다가는 대책 안 섭니다. 만약 memory가 꽉 차 버리면, 제 아무리 CMS Collector라도 Serial Collector나 Parallel Collector 등이 GC하는 방식이자, stop-the-world 시간이 많이 걸리는 방식인 Mark-Sweep-Compact 전술을 써야 하죠(실제로 씁니다). 이런 불상사(?)를 막으려면 CMS Collector는 이전의 GC 시간 및 얼마나 오랫동안 Tenured 영역이 점유당했는지를 감안한 통계에 기초하여 GC를 개시합니다. 또한 Tenured 영역이 일정 비율 이상 차면 GC를 수행하는 방법도 있는데, JVM의 command line option인 -XX:CMSInitialOccupancyFraction=으로 조정 가능합니다. 은 점유 당한 Tenured 영역의 precentage를 나타내는 양의 정수를 쓰며 default는 68입니다(즉 68%의 tenured 영역이 차면 GC를 수행하는 것이 default라는 거죠).

Incremental Mode#
CMS Collector의 약점을 살펴보면, concurrent mark가 문제(?)라는 것을 알 수 있습니다. remark가 필요한 것도, 그리고 floating garbage가 생기는 것도 program을 안 중단시키고 표시를 하다 보니 야기되는 문제입니다. 그렇다면 concurrent mark 상태를 길게 가져가는 것보다 짧게 가져가는 것이 이러한 골아픈 문제를 덜 일으키겠죠? 그래서 JVM은 incremental mode라는 것을 도입했는데, 이 mode는 concurrent mark 상태를 간간히 멈추고 program들에게 처리를 양보합니다. CMS Collector는 시간을 잘게 나누어서, young generation GC 사이사이에 틈틈히 concurrent mark를 수행하도록 schedule합니다(음, 일종의 시분할 scheduling이군요). 이 mode는 특히 CPU 갯수가 1, 2개 정도 밖에 안되는 system에서 CMS collector를 수행할 때 좋습니다.

언제 쓰면 좋지?#
여러 개의 CPU를 가지고, client에게 빠른 응답을 줘야 할 program 구동에 적합합니다. 예를 들면 Swing으로 GUI를 구성한 Desktop Application이나 JSP나 Servlet을 처리하는 프로그램들 적격이겠네요. 이런 program들은 응답 시간이 오래 걸리면 사용자가 짜증을 내거나 program이 뻗은 줄 아니까요.


GC와 관련된 JVM command line option들#


GC 관련 command line option을 Mind Map으로 그려봤습니다. Option에 대해서는 Option 이름, 의미, 그리고 default 값을 알아야 합니다. 이러한 자세한 사항은 Java HotSpot VM Options를 참조하세요.

참고 문헌 및 Web Site#
1. Java HotSpot Garbage Collection
2. Java SE 6 HotSpot Virtual Machine Garbage Collection Tuning
3. Java HotSpot VM Options
4. developerWorks: IBM Developer Kits
5. IBM JDK 6.0 Information Center
6. Java™ technology software HP-UX 11.0 & 11i
7. JVM Garbage Collection Options
8. JVM Options

Eclipse Heap Memory 분석 tool

DDMS -> device tab에서 process 선택 -> Dump HPROF file 버튼 클릭

이게 heap을 덤프하는 툴인데, 이를 분석할수 있게 해주는 tool입니다.
Eclipse plugin으로 설치가능하고, stand-alone버전으로 설치가능합니다.
(plug-in으로 설치하면, dump뜸과 동시에 tool이 같이 떠서 편하네요.)

download는 아래에서 받으시면 됩니다.
공식홈-http://www.eclipse.org/mat/
eclipse plugin으로 설치 - eclipse>help>install new software>http://download.eclipse.org/mat/1.0/update-site/
stand-alone버전 download - http://www.eclipse.org/mat/downloads.php

Intent 구성요소

Component Name - Intent를 전달 받을 컴포넌트 명
Action - 동작
Category - 대상의 종류
Data - 데이터 위치와 타입을 결정
Extra - 기타 정보
Flag - System에 의한 Activity launch 방법과 launch후 Activity를 다루는 방법



Intent Filter [:AndroidManifest.xml 에 설정 ]

- Component의 처리 능력, 즉 Component가 수신하고자 하는 Intent의 집합을 기술

- Activity, Service, Broadcast Receiver가 자신들이 처리할 수 있는 Implicit Intent의 종류를 System에 알려주기 위해 하나 이상의 IntentFilter를 가질 수 있음(Explicit Intent는 항상 Target에 전달됨)

- Component 실행 전에 그 기능을 알아햐 하므로 AndroidManifest.xml을 통해 정의됨
cf> BroadcastReceiver의 경우 Context.registerReceiver()를 통해 동적으로 Filter 등록 가능

- Implicit Intent는 Action, Data, Category 세 개의 영역에 대하여 Test퇴고 이를 모두 통과해야 Component에 전달됨.

- 만약 intent가 하나 이상의 Activity 또는 Service의 Filter를 통과할 수 있다면, 사용자들에게 어떤 Component가 활성화 되어야하는 지 묻게 되고, 만약 어떠한 Target도 발견되지 않으면 예외발생.

Enum 초기 값

public enum Week {Sun, Mon, Tues, Wed, Thurs, Fri, Sat }

1.     Java 에서 위와 같이 enum 을 선언하면 각 enum 상수는 name ordinal 이라는 값이 각각 초기화 됩니다.
-       name : enum 상수의 이름
-       ordinal : enum 상수의 순서 (0부터 시작)
예를 들어 Week.Tues (name, ordinal) 값은 (Tues, 2) 가 됩니다.
2.     Week day; 와 같이 enum 상수의 reference 를 선언하면 day의 초기화는 다음과 같습니다.
-       클래스의 멤버 변수일 경우 null 로 초기화
-       Local method 의 경우는 알 수 없음 (반드시 초기화 하고 사용. 컴파일 안됨)
Cf> * 클래스의 멤버변수 일 경우
- int, char, byte, long, float 등의 primitive 0 으로 초기화
         - boolean false 로 초기화
         - reference 변수는 null 로 초기화
     * Local method 의 변수일 경우 알 수 없음 (반드시 초기화 하고 사용. 컴파일 안됨)
3.     기타 enum 의 특징
-       Enum 객체는 singleton 이다
-       enum 상수는 method 내부에 선언하여 사용할 수 없다

Android Monkey Test

안드로이드 레퍼런스 : http://developer.android.com/guide/developing/tools/monkey.html

ex) browser monkey .. cmd로 consol에서...

C:\> adb devices
List of devices attached
02701042419FF597             device

C:\>adb -s 02701042419FF597 shell monkey --hprof -v -p com.android.browser -s 10 5000 > Monkey_log.txt


이런식으로 bat 파일로 만들면 손쉽게 로그를 뽑아낼 수 있다.



옵션 번역은 http://blog.daum.net/whisperlip/7287317 <-- 참고

General
--help  도움말 표시
-v  출력 레벨 조정 (레벨 0 - 디폴트로 시작, 종료 등의 최소한의 출력, 레벨 1 - 어떤 이벤트를 발생 시켰는지 상세 표시, 레벨 2 - 레벨 1보다 더 상세한 정보 출력)

Events
-s <seed>  monkey는 무작위 이벤트를 발생시키지만 seed를 지정하면 에러를 발견하고 수정한 후 이전과 동일한 이벤트를 발생시킬 수 있다. 같은 이벤트를 발생시키고자 한다면 같은 seed값을 지정하면 된다.
--throttle <milliseconds>  이벤트 발생 속도를 지정. 지정하지 않는 경우에는 가능한 빠르게 이벤트를 발생시킨다.
--pct-touch <percent>  터치 이벤트 발생 비율을 조정한다.(터치 이벤트는 화면의 한 곳을 눌렀다 떼는 신호를 말한다)
--pct-motion <percent>  모션 이벤트의 발생 비율을 조정한다.(모션 이벤트는 화면 한 지점을 누르고 무작위로 다른 지점으로 이동 후 떼는 것을 말한다) 
--pct-trackball <percent>  트랙 볼 이벤트의 발생 비율을 조정한다.(하나 이상의 무작위 이동 이벤트를 말하며 가끔씩 한번의 클릭이 올 수 있다) 
--pct-nav <percent>  "basic"네비게이션 이벤트의 발생 비율을 조정한다.(네비게이션 이벤트란 H/W(폰)의 상하좌우 방향키 입력을 말한다.) 
--pct-majornav <percent>  "major"네비게이션 이벤트의 발생 비율을 조정한다.(백 키나 메뉴 키, 방향키의 가운데 키와 같은 이벤트를 말한다.)
--pct-syskeys <percent>  시스템 이벤트의 발생 비율을 조정한다.(Home 버튼, 백 키, 전화 걸기, 전화  끊기, 볼륨 조절과 같은 이벤트를 말한다.)
--pct-appswitch <percent>  엑티디비 실행 비율을 조정한다. 패키지 안의 다른 액티비티로 변환되는 것을 말한다. Monkey는startActivity()에 의한 Activity 실행도 테스트한다. 

Constraints
-p <allowed-package-name  테스트할 패키지 명을 지정한다. 지정이 없는 경우에는 시스템 모든 패키지를 대상으로 한다. -p <package1> -p <package2>와 같이 복수의 패키지 지정도 가능하다. 테스트할 패키지 내에서 다른 패키지의 액티비티를 사용하고 있다면 그 패키지를 지정한다. 
-c <main-category>  카테고리를 지정한다. 지정하지 않으면 Intent.CATEGORY_LAUNCHER 또는, Intent.CATEGORY_MONKEY를 지정한 것으로 된다. 복수의 카테고리를 지정할 때에는 -c 옵션을 카테고리마다 지정한다.

Debugging
--dbg-no-events  액티비티의 실행은 하지만 이벤트를 발생시키지는 않는다.
-v  커맨드와 함께 사용하하고 최상의 결과를 얻기 위해 -v의 조합과 함게 하나 이상의 패키지 제약과 non-zero throttle로 30초 이상 monkey 실행을 유지한다. 
--hprof  프로파일 리포트를 작성한다. 리포트 파일은 data/misc 디렉터리에 작성되고 파일 사이즈는 5M 이상이 되므로 주의한다. Traceview 어플리케이션 도큐먼트에 상세하게 설명되어 있다.
--ignore-crashes  지정을 하지 않는 경우에 Monkey는 어플리케이션의 크래쉬나 익셉션이 발생하면 정지된다. 이 옵션을 지정하면 이벤트 개수만큼 계속 이벤트를 보내게 된다.
--ignore-timeouts  지정을 하지 않은 경우에 Monkey는 타임 아웃 에러가 발생하면 정지한다. 타임 아웃 에러는 Application Not Responding 다이얼로그와 같은 것이 나올 때는 말한다. 옵션을 지정하면 에러 후에도 이벤트를 계속 발생시킨다.
--ignore-security-exceptions  지정 하지 않은 경우네 Monkey는 시큐리티 익셉션(퍼미션 에러)가 발생하면 정지한다. 이 옵션을 지정하면 에러 후에도 이벤트를 계속 발생시킨다.
--kill-process-after-error  통상 에러에 의해 Monkey가 정지될 때에는 테스트 된 어플리케이션은 fail이 나지만 프로세스는 돌고 있다. 이 옵션을 지정하면 시스템에서 프로세스로 종료 시그널(kill)을 보낸다.
--monitor-native-crashes  Android의 시스템 네이티브 코드에서 일어나는 크래쉬를 리포트한다. --kill-process-after-error 옵션을 함께 사용하면 시스템은 정지한다.
--wait-dbg  디버거가 attached 할 때가지 Monkey 실행을 정지한다.