Android N 中的 Java 8 特性 (Jack 编译器) 和 Kotlin 互操作性

98

更新 3. Kotlin 现已成为官方支持的Android开发语言。由Google提供。太棒了!

更新 2: 看起来 JetBrains真的致力于长期支持Kotlin用于Android。我是一个快乐的Kotlin用户:)。

更新: 来自JetBrains的Hadi Hariri提到他们将发布一些关于此主题的信息。一旦他们发布,我会更新这篇文章。


=== 下面是已废弃的内容 ===

Google刚刚发布了即将推出的Android N的预览版,其中有一些有趣的功能,最引人注目的是部分的Java 8语言支持。这得益于Google正在开发的新的Jack工具链

当前的工具链使用javackotlinc
javac.java --> .class)--> dx.class --> .dex
kotlinc.kt --> .class)--> dx.class --> .dex

新的Jack工具链:
Jack.java --> .jack --> .dex

我认为Google将向前推进,使Jack成为Android开发的默认工具链。

更新:Jack现在已被弃用。是的。
我的问题是,作为一个在Android开发中使用kotlin的用户,这个新的工具链将如何影响我的未来?我会“被困在过去”吗?

1
将 kotlin_library(multiple*.kt) 编译成 .jar 文件,然后使用 Jill 工具将其转换为 Jayce 格式。最后像导入其他(非 Android)的 plain java jars 一样,将其导入到 jack 中。 - Selvin
阅读文档:“您不必采取任何不同的操作来使用Jack - 只需使用标准的makefile命令编译树或项目即可。Jack是M版Android的默认构建工具链。”- 来源:https://source.android.com/source/jack.html,肯定是笔误,他们的意思是“N”而不是“M”吧? - Mark
杰克已经去世了,庆祝一下吧 :P - EpicPandaForce
8个回答

63

免责声明:我在Jack工作

这不会影响您。Kotlin编译器生成的是Java 6字节码,可以被Jack/Jill轻松导入。


7
你能分享一些关于这个的细节吗? :) - Tudor Luca
但是 Kotlin 能否从 Jack 的性能优化中受益呢?(至少有一天)因为 Jack 看起来非常棒(我现在迫不及待地想看一些基准测试结果)。 - NitroG42
我看过Proguard作者的基准测试视频演示,只需稍微搜索一下,您就能找到它。 - sakis kaliakoudas
@Lukas Bergstrom,您能否回答一下这个相关问题:https://dev59.com/vlsV5IYBdhLWcg3wpgRD - Markus Marvell
1
这是否意味着Jill不接受Java 8字节码?那库模块呢?如果它们被编译成.aar文件,然后被Jill导入,它们也无法使用Java 8吗?也就是说,这是否意味着Java的新特性仅适用于内部项目的.java源代码? - far.be
显示剩余2条评论

15

@Pavel Dudka

Jack是一个编译器,类似于javac,但它处理的事情略有不同:

enter image description here

正如你所看到的,Jack直接将Java源代码编译成Dex文件!我们不再需要中间的*.class文件,因此dx工具也不再需要!

但是等等!如果我在项目中包含第三方库(这些库作为一组.class文件提供),该怎么办?

这就是Jill发挥作用的时候了:

enter image description here

Jill可以处理类文件并将它们转换成特殊的Jayce格式,以便作为Jack编译器的输入。

那么现在我们暂停一秒钟思考一下......那些我们习惯使用的很酷的插件会发生什么呢?它们都需要.class文件,而Jack编译器不再具备这些文件...

幸运的是,Jack现在已经内置了我们需要的一些重要功能:

  • Retrolambda - 不再需要。Jack可以正确处理lambda表达式
  • Proguard - 现在已经内置到Jack中,因此您仍然可以使用混淆和代码最小化

优点:

Jack支持Java编程语言1.7,并集成了以下附加功能。

  • Predexing

    生成JACK库文件时,库的.dex文件被生成并存储在.jack库文件中作为预编译的.dex。在编译时,JACK会重复使用每个库的预编译.dex。所有库都已经预编译好了。

  • 增量编译

    增量编译意味着只重新编译自上次编译以来被修改及其依赖关系的组件。当更改仅限于一组有限的组件时,增量编译可以比完整编译快很多。

  • 重新打包

    JACK使用jarjar配置文件进行重新打包。

  • 多dex支持

    由于dex文件最多可以包含65K个方法,拥有超过65K个方法的应用程序必须分成多个dex文件。(有关multidex的更多信息,请参见“使用超过65K个方法构建应用程序”)。

缺点:

  • Jack不支持Transform API-没有中间的Java字节码可以修改,因此一些插件(我在这里没有提到)将停止工作。
  • Jack目前不支持注释处理,因此如果您严重依赖Dagger、AutoValue等库,那么在切换到Jack之前应该三思而后行。编辑:正如Jake Wharton所指出的,N预览版的Jack具有注释处理支持,但尚未通过Gradle公开。
  • 不支持以Java字节码级别操作的Lint检测器。
  • Jacoco不受支持-好吧,我个人认为Jacoco有问题(它并没有真正显示您想要看到的内容),所以完全可以没有它。
  • 目前不支持Proguard的企业版本Dexguard。

