2014년 5월 20일 화요일

[Android] Dalvik VM

Dalvik VM의 개괄적 Source 분석
Dalvik VM은 Android에서 돌아가는 VM이다. 이전에도 포스트 한바와 같이 

Phoneme project, harmony의 코드와도 외형과 핵심 구조체 등이 상당히 유사하다.

이전 포스트 이후 harmony를 대략적으로 분석해 보았으며 

결론은 대략 비슷한데 phoneme와 harmony는 상당히 일치하고 dalvik은 harmony를

바탕으로 만들어진 것이 맞다고 봐야 할듯하다. 

직접적인 코드 외에도 초기화시 로드하는 핵심클래스가 동일한 것들도 몇가지 있다.

예를 들면 다음과 같은 것들이 있다. ( dalvik/vm/Init.c의 dvmJniStartup()을 참고하자. )

org/apache/harmony/luni/platform/PlatformAddress.java
org/apache/harmony/luni/platform/PlatformAddressFactory.java
org/apache/harmony/nio/internal/DirectBuffer.java

간단히 dalvik vm이 실행되는 process를 정리해 보자.

main() -> option을 위한 메모리 할당 -> option 파싱 -> JNI_CreateJavaVM() -> findClass()
-> GetStaticMethodID() -> CallStaticVoidMethod() -> DetachCurrentThread() -> DestroyJavaVM() 

dalvik/vm/main.c의 main() 함수가 entry point이다. 대략 위와 같은 과정을 거치는데 거의 모든 

초기화의 과정이 JNI_CreateJavaVM()에서 이루어진다. 

이후에는 실행시킬 클래스를 findClass()로 실행시킬 main 메소드를 GetStaticMethodID()로 찾는다.

이후 CallStaticVoidMethod()로 class의 main 메소드를 실행시키면 이후의 과정은 main 메소드가

종료할때까지는 intepreter와 dex 파일과의 상호작용이라 봐야 하겠다. 

종료는 DetachCurrentThread()와 DestroyJavaVM()의 두가지 과정으로 볼수 있는데 

Exception에 의한 종료와 정상 종료 크게 두가지 경우가 있을수 있다.

jvm의 경우 일반적으로 따로 Thread를 사용하지 않아도 최소 1개의 쓰레드를 가지고 있는데 

이를 main thread라고 부른다. 일반적으로 static void main(String[] args)으로 선언한 메소드의

코드를 실행하는 역할을 한다고 보면 된다. 


dalvik vm의 전체개요를 이해하기 위해서는 JavaVM, JNIEnv의 두가지 구조체를 이해하는 것이

상당히 중요한데 코드에서는 다음과 같이 정의되어 있다. 

#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif

C로 정의된 JNINativeInterface나 JNIInvokeInterface의 경우 디바이스 드라이버를 개발해

보신분들은 상당히 익숙한 구조일듯한 변수와 함수 포인터의 집합으로 구조체를 만들어 놓았다.

정리해 보면

JNIEnv는 대략적으로 dalvik vm의 환경 설정과 관련된 함수들이 쭈욱 모아져 있는데 

코드를 분석하기 위해서는 우선 CallMethod 계열, GetMethod 계열, FindClass 부분을 우선적으로

보는 것이 좋을 것이다.

JavaVM의 경우는 

DestroyJavaVM, AttachCurrentThread, DetachCurrentThread, GetEnv, AttachCurrentThreadAsDeamon

등의 단촐하게 5가지만 있다. 

JNIEnv와 JavaVM 구조체의 함수 포인터들은 각각

JavaVM: main -> JNI_CreateJavaVM()에서 gInvokeInterface의 값으로
JNIEnv: main()->JNI_CreateJavaVM()에서 gNativeInterface의 값으로 

셋팅된다. 


이후의 과정은 서술한 바와 같이 class를 찾고 class의 static main 메소드를 찾고 이를 호출하는

과정이다. 실제 코드는 다음과 같이 되어 있다.

(*env)->CallStaticVoidMethod(env, startClass, startMeth, strArray);


