小程序基础库与Android之间通信优化的可能

最近在学习graalvm,发现有一个graaljs项目,项目中介绍可以让java与JavaScript做数据转换,比如JavaScript中可以使用java的数据类型与结构。突然想到之前遇到的一个问题,小程序中开发的代码和基础库的部分代码都是j2v8来执行的,其中的数据通信是通过bridge去做的,其实就是把数据结构都转换为字符串,这样就存在问题,比如Android这边的网络请求、音视频帧数据、文件流对外都是通过java封装的对象,无法直接在JavaScript中使用,只能是通过转换为base64来做,而且一个buffer数据基本需要两次转换,sdk转一次,基础库转一次,比较消耗性能。

如果JavaScript和java之间的结构互通,那是不是就解决这个问题了,理论上来说如果js引擎是通过java编写的解释器去执行,那确实是可以这样的。

GraalJs

GraalJs核心代码如下:

BufferedReader br = null;
try {br = new BufferedReader(new FileReader("/Users/xxx/tmp/index.md"));
} catch (FileNotFoundException e) {throw new RuntimeException(e);
}
try (Context context = Context.newBuilder().allowAllAccess(true).build()) {Set<String> languages = context.getEngine().getLanguages().keySet();for (String id : languages) {context.initialize(id);if (id.equals("js")) {context.eval("js", "function main(data) { console.log(data.readLine()); }");Value funMain = context.getBindings("js").getMember("main");funMain.execute(br);}}
}

这里我们使用GraalVM的jdk是可以运行的,可以看到JavaScript中接收到的data其实是java的BufferedReader,执行之后就发现JavaScript中的data.readLine成功执行并打印了文件内容,WC,如果Android可以这样那就太强了。可惜,GraalJs必须使用GraalVM提供的jdk,也不好直接替换android中使用的jdk。。。
那有没有其他办法?对了,GraalVM是可以将java代码生成分享库的,比如.so,Android也正好可以加载so库。有没有可能这样搞。最终项目如下https://github.com/schizobulia/GraalJs-Android ,可以看到releases中tag为v0.0.8中有arrch64和armv7的so库
截屏2024-01-11 10.02.00.png
可惜拿到so库之后去Android中使用发现,这个so库不是ABI。麻了…
然后查了相关资料发现GraalVM目前也没有计划支持Android。

不过好在最后发现ChatGPT确实是个好东西,现在查资料基本都是先问问ChatGPT,上面项目中的GitHub Action配置文件也是ChatGPT写的。

参考资料:
Android 关于CPU类型的so文件兼容问题(ABI) - 掘金
一分钟搞明白Android的.so文件、ABI和CPU的关系-CSDN博客

J2V8

那有没有可能从j2v8入手,比如node很多内置函数其实在v8中也是没有的,如果可以在v8中实现这些函数然后提供给JavaScript调用好像有可以,然后开始查node这部分功能的实现原理,最后看到一篇博客:Node.js的底层原理 - 掘金其中说到这个部分的实现是V8的自定义拓展实现的,好像确实可以。不过后来试了试,发现还是不行。

主要原因有:比如文件流、帧数据在Android端对外都是通过java封装的对象,v8的自定义扩展需要c++或者v8提供的语言来编写,依然存在语言之间数据结构转换的问题。

次要原因:实在不想看c++的代码

Rhino

然后通过ChatGPT最终选择试试Rhino,因为他也是java写的,缺点是性能可能没没v8那么强,JavaScript中新的语法糖或者全局属性可能没那么快支持到(不过可以使用一些打包库和第三方静态分析库去优化)。
小程序中存在大量的数据交互,如果使用Rhino说不定会有更好的效果,以下为示例代码,可以看到JavaScript中可以使用java的数据结构,这得益于解释器是使用java写的,节省了不同语言之间数据结构的转换。

var System = java.lang.System;
System.out.println(myClass.add(1, 2));
function test(str) {myClass.show(str);
}

通过下面代码的测试,发现读取一个53kb的文件从调用test方法到show方法的触发基本没消耗时间。而且根据这种方式其实也很节省内存,因为数据其实只保存在了jvm中,按j2v8的思路同一份数据需要在v8、jvm中各保存一份。
以下为完整代码:

