android中調用native的fork函數後的現象觀察

疑問

android的app運行過程當中,若是經過jni調用到了native層的fork()函數,那麼java層的各對象都會複製一份嗎?java

建工程作實驗

創建一個包含C++的android工程,在工程中的native-lib.cpp中改爲這個android

#include <jni.h>
#include <string>
#include <unistd.h>

extern "C" JNIEXPORT jint JNICALL Java_mainpackage_MainActivity_invokeFork( JNIEnv *env, jobject /* this */) {
    return fork();
}
複製代碼

而後在kotlin中創建一個classbash

package mainpackage

class SomeBody(var name: String) {
    override fun toString(): String {
        return "($name ${System.identityHashCode(this).toHex()})"
    }

    private fun Int.toHex() = Integer.toHexString(this)
}
複製代碼

而後在MainActivity中寫一個函數app

fun studyFork() {
        val sb = SomeBody("張三")
        Log.i("fork", "before fork >> sb: $sb")
        val forkRet = invokeFork()
        Log.i("fork", "after fork >> forkRet: $forkRet pid: ${Process.myPid()} sb: $sb")    
    }
複製代碼

而且在MainActivity被create以後,調用studyFork() 發現輸出是:ide

before fork >> sb: (張三 3e8825b)
after fork >> forkRet: 21281 pid: 21262 sb: (張三 3e8825b)
after fork >> forkRet: 0 pid: 21281 sb: (張三 3e8825b)
複製代碼

觀察結果,得出本身的判斷,對象sb在主進程和子進程中是同一個,即主進程和子進程共享同一個對象(後面的實驗推翻了這個結論)。函數

新的困惑

主進程和子進程共享虛擬機中同一個堆空間嗎?兩個進程操做這個對象,觀察到的結果是什麼呢? 繼續作實驗,修改了studyFork()函數以下:ui

fun studyFork() {
        val sb = SomeBody("張三")

        Log.i("fork", "before fork >> sb: $sb")
        val forkRet = invokeFork()
        Log.i("fork", "after fork >> forkRet: $forkRet pid: ${Process.myPid()} sb: $sb")

        if (forkRet == 0) { // 子進程
            sb.name = "李四"
            Log.i("fork", "sub process >> forRet: $forkRet modified-sb: $sb")
        } else { // 父進程
            Thread.sleep(1000)
            Log.i("fork", "parent process >> forRet: $forkRet sb: $sb")
        }
    }
複製代碼

讓子進程建立後馬上修改sb的name爲「李四」,而後父進程1s以後觀察這個sb並打印日誌。日誌以下:this

2019-04-03 18:33:24.208  I/fork: before fork >> sb: (張三 3e8825b)
2019-04-03 18:33:24.214  I/fork: after fork >> forkRet: 0 pid: 22143 sb: (張三 3e8825b)
2019-04-03 18:33:24.214  I/fork: after fork >> forkRet: 22143 pid: 22123 sb: (張三 3e8825b)
2019-04-03 18:33:24.215  I/fork: sub process >> forRet: 0 modified-sb: (李四 3e8825b)
2019-04-03 18:33:25.219  I/fork: parent process >> forRet: 22143 sb: (張三 3e8825b)
複製代碼

因而得出本身的判斷:子進程修改了sb對象的name,主進程感知不到。進而得出這樣的結論,主進程和子進程不共享同一個對象,只是各自持有一份sb拷貝。進而,兩個進程不共享虛擬機的同一個堆空間。spa

相關文章
相關標籤/搜索