各位大侠,有几个问题,请问下:在一个apk程序里面,如果有用JNI去调用C库程序。1)库中的C语言代码和该apk中的Java代码是否同在apk所申请的进程地址空间里面运行?
2)库中的C语言代码是否归apk启动起来的Dalvik虚拟机的线程来管理?
3)库中的C程序能否开辟自己的线程甚至是进程,如果可以,这些新开出来的线程或者进程
  的地址空间是由Dalvik虚拟机来管来还是由底层Linux来管理?

解决方案 »

  1.   

    好问题
    1)JNI的代码都是动态库形式的,所以无所谓是不是同一个进程地址空间,linux动态库什么样android里面就什么样,都是多个进程共享这段空间
    2)估计跟dalvik关系不大,动态库都是ld加载的
    3)动态库没有自己的进程,都是映射到不同进程的某一段地址空间
      

  2.   

    1. 我的理解是,apk只是打包形式,不代表一个apk就会一个进程。但是我猜测你的问题是apk里程序只有一个进程的情况,这样动态库运行时是和其同一进程。这一点不是完全同意1楼,动态库还是要映射到进程的某一空间的,虽然其是多进程共享的,否则无法访问。这一点可参考build/core/prelink-linux-arm.map,里面会有linux进程地址空间的一些划分
    2.不明白楼主的管理是指的什么,dalvik可以调用动态库中的方法,参照libc.so就可知道,dalvik一定会调用c库中方法。
    3.动态库里的代码可以启动新的进程或线程,还是不明白楼主的dalvik来管理是什么意思,linux会负责调度这些进程线程
      

  3.   

    cdbdyx你好,感谢答复。我对你的回答的理解是JNI库的运行和管理都是由Linux操作系统在做,而Java代码是跑在dalvik里面(dalvik也是由操作系统来运行和管理的),然后它们通过dalvik的JNI接口进行沟通。是不是不管在什么操作系统下面,Java和JNI的关系都和上面类似,除了Android下面的dalvik是多个
    实例的?
     
      

  4.   

    感谢challchampion的回复,对第一个问题的描述很清楚。
      

  5.   

    我个人理解应该是这样的,细节方面要再研究下
    首先,android用的是bionic而非glibc,不同的地方可能就包括动态库加载上,jni加载的时候要call一个jniload函数,一般在这里注册jni接口                                                
    其次,dalvik调用jni的时候就应该和这个注册过程有关       我感觉你主要纠结在java怎么调用c的,因为java编译后是字节码而c是机器码,所以java代码是不可能调用到c的,真正调用c是dalvik做的,而dalvik又是c写的,这就不奇怪了,反过来也能解释c调用java代码,感兴趣可以研究一下最简单的虚拟机,就是一般java卡里面跑的虚拟机                          别的系统我不清楚,但android的虚拟机确是多个实例的,但是多个实例并不代表每个进程都有一份完整的copy,因为在linux看来不同的进程的好多地方是可以共享的,一个例子就是framework的代码我理解在物理内存上只有一份就够了,所以android运行起来并不笨重。          
                                                                                     
    以上内容很多猜测成分,如有误导,当我瞎扯。 
    ps,第一次码了这么多字,多给点分儿啊             
      

  6.   

    再把java怎么调用c解释细一点。
    java虚拟机标准会规定都解释那些字节码,就比如add a b,那么虚拟机就认为你是做加法,而虚拟机还有一个约定就是调用native code,比如call method,虚拟机看到这个字节码就会认为你是想调用某个c函数,这时他就会搜索已经注册了的方法,从而就可以call他了。 
    不容易啊在android上码字