gInvokeInterface에서 찾아보아도 호출하는 함수의 실제 이름도 CallStaticVoidMethod로 동일하다.

CallStaticVoidMethod는 내부에서 CallStaticVoidMethodV를 호출하는데 이함수는 crags, scope

등으로 찾으려하면 잘 나오지 않는데 이는 코드의 선언이 다음처럼 되어 있기 떄문이다. 



 "##"은 변수 또는 함수의 이름을 접합시켜 주는 역할을 한다. 

위의 코드에서는 CallStatic##_jname##MethodA 처럼 사용됐는데 _jname이 컴파일 타임에 결정되어

반드시 결정되어 있어야만 하며 

예를 들어, CALL_STATIC(jbyte,Byte,result.b, false); 의 코드가 있다면

CallStaticByteMethodA와 같은 함수선언이 된것과 같은 효과가 있다. 

그럼 CallStaticVoidMethodV를 잠깐 살펴보자. 

JNI_ENTER()로 쓰레드의 상태를 변경해준후 바로 dvmCallMethodV()를 호출해준다. 

프레임에 공간을 확보한후에 argument를 처리하고 dvmInterpret()를 호출하여 

본격적으로 dex의 opcode의 처리를 시작한다. 

여기서 부터는 다시 복잡해 지므로 자바의 메소드 호출 방식 및 메소프 스택을 

처리하는 법에 관해서는 다음글에서 이어서 포스트한다. 


[Android] SDCard 남은 용량 체크하기

[Android] SDCard 남은 용량 체크하기

간략히 사용방법에 대해서 포스팅 하자.



아래와 같이 임포트 해준다.
1
2
3
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;

사용되는 실 사용 코드이다.
1
2
3
           StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
        long bytesAvailable  =(long) stat.getFreeBlocks()* (long)stat.getBlockSize();
        Log.d("########", ">>>> bytesAvailable : " + bytesAvailable);


위와같이 사용하면 로그 기록에 남은 용량에 대해서 byte 단위로 나오게 된다^^

이상~ ㅎㅎ

[JAVA] HashMap

[JAVA] HashMap

#. HashMap이란?

  • HashMap은 Map을 구현한다. Key와 value를 묶어 하나의 entry로 저장한다는 특징을 갖는다. 그리고 hashing을 사용하기 때문에 많은양의 데이터를 검색하는데 뛰어난 성능을 보인다.


  • Map 인터페이스의 한 종류로 ( "Key", value) 로 이뤄져 있다.
  • Key값을 중복이 불가능 하고 value는 중복이 가능. value에 null값도 사용 가능하다.
  • 멀티쓰레드에서 동시에 HashMap을 건드려 Key- value값을 사용하면 문제가 될 수 있다. 멀티쓰레드에서는 HashTable을 쓴다

#. HashMap 생성자 / 메서드

생성자 / 메서드
설명 
HashMap()
- HashMap 객체를 생성
ex) HashMap<String , Integer> map = new HashMap<String , Integer>();
      Map<String, Integer> map = new HashMap<String, integer>();
HashMap(int initlalCapacity)
- 지정된 값을 초기 용량으로 하는 HashMap객체를 생성한다.
HashMap(int initlalCapacity, float loadFactory)
- 지정된 값을 초기용량과 load factory의 HashMap 객체를 생성한다. 
HashMap(Map m) 
- 주어진 Map에 저장된 모든 요소를 포함하는 HashMap을 생성한다. 
void clear()
- HashMap에 저장된 모든 객체를 제거한다. 
ex) map.clear();
Object clone()
- 현재 HashMap을 복제하여 반환한다. 
ex) newmap = (HashMap)map.clone();
boolean containsKey(Object Key)
- HashMap에 지정된 키(Key)가 포함되어 있는지 알려준다. 
boolean containsValue(Object Value)
- HashMap에 지정된 값(Value)가 포함되어 있는지 알려준다. 
Set entrySet()
- HashMap에 저장된 Key - Value갑슬 엔트리(키와 값을 결합)의 형태로 Set에 저장하여 반환
ex) map.put("A", 1);
      map.put("B", 2);
      map.put("C", 3);
      Set set = map.entrySet();
      System.out.println("set values are" + set);
      (result) set values : [A=1,B=2,C=3]