“Annotation processing is not currently supported by Jack”这个说法在2016年9月仍然有效吗?现在似乎已经支持了... - ticofab
它是被支持的,但仍然存在一些错误:例如数据绑定尚未工作:请参见android #210615 - TmTron
请注意,注解处理在Jack中并没有得到完全支持——它与Eclipse编译器处于相同的陈旧状态,因为Jack正是基于Eclipse编译器开发的(有几个方法被实现为占位符,当调用时抛出异常,而且还有许多未修复的错误已经被记录在ECJ Bugtracker上)。 - user1643723

7

更新(2017年3月16日)

幸运的是,Jack已经去世了,因此不会影响Kotlin开发人员。


如果Jack是未来,那么您将会在使用Kotlin时停留在过去。目前,Jack不支持编译非Java源代码为Dalvik字节码的插件。即使支持了,JetBrains也需要为Kotlin编译器添加新的后端,这是一项非常棘手的任务。因此,您将需要使用Jill来与Kotlin一起使用,而它将非常类似于您现在使用的工具链。
如下图所示,即使无法显式关闭Jack,您仍然可以将项目转换为库项目以使用Jill。应用程序项目将仅引用该库项目。

Jack and Jill Application Build

我唯一能想到的 Kotlin 与 Jack 协作的方式(可能不会被实现)是向 Kotlin 编译器添加一个 Java 后端,即生成类似 Xtend 的 Java 代码的后端。在这种情况下,由 Kotlin 编译器生成的代码可以像任何其他 Java 代码一样被 Jack 处理。

但目前我们不知道 Jack 发布时将支持什么。也许会有巨大变化,从而使得将 Kotlin 支持添加到 Jack 成为可能。


7
实际上,Kotlin团队计划支持Jack&Jill,我在他们的直播活动中听说过,但我更愿意在JetBrains官方发布帖子之后再回答这个问题,所以我没有回答。 - hotkey
那会很好,但我听说唯一的支持是通过Jill。正如我在答案中提到的,添加此支持的方法并不多。 - Michael
1
除了 Kotlin 团队之外,没有人应该说出他们能做什么或不能做什么,或者他们可能会做什么或不会做什么。他们之前已经谈论过这个问题,并且有计划可以呈现。 - Jayson Minard
不需要成为Kotlin团队的一员来猜测他们如何添加对新工具链的支持。考虑到该工具链是由另一家公司开发的,JB对其功能影响不大。 - Michael
将 .class 转换为 .dex 比编译器本身简单得多 - 我的意思是 javac/kotlin。IntelliJ IDEA 的开发人员可以双手绑在背后,蒙上眼睛也能完成这个任务。 - Alex Byrth
显示剩余2条评论

7
谷歌不会将Jack作为默认工具,而是使用Jack和Jill。 使用Jill编译.class文件到dex文件已经成为常态。否则,你就只能和jar/aar库说再见了。
至于Jack或Jill哪一个更慢还存在争议。安卓团队希望jack比当前的构建流程更快,但现在并不是这样的情况。
此外,Jack和Dex是开放的,没有任何阻止Kotlin团队从Kotlin源代码中写出发射.jack或.dex文件的工具。

5

正如今天的博客文章(Kotlin's Android Roadmap)中所述:

目前存在一些问题,导致Jack无法正确处理由Kotlin生成的字节码(196084203531),但我们计划与Google团队合作,要么解决这些问题,要么在我们这边提供解决方案。一旦完成,我们将能够在增量编译期间仅翻译更改的类文件,而不是每次都翻译所有类文件(这是旧版Android工具链中唯一可能的行为)

因此,Kotlin最终将支持Jack&Jill,并从中获得好处。


2
根据Google最新的公告 - 我们决定将Java 8语言特性直接添加到当前的javac和dx工具集中,并弃用Jack工具链。通过这个新方向,现有的依赖于Java类文件格式的工具和插件应该继续工作。未来,Android构建系统将本地支持Java 8语言特性。我们计划在未来几周内作为Android Studio的一部分推出这项服务,并希望与您早期分享这个决定。
我们最初通过Jack工具链测试添加Java 8支持。随着时间的推移,我们意识到当考虑到注释处理器、字节码分析器和重写器时,转换到Jack的成本对我们的社区来说太高了。感谢您尝试使用Jack工具链并给我们提供了很好的反馈。在我们发布新的支持之前,您可以继续使用Jack来构建您的Java 8代码。从Jack迁移应该需要很少或没有工作。
因此,我们不必担心jack工具链会成为Android开发的默认工具链。您可以继续使用kotlin或使用普通的javac / dx工具集。
来源:Android上Java 8语言特性支持的未来

1
我已经在 Kotlin 官方博客中找到了这篇文章:Kotlin 的 Android 路线图
在那里,您会发现一部分内容,其中提到:
下一步,我们计划改进 Android 构建性能,与 Android 的新 Jack 和 Jill 工具链 集成。目前存在一些问题,阻止 Jack 正确处理由 Kotlin 生成的字节码(196084203531),但我们计划与 Google 团队合作,解决这些问题或在我们这边提供解决方法。完成后,我们将能够仅使用 Jill 翻译已更改的类文件进行增量编译,而不是每次都翻译所有类文件(这是旧 Android 工具链中唯一可能的行为)。

正如@LukasBergstrom所说,"过去的困境"不会再成为问题;-)

您还可以查看与此主题相关的Reddit讨论: Kotlin和Jack以及Jill的现状是什么?

编程愉快。


0
根据Kotlin博客中发布的1.1-beta2新功能部分:

支持在启用Jack工具链(jackOptions { true })时构建Android项目;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接