【android】SDK兼容低版本Lambda的一次尝试

背景信息

背景是最近我们提供的SDK给合作方接入,对方接入的时候编译报这个错误。

报错内容如下

Exception in thread "main" java.lang.IllegalStateException: Expected a load for Lorg/yeshen/hello/test/u9; to set up parameter 0 for org/yeshen/hello/test/u9$$Lambda$0 but got 89
at com.google.common.base.Preconditions.checkState(Preconditions.java:756)
at com.google.devtools.build.android.desugar.LambdaDesugaring$InvokedynamicRewriter.attemptAllocationBeforeArgumentLoads(LambdaDesugaring.java:535)
at com.google.devtools.build.android.desugar.LambdaDesugaring$InvokedynamicRewriter.visitInvokeDynamicInsn(LambdaDesugaring.java:420)
at org.objectweb.asm.ClassReader.a(Unknown Source)
at org.objectweb.asm.ClassReader.b(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at com.google.devtools.build.android.desugar.Desugar.desugarClassesInInput(Desugar.java:401)
at com.google.devtools.build.android.desugar.Desugar.desugarOneInput(Desugar.java:326)
at com.google.devtools.build.android.desugar.Desugar.desugar(Desugar.java:280)
at com.google.devtools.build.android.desugar.Desugar.main(Desugar.java:584)FAILURE: Build failed with an exception.* What went wrong:
Execution failed for task ':app:transformClassesWithDesugarForDebug'.

原因

// 合作方配置
classpath 'com.android.tools.build:gradle:3.0.1'// 我方配置
classpath 'com.android.tools.build:gradle:4.0.1'

沟通之后,我调整了 com.android.tools.build:gradle,和对方调整成一致之后,重现到了问题。

查了相关资料 1,大概是java jdk8支持了Lambda表达式,但是在Android中为了向下兼容,虽然支持了jdk8的语法,但是在编译 dex 阶段会 desugar 成内部类的实现。这个报错是两个 tools.build 的版本 (It was made the default dexer in Android Gradle plugin 3.1 and it then became responsible for desugaring in 3.2.) 2,对 Lambda 的处理有区别导致的。

解决思路

所以我理解解决思路有几个:

  1. 同步版本(我这边降低版本,或者对方升级版本)
    => 沟通后,对方表示无法降低版本
    => 我这边降低版本一是会导致原本正常使用的kotlin出现问题;二是我这边很多内部的依赖,一揽子都需要重新编译,维护成本很高。

  2. 代码中逐行替换Lambda表达式成匿名内部类
    => 可以绕过问题,但是代码中已经到处都是Lambda表达式,维护成本巨高不下。

  3. 从Android编译工具链中找相关的降级/兼容配置
    => 未找到。我这边使用的是D8,在D8中没找到配置。

  4. 参考 RetroLambda 提供插件给合作方做兼容 3
    => 自己写的话,大概是: app:compileDebugJavaWithJavac(对应javac)之后,和app:transformDexArchiveWithDexMergerForDebug(对应dx)之前,根据 java/lang/invoke/LambdaMetafactory.metafactory 方法,直接将原本在运行时生成在内存中的 J8Sample\$\$Lambda\$1.class,在javac编译结束之后,dx编译dex之前,直接生成到本地,并使用生成的J8Sample\$\$Lambda\$1类修改J8Sample.class字节码文件,将J8Sample.class中的invokedynamic指令替换成invokestatic指令。
    => 或者让合作方直接使用 retrolambda 插件。
    => 修改合作方的编译工具,对方大概率不接受。

  5. 把代码抽离成dex,运行时动态加载dex代码,而不是直接给对方接入使用。
    => 自己写的话,大概是:

    1. 获取已经输出的sdk, 把 代码资源 分离,资源作为新sdk的一部分直接使用。
    2. 把步骤1获得的 代码 编译后输出成apk,放在asset下.
    3. 动态加载asset中的 代码 ,完成功能。

参考资料


  1. https://jakewharton.com/androids-java-8-support/ ↩︎

  2. https://android-developers.googleblog.com/2017/08/next-generation-dex-compiler-now-in.html ↩︎

  3. https://tech.meituan.com/2019/10/17/android-java-8.html ↩︎

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

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

相关文章

spring-security 过滤器 (三)

spring-security过滤器 版本信息过滤器配置过滤器配置相关类图过滤器加载过程创建 HttpSecurity Bean 对象创建过滤器 过滤器作用ExceptionTranslationFilter 自定义过滤器 本章介绍 spring-security 过滤器配置类 HttpSecurity,过滤器加载过程,自定义过…

信息抽取(UIE):使用自然语言处理技术提升证券投资决策效率

一、引言 在当今快速变化的证券市场中,信息的价值不言而喻。作为一名资深项目经理,我曾领导一个关键项目,旨在通过先进的信息抽取技术,从海量的文本数据中提取关键事件,如企业并购、新产品发布以及政策环境的变动。这些…

Open CASCADE学习|几何数据结构

在几何引擎内一般把数据分成两类:几何信息与拓扑信息。二者可以完整地表达出实体模型,彼此相互独立、又互相关联。几何信息是指构成几何实体的各几何元素在欧式空间中的位置、大小、尺寸和形状信息。例如一条空间的直线,可以用两端点的位置矢…

[ffmpeg] 获取编译配置信息

背景 想使用 ffmpeg 的 n 卡编码器,发现 find_encode 失败,想看看是不是编译 ffmpeg 的时候有些功能没有打开。 如何获取编译配置信息 api const char* configuration avcodec_configuration(); printf("FFmpeg file configuration: %s\n"…

五种多目标优化算法(MOCS、MOFA、NSWOA、MOAHA、MOPSO)性能对比(提供MATLAB代码)

一、5种多目标优化算法简介 多目标优化算法是用于解决具有多个目标函数的优化问题的一类算法。其求解流程通常包括以下几个步骤: 1. 定义问题:首先需要明确问题的目标函数和约束条件。多目标优化问题通常涉及多个目标函数,这些目标函数可能…

【人脸朝向识别与分类预测】基于BP神经网络

课题名称:基于BP神经网络的人脸朝向识别分类 版本日期:2024-02-20 运行方式:直接运行BP0503.m文件 代码获取方式:私信博主或 QQ:491052175 模型描述: 采集到一组人脸朝向不同角度时的图像,图像来自不同…

17.材质和外观

1.图形学中的材质 在图形学中,材质(Material)是用来描述物体外观和表面特性的属性集合。它包含了控制光的反射、折射、吸收以及其他光学效果的信息,从而决定了物体在渲染过程中的外观。 渲染方程中那一项和材质有关? …

c#高级-正则表达式

正则表达式是由普通字符和元字符(特殊符号)组成的文字形式 应用场景 1.用于验证输入的邮箱是否合法。 2.用于验证输入的电话号码是否合法。 3.用于验证输入的身份证号码是否合法。等等 正则表达式常用的限定符总结: 几种常用的正则简写表达式…

[VNCTF2024]-Web:CheckIn解析

查看网页 一款很经典的游戏,而且是用js写的 在调试器里面我们可以看见,如果游戏通关的话,它会进行一系列操作,包括使用console.log(_0x3d9d[0]);输出_0x3d9d[0]到控制台,那我们就直接在点击在控制台求出它的值

架构面试题汇总(一)

目录 系统设计性能优化分布式系统安全性微服务架构数据库设计 系统设计 问题: 在设计高可用的电商系统时,你会考虑哪些关键因素来确保系统的可扩展性? 答案: 水平扩展与垂直扩展:设计系统时应考虑支持通过增加更多服…

C++ //练习 8.9 使用你为8.1.2节(第281页)第一个练习所编写的函数打印一个istringstream对象的内容。

C Primer(第5版) 练习 8.9 练习 8.9 使用你为8.1.2节(第281页)第一个练习所编写的函数打印一个istringstream对象的内容。 环境:Linux Ubuntu(云服务器) 工具:vim 代码块 /*****…

独立版表情包小程序完整版源码前后端源码,附带系统搭建教程

搭建要求: 1.系统要求Nginx 1.18.0PHP-7.2mysql5.6,开启 ssl,php需要安装 sg11 扩展 2.设置伪静态 location / { index index.php index.html index.htm; if (!-e $request_filename) { rewrite ^/(.*)$ /index.php?s$1; } } location /a…

容器镜像详解

1. 镜像组成 一个标准的OCI容器镜像由index, manifest, config, image layers这几个部分组成。 以docker镜像为例,下载的镜像文件保存在/var/lib/docker/目录下面 image/overlay2子目录下面保存着镜像相关的一些元数据 在下面的介绍主要以nginx:latest镜像为例子…

接口自动化测试用例如何设计

说到自动化测试,或者说接口自动化测试,多数人的第一反应是该用什么工具,比如:Python Requests、Java HttpClient、Apifox、MeterSphere、自研的自动化平台等。大家似乎更关注的是哪个工具更优秀,甚至出现“ 做平台的 &…

流计算之Flink

文章目录 概要有界无界流集群JobManagerTaskManagersTasks 和算子链Task Slots 和资源 小结 概要 Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模…

【微服务】mybatis typehandler使用详解

目录 一、前言 二、TypeHandler简介 2.1 什么是TypeHandler 2.1.1 TypeHandler特点 2.2 TypeHandler原理 2.3 mybatis自带的TypeHandler 三、环境准备 3.1 准备一张数据表 3.2 搭建一个springboot工程 3.2.1 基础依赖如下 3.2.2 核心配置文件 3.2.3 测试接口 四、T…

JAVA工程师面试专题-《Mysql》篇

目录 一、基础 1、mysql可以使用多少列创建索引? 2、mysql常用的存储引擎有哪些 3、MySQL 存储引擎,两者区别 4、mysql默认的隔离级别 5、数据库三范式 6、drop、delete 与 truncate 区别? 7、IN与EXISTS的区别 二、索引 1、索引及索…

odoo17彻底删除一个model

Odoo的ORM非常牛逼, 但是有一个缺点,就是删除一个模型的时候, 系统并不会帮我们从数据库中删除,然后重启odoo的时候就会报keyerror, 为了彻底从数据库中删除一个模型的数据,我整理了如下sql脚本&#xff1a…

暴雨服务器让数据中心变“绿”

近年来,随着数字经济的快速发展和信息技术的广泛应用,算力成为社会发展的重要支撑。我国算力总规模近5年年均增速近30%,达到每秒1.97万亿亿次浮点运算,位居全球第二。然而,传统算力方式往往伴随着高能耗、高…

接口测试实战--自动化测试流程

一、项目前期准备 常见项目软件架构: springMvc:tomcat里运行war包(在webapps目录下) springboot:java -jar xx.jar -xms(**) 运行参数 springCloud:k8s部署,使用kubectl create -f xx.yaml 接口自动化测试介入需越早越好,只要api定义好就可以编写自动化脚本; 某个…