See https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Designated-Inits.html


And here is one more tips.

Sometimes, you may want to initialize all array element with same value.

Then, you can do it as follows if you are using GCC.


static const int arr[10] = {[0 ... (sizeof(arr)/sizeof(arr[0]) - 1)] = 10};



Android VM은 일반적인 Java VM과 마찬가지로 boot class path와 class path를 지원한다.

그렇지만, Android App(APK)에서 위의 내용들이 어떻게 사용되고 있는가에 대한 점은 상세히 분석해 볼 필요가 있다.

왜냐하면, Android에서는 App(APK)가 처음부터 loading되는 것이 아니고 zygote를 통해서 fork되는 방식이기 때문에  Java의 경우와는 약간 다르기 때문이다.


Class Loader 의 종류와 내용.


VMClassLoader / BootClassLoader

BOOTCLASSPATH만을 load하는 기본적인 class loader


System Class Loader

BootClassLoader + "CLASSPATH" 를 가지는 Loader.

VM이 최초 "static main"을 invoke시킬때 사용하는 class loader이다.

근거:

startVm() -> DvmStartup() -> dvmPrepMainThread()

: SystemClassLoader를 Thread의 ContextClassLoader로 setting함.

AndroidRuntime::start()pEnv->FindClass() - Function pointer to 'dalvik/vm/Jni.cpp:FindClass' - 를 이용해서 "static main"을 invoke하는데, 이때 SystemClassLoader가 사용됨.


Context Class Loader

SystemClassLoader + "Package private configuration"을 가지는 loader.

VM이 뜬 이후, Android context instance - ex. Activity - 를 시작할때 - ex. performLaunchActivity() - 사용되는 class loader로 기본 System Class Loader에 package private configuration(LoadedApk.java) - ex. shared java library - 을 포함한다.

근거:

LoadedApk.getClassLoader() 함수를 자세히 살펴볼 필요가 있는데, package정보의 java shared library나 native shared library정보 등을 이용해서 PathClassLoader를 생성하고 이를 이용하는데, 이때 base class loader가 default로, SystemClassLoader이기 때문이다.


여기서 또 한가지 중요한 내용은, Java의 경우, class가 최초 reference될때, referer가 load될때 사용된 classLoader를 이용해서, reference되는 class도 load된다는 것이다. 이것은 Android VM의 경우도 마찬가지인데 예로, dalvik의 OP_NEW_INSTANCE op code처리 부분을 보면, dvmResolveClass() 를 call하고, 함수 내부의 구현을 보면, referer의 class loader 를 이용하는 것을 볼 수 있다.


이제 정리할 시간이다.

Android의 경우, 최초 vm이 뜰때는 System Class Loader가 사용되나, context가 수행될 때는 Context Class Loader가 사용된다. 따라서, Package(APK)에 추가적으로 사용할 library를 기록해 두면, Context내부에서는 정상적으로 사용이 가능하다.


그러면, Package 에서 사용할 library들은 어떤식으로 정의할 수 있을까?


먼저 사용할 library가 permission file에 정의되어 있고, platform build시 /system/etc/permissions 에 위치해야 한다.

(당연히, 해당 library도 정해진 위치에 있어야 한다.)


com.my.android.test.xml

<permissions>

<library name="com.my.android.test"

         file="/system/framework/com.my.android.test.jar" />

</permissions>


이제 위의 library는 package manager에 의해 shared library로 인식된다.


Package에서 사용하기 위해서는, package의 AndroidManifest.xml에 application element의 sub element로 아래 'uses-library' element를 추가해야 한다.


AndroidManifest.xml

<uses-library android:name="com.my.android.test" />


이렇게 정의되면, package manager service가 Context Class Loader에 해당 library를 추가해 준다.


또 한가지 짚고 넘어가야 할 것은, CLASSPATH 에 대한 부분이다.

CLASSPATH의 경우, VM이 시작할때, setting되는 java.class.path property를 읽는데, 이 값은 Dvm의 classPathStr 값이다.


[[ TO DO ]]

그런데, 재미있는 사실은, system의 CLASSPATH 환경변수를 설정하더라도, Zygote에서 fork되는 App에서는 이를 바로 사용하지 못하는데 (실험적. 확인 필요)이 부분은 좀더 분석해 봐야 한다.



====== Rough Reference - Starting new Activity ======


ActivityStackSupervisor
startActivityLocked
startActivityUncheckedLocked