Object get(Object Key)
- 지정된 Key 의 값을 반환한다. 
ex) map.put("A", 1);
      map.put("B", 2);
      map.put("C", 3);
      String val = (String)map.get("B");
System.out.println("Value for key B is: " + val);

(result) Value for key B is 2
bloolean isEmpty
- HashMap이 비어있는지 확인한다.
ex) boolean val = map.isEmpty();
Set keySet()
- HashMap에 저장된 모든 키가 저장된 Set을 반환한다.
ex) map.put("A", 1);
      map.put("B", 2);
      map.put("C", 3);
      Set keyset = map.keySet();
      System.out.println("Key set values are" + keyset);
      (result) Key set values are [A,B,C]
Object put(Object Key, Object Value)
- HashMap에 키와 값을 저장.
ex) map.put("A", "aaa");
      map.put("B", "bbb");
      map.put("C", "ccc");
void putAll(Map m)
- Map에 해당하는 모든 요소를 HashMap에 저장한다. 
Object remove(Object Key)
- HashMap에서 지정된 키로 지정된 값을 제거한다.
ex) map.remove("key");
int size()
- HashMap에 저장된 요소의 개수를 반환한다. 
Collection values()
- HashMap에 저장된 모든 값을 컬렉션 형태로 반환한다. 









#. 사용

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

pubilc class HashMapDemo
{
public static void main(String[] args) 
{
HashMap<String, Integer> fruitMap = new HashMap();
fruitMap.put("사과", 1000);
fruitMap.put("배", 2000);
fruitMap.put("자두", 3000);
fruitMap.put("수박", 4000);

// get() --> Key에 해당하는 Value를 출력한다.
System.out.println( fruitMap.get("자두") );   // 3000

        // values() --> 저장된 모든 값 출력
System.out.println( fruitMap.values() ); // [1000, 2000, 3000, 4000]

// HashMap에 넣은 Key와 Value를 Set에 넣고 iterator에 값으로 Set정보를 담에 준다.
// Interator itr = fruitMap.entrySet().interator(); 와 같다.
Set<Entry<String, Integer>> set = fruitMap.entrySet();
Interator<Entry<String, Integer>> itr = set.interator();
while (itr.hasNext())
{
Map.Entry<String, Integer> e = (Map.Entry<String, Integer>)itr.next();
System.out.println("이름 : " + e.getKey() + ", 가격 : " + e.getValue() + "원");
}
}

결과 :
이름 : 사과, 가격 : 1000원
이름 : 배, 가격 : 2000원
이름 : 자두, 가격 : 3000원
이름 : 수박, 가격 :  4000원


참고 >

2014년 3월 14일 금요일

[JAVA] substring Method in String

[JAVA] substring Method in String


Java String 클래스의 substring 메소드

# substring 은 java.lang.String 클래스 안에 있는 메소드

# 문자열을 자를 때 사용

# substring 은 두가지 메소드로 오버라이딩 되어 있음
  • substring(int beginIndex)
    • beginIndex(포함)부터 뒤에 있는 모든 문자열
  • substring(int beginIndex, int endIndex)
    • beginIndex(포함)부터 시작하여 endIndex(포함x)전까지의 문자열

단. 문자열의 시작은 0 부터임을 명심하자!
   ex> 안 녕 하 세 요
          0  1  2  3  4





[JAVA] equalsIgnoreCase method in String

Java String 클래스의 equalsIgnoreCase 메소드
자바에서는 스트링 값의 동등비교시 equals와 equalsIgnoreCase 메소드를 사용한다.
equalsIgnoreCase 메소드의 특징은 다음과 같다.

equalsIgnoreCase : 대소구분 안함, 비교하기전에 크기가 다르면 false 반환