欢迎光临企业官网建站网站,提供自助建设系统平台服务

企业官网建站

专业为公司品牌推广建设网站

安卓 v8 静态库调试

作者:jcmp      发布时间:2021-04-22      浏览量:0
概述如果要在安卓客户端进行js动态加载,

概述

如果要在安卓客户端进行js动态加载,通过js渲染界面,这就必须要通过v8进行解析,v8解析过js之后,就会将js的对象,包装成一个个的C++对象,可以通过v8提供的接口,在native端获取这些对象,从而对其进行使用。这种方式,基本上是所有动态化框架的基础。weex就是这种方式,reactnative(以下简称RN)也是这种方式,不过解析js使用的引擎不相同而已,RN使用的是iOS平台的javascriptcore。而weex在安卓上也是使用的v8。通过这种方式,js一次编写,就可以同时运行在web端,安卓端,iOS端。(iOS端在此不作介绍。)这种动态加载,可以应对业务变化很快的app,比如淘宝,页面需要经常变动,只是更改一下界面,业务逻辑,就要重新发布新版本,是一件很没有意思的事情。所以,这种基于v8的动态化框架,就成为了趋势。

众所周知,在web端调试js很容易,而在安卓端通过webview调试js也很容易,而直接通过v8调试js,却很困难。首先,v8协议在不断的发生改变,而v8所使用的调试协议和chrome所使用的v8调试协议完全不一样。前面有一篇文章,记录了本文所介绍的3.17版本的v8调试协议,chrome的调试协议比较稳定,google一下,就可以找到。你可以进行对比,他们是完全不一样的。这就意味着,要进行调试,就必须要做协议转换。( 注意:谷歌自从5.6版本起,就自带了调试客户端,内部自己转换了协议,而且可以直接和chrome进行连接,只需要调用相关的方法就可以。可以参考v8 github上的wiki。如果使用的是5.6及以上版本,本文可以直接忽略不看。 )。

安卓客户端工作

主要有以下三个重点

1、客户端首先需要注册一个handler。在v8-debug.h中有这样一个方法:

static void SetMessageHandler2(MessageHandler2 handler);//MessageHandler2的定义如下:typedef void (*MessageHandler2)(const Message& message);

将自己的MessageHandler2set进去之后,就可以接收到来自v8的message类型数据。

//通过这种方式,可以得到json数据。message.GetJSON();

获得了消息之后,传递到服务端,进行协议转换。

2、那么被服务端转换之后的chrome消息怎么处理呢?在v8-debug.h文件中,有如下一个方法:

// If no isolate is provided the default isolate is used.static void SendCommand(const uint16_t* command, int length, ClientData* client_data = NULL, Isolate* isolate = NULL);

通过这个方法,可以将转换之后的消息发送给v8进行处理,v8通过处理,就会将消息通过步骤1的方式传递结果。

3、有一些情况下,发送到v8的调试信息可能没有返回,可以尝试下面的方法:

/** * Makes V8 process all pending debug messages. * * From V8 point of view all debug messages come asynchronously (e.g. from * remote debugger) but they all must be handled synchronously: V8 cannot * do 2 things at one time so normal script execution must be interrupted * for a while. * * Generally when message arrives V8 may be in one of 3 states: * 1. V8 is running script; V8 will automatically interrupt and process all * pending messages (however auto_break flag should be enabled); * 2. V8 is suspended on debug breakpoint; in this state V8 is dedicated * to reading and processing debug messages; * 3. V8 is not running at all or has called some long-working C++ function; * by default it means that processing of all debug messages will be deferred * until V8 gets control again; however, embedding application may improve * this by manually calling this method. * * It makes sense to call this method whenever a new debug message arrived and * V8 is not already running. Method v8::Debug::SetDebugMessageDispatchHandler * should help with the former condition. * * Technically this method in many senses is equivalent to executing empty * script: * 1. It does nothing except for processing all pending debug messages. * 2. It should be invoked with the same precautions and from the same context * as V8 script would be invoked from, because: * a. with "evaluate" command it can do whatever normal script can do, * including all native calls; * b. no other thread should call V8 while this method is running * (v8::Locker may be used here). * * "Evaluate" debug command behavior currently is not specified in scope * of this method. */static void ProcessDebugMessages();

文档介绍很多,主要意思是如果命令是 Evaluate ,有些情况下v8是不会返回的,这时可以尝试调用此方法,催促v8返回。通常情况下,此方法可以不用调用。

3、v8加载运行js很快,这就需要我们每次打开调试的时候,js都断点在第0行第0列等我们来运行。

// Schedule a debugger break to happen when JavaScript code is run// in the given isolate. If no isolate is provided the default// isolate is used.static void DebugBreak(Isolate* isolate = NULL);

在比较靠前的时候,调用此方法,就可以将v8暂停在0行0列,直到给出了下一步或者中断之后,才会继续加载js。

服务端工作

所有的消息都是通过socket或者websocket进行传输。推荐websocket,实现简单,双向通信。而且和chrome的调试连接必须使用websocket。接下来看看几个步骤: 1、处理v8发送过来的消息 v8发送过来的消息是一个json格式的数据,而chrome需要的也是一个json格式的数据。举两个例子,首先看看chrome的协议:

{ "method": "Console.messageAdded", "params": { "message": { "source": "console-api", "level": "log", "text": "a=x", "type": "log" } }}

接下来看看v8的协议:

{ "seq": 1, "type": "request", "command": "setexceptionbreak", "arguments": { "type": "all", "enabled": false, "maxStringLength": -1 }}

可以看到,他们的协议格式是不相同的。在此,我们都知道nodejs,他也是基于v8进行开发的,想必他的调试也会进行协议转换,就这条线索,找到了node-inspector这个项目,发现其中确实对协议进行了转换。将其协议转换的部分,抽取出来,大部分都可以正常使用。需要更改的有几个要点:

注意点:

chrome端

chrome端使用的源码中的devtool文件,协议会发生改变,所以确保使用的协议是低于chrome55版本的,以上可能不支持。从这些低版本中抽取出devtool工程。当然,也可以自己修改,升级升上去。

连接起来

以上所讲都是一个个单独的部分,如果需要使用,就需要将其连接起来。我的方案是通过websocket连接起来,起一个nodejs后台服务,处理这些websocket交互。建立对应的session,就会非常简单。

结束

以上只是粗略讲了一下其中的一些重点部分,具体实践起来还是有大量的工作需要去做的。比如多v8的调试,session管理等等,都是比较复杂的。 v8内核能量巨大,未来如何,拭目以待。