ActivityStack (target stack)
startActivityLocked

ActivityManagerService

attachApplicationLocked

ActivityStackSupervisor

resumeTopActivityLocked

ActivityManagerService.java
startProcessLocked() -> Process.start("android.app.ActivityThread", app.processName, uid, uid, gids ....)

Process.java
Process.start()
startViaZygote()
zygoteSendArgsAndGetResult() === send argument list via socket ===> zygote

<<< Socket connection >>>

ZygoteInit
registerZygoteSocket()
acceptCommandPeer()

ZygoteConnection
readArgumentList()

Zygote.java
forkAndSpecialize

--- child process ---

'WrapperInit.execApplication' or 'execStandalone'
# executing execv -> "/system/bin/app_process /system/bin --application --nice-name=xxx com.android.internal.os.WrapperInit <pipe fd> <targetSdkVersion> <shell args>
<shell args> : Args from Process.zygoteSendArgsAndGetResult <= which comes from startProcessLocked ("android.app.ActivityThread" ...)
# executing execv -> "/system/bin/dalvikvm -classpath '...' ...

--- execv ---

AppRuntime : AndroidRuntime -> "com.android.internal.os.RuntimeInit"

AndroidRuntime.start()
: startVm()
...
# starts Java startClass or starts "main" method.

RuntimeInit.main()

AndroidRuntime.cpp:: com_android_internal_os_RuntimeInit_nativeFinishInit()

app_main::AppRuntime.onStarted

AndroidRuntime.callMain()

*** <class>.main() *** => WrapperInit.main (see app_process argument above....).

RuntimeInit
wrapperInit()
applicationInit()
invokeStaticMain()

static ActivityThread.main : <= See WrapperInit.execApplication.

ActivityThread
attach()
ActivityManager.attachApplication() ==> ActivityManagerService.attachApplication()
# enter message loop!

ActivityManagerService
attachApplication()
attachApplicationLocked()
:--- attaching applications...

ActivityStackSupervisor.attachApplication()

ActivityStackSupervisor
realStartActivityLocked()

ActivityThread.scheduleLaunchActivity()
-> queue message : ActivityThread.LAUNCH_ACTIVITY

'Domain > Android' 카테고리의 다른 글

Multiple ABI and 64bit on Lolipop  (2) 2014.11.08
[Android] WindowManager & Display Area  (0) 2014.08.08
Create and use java library from packages.  (0) 2014.02.03
[NDK] 불편한 진실... 00  (0) 2013.11.25
Android resource compiler의 한계...  (0) 2013.11.09

조직 변경의 2가지 방법 - 역할 변경 vs. 사람 변경 - 에 대한 고찰.


먼저, "역할의 단위와 조직의 단위가 정확히 일치할 때 효율은 극대화 된다는 것"을 가정할 필요가 있다 - 이후 논의는 이 가정에 기반한다.

(물론, 필자가 이에 대한 논문을 찾아 본적도 없고, 연구결과가 있는지도 모르겠으나, 직관적으로 대부분의 사람들에 의해 그렇게 받아들여지고 있는 것 같다.)

또한, 큰 조직의 변경에 대해서 논할 만큼 나 자신이 경험이 많거나 연구를 많이 한 것이 아니라서 일단 고려하지 않고, 이 글에서는 소규모 조직 - 인원 50명 이하 정도가 4-5 개의 하위 조직으로 다시 나누어진 형태 - 의 변경에 대해서만 이야기 하고자 한다.


조직의 형태는 항상, 다양한 방식으로 변경된다.

많은 경우, 10명 이내/내외 의 인원이 가장 작은 단위의 조직이 되고, 이런 조직들이 다시 적게는 4-5개 많게는 10여개가 모여 다시 차 상위 조직이 되는 구조가 반복적으로 사용되어 하나의 큰 조직이 구성된다.

(옛날, 군대 조직 역시, 10부장, 100부장 등 10 단위로 조직이 구성되는 형태를 종종 볼 수 있다.)

그리고, 이런 소조직 별로 독립적인 역할이 부여되고, 이런 조직들의 유기적인 결합에 의해 다시 차상위 조직의 역할이 결정되는 구조를 가진다.

그런데, 업무와 역할이 항상 고정적일 수는 없고 변화가 생기게 마련이다.

어떤 역할은 그 규모가 확대되기도 하고, 또 어떤 역할은 그 규모가 축소되거나 혹은 아예 사라지기도 한다.

