查看原文
其他

解读Android虚拟机工作原理

2017-04-13 androidstarjack 终端研发部
前言介绍

新的一天,祝大家工作愉快!

上次讲了java虚拟机和Dalvik虚拟机的区别,还没有了解的童鞋们请参考

来自GoogleCoder的简书:

正文


什么是Dalvik虚拟机

Dalvik是Google公司自己设计用于Android平台的Java虚拟机,它是Android平台的重要组成部分,支持dex格式(Dalvik Executable)的Java应用程序的运行。dex格式是专门为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。Google对其进行了特定的优化,使得Dalvik具有高效、简洁、节省资源的特点。从Android系统架构图知,Dalvik虚拟机运行在Android的运行时库层。

2 Dalvik虚拟机的功能

Dalvik作为面向Linux、为嵌入式操作系统设计的虚拟机,主要负责完成对象生命周期管理、堆栈管理、线程管理、安全和异常管理,以及垃圾回收等。Dalvik充分利用Linux进程管理的特定,对其进行了面向对象的设计,使得可以同时运行多个进程,而传统的Java程序通常只能运行一个进程,这也是为什么Android不采用JVM的原因。Dalvik为了达到优化的目的,底层的操作大多和系统内核相关,或者直接调用内核接口。另外,Dalvik早期并没有JIT编译器,直到Android2.2才加入了对JIT的技术支持。

Linux系统中进程间通信的方式有:

  • socket

  • named pipe

  • message queque

  • signal

  • share memory。 Java系统中的进程间通信方式有

  • socket

  • named pipe等。

android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信.

取而代之的是Binder通信。Google为什么要采用这种方式呢,这取决于Binder通信方式的高效率。 Binder通信是通过linux的binder driver来实现的。Binder通信操作类似线程迁移(thread migration),两个进程间IPC看起来就象是一个进程进入另一个进程执行代码然后带着执行的结果返回。

Binder的用户空间为每一个进程维护着一个可用的线程池,线程池用于处理到来的IPC以及执行进程本地消息,Binder通信是同步而不是异步。Android中的Binder通信是基于Service与Client的,所有需要IBinder通信的进程都必须创建一个IBinder接口。

系统中有一个进程管理所有的system service,Android虚拟机不允许用户添加非授权的System service,当然现在源码开发了,我们可以修改一些代码来实现添加底层system Service的目的。

对用户程序来说,我们也要创建server,或者Service用于进程间通信,这里有一ActivityManagerService管理JAVA应用层所有的service创建与连接(connect)。disconnect,所有的 Activity也是通过这个service来启动,加载的。ActivityManagerService也是加载在Systems Servcie中的。

Android虚拟机启动之前系统会先启动service Manager进程,service Manager打开binder驱动,并通知binder kernel驱动程序这个进程将作为System Service Manager。然后该进程将进入一个循环,等待处理来自其他进程的数据。用户创建一个System service后,通过defaultServiceManager得到一个远程ServiceManager的接口。

通过这个接口我们可以调用 addService函数将System service添加到Service Manager进程中,然后client可以通过getService获取到需要连接的目的Service的IBinder对象。这个IBinder是 Service的BBinder在binder kernel的一个参考,所以service IBinder 在binder kernel中不会存在相同的两个IBinder对象。

每一个Client进程同样需要打开Binder驱动程序。对用户程序而言,我们获得这个对象就可以通过binder kernel访问service对象中的方法。Client与Service在不同的进程中,通过这种方式实现了类似线程间的迁移的通信方式,对用户程序而言当调用Service返回的IBinder接口后,访问Service中的方法就如同调用自己的函数。

实现接口时有几个原则:

抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的。IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。

也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理,能在AIDL接口中声明静态属性。IPC的调用步骤:


  1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。


    1. 实现ServiceConnection。


    1. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.


    1. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用 YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换YourInterface类型。


    1. 调用接口中定义的方法。 你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。


    1. 断开连接,调用接口实例中的ApplicationContext.unbindService()

    Dalvik虚拟机的运行过程分析:

    理解Android虚拟机体系结构

    Dalvik虚拟机的启动过程分析

    如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809   

    微信公众号:终端研发部


                

    Hello,伙伴们

    长按二维码就可以关注我们啦



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存