package com.example.myapplicationimport android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.myapplication.ui.theme.MyApplicationTheme
import org.mozilla.javascript.Context
import org.mozilla.javascript.Function
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.ScriptableObject
import java.nio.ByteBuffer
import java.nio.CharBuffer
import java.nio.charset.Charsetclass MainActivity : ComponentActivity() {class MyFunctions {fun add(a: Int, b: Int): Int {return a + b}fun show(buffer: ByteArray) {println("这是js传递过来的:")println(System.currentTimeMillis())println(buffer)
//            val text = String(buffer)
//            println("File Content: $text")}}class JsEngine {public val rhino: Context = Context.enter()public val scope: Scriptableinit {rhino.optimizationLevel = -1scope = rhino.initStandardObjects()}fun evaluate(jsCode: String) {try {ScriptableObject.putProperty(scope,"myClass", Context.javaToJS(MyFunctions(), scope))ScriptableObject.putProperty(scope, "javaContext", Context.javaToJS(this, scope))ScriptableObject.putProperty(scope, "javaLoader", Context.javaToJS(JsEngine::class.java.classLoader, scope))rhino.evaluateString(scope, jsCode, JsEngine::class.java.simpleName, 1, null)} finally {
//                Context.exit()}}fun callFunction(functionName: String, vararg args: Any): Any? {try {val function = scope[functionName, scope] as Functionreturn function.call(rhino, scope, scope, args)} finally {
//                Context.exit()}}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {MyApplicationTheme {// A surface container using the 'background' color from the themeSurface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {Greeting("Android")}}}val inputStream = resources.assets.open("data.txt");val size = inputStream.available()val buffer = ByteArray(size)inputStream.read(buffer)inputStream.close()Thread {val jsCode = """var System = java.lang.System;System.out.println(myClass.add(1, 2));function test(str) {myClass.show(str);}""".trimIndent()val jsEngine = JsEngine()jsEngine.evaluate(jsCode)println(System.currentTimeMillis())jsEngine.callFunction("test", buffer)}.start()}
}@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {Text(text = "Hello $name!",modifier = modifier)
}@Preview(showBackground = true)
@Composable
fun GreetingPreview() {MyApplicationTheme {Greeting("Android")}
}

最后:ChatGPT真👍🏻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/628829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解 Spark(二)SparkApplication 提交和运行源码分析

spark 核心流程 yarn-client yarn-cluster spark 任务调度 spark stage 级别调度 spark task 级别调度 失败重试和白名单 对于运行失败的 Task&#xff0c;TaskSetManager 会记录它失败的次数&#xff0c;如果失败次数还没有超过最大重试次数&#xff0c;那么就把它放回待调…

【Docker构建MySQL8.0镜像】

Docker构建MySQL8.0镜像 部署流程1. 拉取docker镜像2. 创建数据卷&#xff0c;存放MySQL数据3. 启动MySQL镜像4. 初始化sql放入MySQL镜像5. 执行MySQL脚本6. MySQL镜像打包7. MySQL镜像迁移 部署流程 1. 拉取docker镜像 docker pull mysql:8.0.35拉取成功后就可以看到镜像了&…

NFS(Network File System 网络文件服务)

一&#xff0c;nfs 简介 1&#xff0c;nfs 性质 NFS&#xff08;Network File System 网络文件服务&#xff09; 文件系统&#xff08;软件&#xff09;文件的权限 NFS 是一种基于 TCP/IP 传输的网络文件系统协议 通过使用 NFS 协议&#xff0c;客户机可以像访问本地目录一样…

【NI国产替代】NI-9231,8通道,51.2 kS/s/ch,-5至5 V,C系列声音和振动输入模块

8通道&#xff0c;51.2 kS/s/ch&#xff0c;-5至5 V&#xff0c;C系列声音和振动输入模块 NI-9231是一款高密度声音和振动模块&#xff0c;能够测量来自速度计、转速计和接近式探针等集成电子压电(IEPE)和非IEPE传感器的信号。该模块可以执行现代麦克风和加速计所需的高动态范围…

verilog编程题

verilog编程题 文章目录 verilog编程题序列检测电路&#xff08;状态机实现&#xff09;分频电路计数器译码器选择器加减器触发器寄存器 序列检测电路&#xff08;状态机实现&#xff09; module Detect_101(input clk,input rst_n,input data,o…

力扣每日一练(24-1-15)

重复n次检查&#xff0c;几乎都用双指针。。。 固然双指针就是题解&#xff1a; if len(nums) < 3:return len(nums)p1 2 for p2 in range(2, len(nums)):if nums[p2] ! nums[p1 - 2]:nums[p1] nums[p2]p1 1return p1 可以重复两次&#xff0c;那么隔一个检查就行&#…

vtk9.3 配置 visual studio 2019 运行环境 和运行实例详解

&#xff08;1&#xff09;包含文件配置&#xff1a; 项目--属性--VC目录&#xff0c;在包含目录中把include文件夹的地址加进去&#xff0c;一直要到下一级 vtk-9.3目录下&#xff0c; 小知识&#xff1a; 在Visual Studio 2019中运行项目时&#xff0c;如果项目中使用了第三…

网络安全笔记-SQL注入

文章目录 前言一、数据库1、Information_schema2、相关函数 二、SQL注入分类1、联合查询注入&#xff08;UNION query SQL injection&#xff09;语法 2、报错注入&#xff08;Error-based SQL injection&#xff09;报错注入分类报错函数报错注入原理 3、盲注布尔型盲注&#…

【Java 设计模式】创建型之抽象工厂模式

文章目录 1. 定义2. 应用场景3. 代码实现4. 应用示例结语 在软件开发中&#xff0c;抽象工厂模式是一种常见的创建型设计模式&#xff0c;它提供了一种创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。抽象工厂模式的核心思想是将一组相关的产品组合成…

docker screen 常用基础命令

1.docker基础命令 1.1开启docker systemctl start docker #开启docker service docker restart #重启docker systemctl stop docker #关闭docker 1.2查看命令 docker images #查看docker镜像docker ps #查看正在运行的镜像或者容器docker ps -a #查看所有容器1.3运…

刘知远LLM入门到实战——自然语言基础

文章目录 自然语言处理基础词表示语言模型N-gram ModelNeural Language Model: 为什么NLP等领域的模型越来越大&#xff1f; 大模型会带来哪些新的范式和挑战&#xff1f; 自然语言处理基础 让计算机理解人类语言&#xff0c;图灵测试就是基于对话的方式。 研究历史&#xff…

FlinkAPI开发之处理函数

案例用到的测试数据请参考文章&#xff1a; Flink自定义Source模拟数据流 原文链接&#xff1a;https://blog.csdn.net/m0_52606060/article/details/135436048 概述 之前所介绍的流处理API&#xff0c;无论是基本的转换、聚合&#xff0c;还是更为复杂的窗口操作&#xff0c…

cron表达式大全

简介 Cron表达式是一种用于指定定时任务的时间表达式&#xff0c;常用来指定任务的执行时间、执行频率和执行间隔。它由6&#xff5e;7个字段组成&#xff0c;分别表示秒、分、时、日期、月份、星期、年份&#xff08;可省略&#xff09;。 Cron表达式基本语法如下&#xff1a;…

人工智能 | ChatGPT 和文心一言哪个更好用?

github&#xff1a;https://github.com/MichaelBeechan CSDN&#xff1a;https://blog.csdn.net/u011344545 ChatGPT 和文心一言哪个更好用&#xff1f; ChatGPT 和文心一言哪个更好用&#xff1f;方向一&#xff1a;ChatGPT主要优势局限性和挑战如何克服chatGPT的局限性和挑战…

全罐喂养一个月多少钱?适合全罐喂养的猫罐头推荐

不少铲屎官一直没有办法get到猫罐头对猫咪的好处&#xff0c;或者get到了又觉得给猫咪买猫罐头好贵&#xff0c;看到其他铲屎官都开始全罐喂养了&#xff0c;但是自己却迟迟下不了手&#xff0c;犹犹豫豫的不知道全罐喂养一个月多少钱&#xff1f; 今天&#xff0c;铲龄15年的…

Python实现Excel切片删除功能(附源码)

使用Python实现Excel中的“切片删除”功能&#xff08;附源码&#xff09; 先上效果图&#xff01;&#xff01;&#xff01; 如下是需要处理的Excel文件&#xff0c;可以看到在27行和117行处的E列存在数据不一致情况&#xff0c;需进行“切片删除” 运行结果图如下&#xff…

【前端架构】前端通用架构

一个强大的前端通用架构应该具备多种能力&#xff0c;以支持现代化的应用程序开发和提高开发效率。以下是一些前端通用架构应该具备的关键能力&#xff1a; 模块化和组件化&#xff1a;支持模块化开发和组件化架构&#xff0c;能够将应用拆分为独立的模块和组件&#xff0c;以便…

leetcode 2418. 按身高排序

题目 给你一个字符串数组 names &#xff0c;和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。 对于每个下标 i&#xff0c;names[i] 和 heights[i] 表示第 i 个人的名字和身高。 请按身高 降序 顺序返回对应的名字数组 names 。 解题方法&#xff…

Go新项目-为何选Gin框架?(0)

先说结论&#xff1a;我们选型Gin框架 早在大概在2019年下旬&#xff0c;由于内部一个多线程上传的需求&#xff0c;考虑到Go协程的优势&#xff1b; 内部采用Gin框架编写了内部的数据上传平台BAP&#xff0c;采用GinVue开发&#xff0c;但前期没考虑到工程化思维&#xff0c;导…

Vue3入门

文章目录 一、Vue3介绍二、Vue3项目创建1&#xff09;使用vue-cli创建vue3项目2&#xff09;使用vite创建vue3项目 三、Setup函数vue2的创建vue实例和vue3创建vue实例的区别 四、ref和reactive1&#xff09;ref函数2&#xff09;reactive函数3&#xff09;reactive对比ref4&…