그리고, 이런 일들이 벌어질 때마다 소위 말하는 '조직변경'이라는 것이 생긴다.


'조직변경'의 생기게 되는 이유는 결과적으로 말하면, 역할의 단위와 조직의 단위가 잘 맞지 않기 때문이다.

역할은 내/외부 환경에 의해 계속 해서 바뀌게 되는데, 이때, 요구되는 역할의 단위가 현재 조직의 단위와 맞지 않다면, 조직의 효율을 높이기 위해, 기존 조직을 역할의 단위에 맞게 수정할 필요가 있다.

이때, "어떤 식으로 기존 조직을 변경할 것인가?"라는 문제가 생기게 되는데, 필자는 크게 두 가지 방법이 있다고 생각한다.

첫째, 역할의 변경.

둘째, 사람의 변경.


용어의 모호성을 없애기 위해 '조직 변경'을 '조직역할 변경'과 '조직원 변경'으로 구분하여 사용한다.

'조직역할 변경'이란, '조직'이 수행하는 역할이 변경되는 것을 뜻한다.

'조직원 변경'이란, '조직'의 사람(구성원)이 바뀌는 것을 의미한다.


[역할의 변경]

조직원을 기준으로 역할을 조정하는 방법이다.

즉, 조직 구성원의 변경을 최소화하고, 역할을 조정한다.


[사람의 변경]

역할을 기준으로, 조직원을 변경하는 방법이다.

위의 '역할의 변경'과 반대되는 개념이다.


일반적으로 '사람의 변경'이 '역할의 변경'보다 더 자주 사용되는 경향이 있는데, 내 생각에는, '사람의 변경'에 필요한 비용이 '역할의 변경'에 필요한 비용보다 예측하기 쉽고, 대부분의 경우 비용이 더 적게 들어가기 때문인 것 같다.


예를 들어, 아래의 상황을 가정해 보자.

* A팀(7명)과, B팀(10명) 이 존재한다.

* A팀은 kernel관련 업무를, B팀은 App.관련 업무를 맡고 있다.

* Kernel 업무는 많이 늘어나고 있어서 10명 정도의 인원이 필요한 반면, App. 업무는 줄어들고 있어서 7명 정도면 가능한 상황이다.


이와 같은 경우, 각각 아래와 같이 적용된다.

* 사람의 변경 : B팀의 인원 3명을 A팀으로 옮긴다.

* 역할의 변경 : B팀이 Kernel업무를 담당하고, A팀이 App. 업무를 담당하도록 한다.


어느쪽이 더 효율적이라고 보이는가?

아마, 대부분의 사람들이 아무런 의심이 없이 '사람의 변경'쪽을 택할 것이고, 나 역시, 높은 확률로 '올바른 선택'이 될 것이라고 생각한다.

그럼, 정말 '항상' 이와 같은 선택이 올바른 선택일까?

난, 여기에 의심을 품어 본다.


그렇다면, '왜' 대부분 '사람의 변경'쪽을 택하게 된 것일까?

아마도 아래와 같은 생각 때문이였을 것이다.


'사람의 변경'의 경우, 3명만, 새로운 업무에 적응하면 된다. 반면, '역할의 변경'의 경우 10 + 7 = 17 명 모두가 새로운 업무에 적응해야하고, 새로운 기술을 습득해야 한다.


상당히 합리적이로 옳은 판단의 근거라고 생각한다.

그렇지만, 정말로, 판단의 근거가 위의 내용밖에 없을까?

3명이 빠져 나감으로 인해서 발행하는 B팀의 사기 저하는? B팀의 인원이 A팀으로 옮길 시, 기존 팀원간의 불화에 따른 조직 문제는?

즉, 사람의 문제는 위의 판단에서 완벽하게 배제되어 있다.

다시 한번 말하지만, 위의 '예'의 경우는 '사람의 변경'이 높은 확률로 옳은 선택이라고 나 역시 생각한다.

그렇지만, '항상'은 아니라고 말하고 싶다.

'사람의 문제'에 따른 비용으로, 특수한 경우는 '역할의 변경'이 오히려 더 나은 경우도 분명히 존재할 것이다.

다만, 앞서 언급한 '사람의 문제'에 따른 비용이 예측되지 않기 때문에 사용되지 않을 뿐이라고 생각한다.


이런 종류의 연구를 좀더 조사해 볼 필요가 있어 보인다...


+ Recent posts